From 8f0927099c72a4b6337c70de09ec5b19f14fe2b4 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Mon, 16 Mar 2026 13:02:35 +0000 Subject: [PATCH 1/2] Rename files for koenig-lexical TypeScript migration --- .../.storybook/{editorEmptyState.js => editorEmptyState.ts} | 0 packages/koenig-lexical/.storybook/{preview.jsx => preview.tsx} | 0 packages/koenig-lexical/demo/{DemoApp.jsx => DemoApp.tsx} | 0 .../demo/{HtmlOutputDemo.jsx => HtmlOutputDemo.tsx} | 0 .../demo/{RestrictedContentDemo.jsx => RestrictedContentDemo.tsx} | 0 .../demo/components/{DarkModeToggle.jsx => DarkModeToggle.tsx} | 0 .../components/{EmailEditorWrapper.jsx => EmailEditorWrapper.tsx} | 0 .../demo/components/{FloatingButton.jsx => FloatingButton.tsx} | 0 .../{InitialContentToggle.jsx => InitialContentToggle.tsx} | 0 .../demo/components/{Navigator.jsx => Navigator.tsx} | 0 .../{SerializedStateTextarea.jsx => SerializedStateTextarea.tsx} | 0 .../koenig-lexical/demo/components/{Sidebar.jsx => Sidebar.tsx} | 0 .../demo/components/{TitleTextBox.jsx => TitleTextBox.tsx} | 0 .../koenig-lexical/demo/components/{TreeView.jsx => TreeView.tsx} | 0 .../demo/components/{Watermark.jsx => Watermark.tsx} | 0 .../demo/components/{WordCount.jsx => WordCount.tsx} | 0 packages/koenig-lexical/demo/{demo.jsx => demo.tsx} | 0 .../koenig-lexical/demo/utils/{fetchEmbed.js => fetchEmbed.ts} | 0 packages/koenig-lexical/demo/utils/{gifConfig.js => gifConfig.ts} | 0 .../demo/utils/{unsplashConfig.js => unsplashConfig.ts} | 0 .../demo/utils/{useFileUpload.js => useFileUpload.ts} | 0 .../koenig-lexical/demo/utils/{useSnippets.js => useSnippets.ts} | 0 packages/koenig-lexical/{eslint.config.js => eslint.config.mjs} | 0 .../koenig-lexical/{playwright.config.js => playwright.config.ts} | 0 .../src/components/{DesignSandbox.jsx => DesignSandbox.tsx} | 0 .../src/components/{EmailEditor.jsx => EmailEditor.tsx} | 0 .../{KoenigCaptionEditor.jsx => KoenigCaptionEditor.tsx} | 0 .../components/{KoenigCardWrapper.jsx => KoenigCardWrapper.tsx} | 0 .../{KoenigComposableEditor.jsx => KoenigComposableEditor.tsx} | 0 .../src/components/{KoenigComposer.jsx => KoenigComposer.tsx} | 0 .../src/components/{KoenigEditor.jsx => KoenigEditor.tsx} | 0 .../{KoenigErrorBoundary.jsx => KoenigErrorBoundary.tsx} | 0 .../{KoenigNestedComposer.jsx => KoenigNestedComposer.tsx} | 0 .../components/{KoenigNestedEditor.jsx => KoenigNestedEditor.tsx} | 0 .../src/components/ui/{ActionToolbar.jsx => ActionToolbar.tsx} | 0 .../ui/{AtLinkResultsPopup.jsx => AtLinkResultsPopup.tsx} | 0 .../components/ui/{AudioUploadForm.jsx => AudioUploadForm.tsx} | 0 .../ui/{BackgroundImagePicker.jsx => BackgroundImagePicker.tsx} | 0 .../src/components/ui/{Button.stories.jsx => Button.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Button.jsx => Button.tsx} | 0 .../ui/{ButtonGroup.stories.jsx => ButtonGroup.stories.tsx} | 0 .../src/components/ui/{ButtonGroup.jsx => ButtonGroup.tsx} | 0 .../ui/{CardCaptionEditor.jsx => CardCaptionEditor.tsx} | 0 .../components/ui/{CardMenu.stories.jsx => CardMenu.stories.tsx} | 0 .../src/components/ui/{CardMenu.jsx => CardMenu.tsx} | 0 .../ui/{CardVisibilityMessage.jsx => CardVisibilityMessage.tsx} | 0 .../src/components/ui/{CardWrapper.jsx => CardWrapper.tsx} | 0 .../ui/{ColorOptionButtons.jsx => ColorOptionButtons.tsx} | 0 .../ui/{ColorPicker.stories.jsx => ColorPicker.stories.tsx} | 0 .../src/components/ui/{ColorPicker.jsx => ColorPicker.tsx} | 0 .../koenig-lexical/src/components/ui/{Delayed.jsx => Delayed.tsx} | 0 .../components/ui/{Dropdown.stories.jsx => Dropdown.stories.tsx} | 0 .../src/components/ui/{Dropdown.jsx => Dropdown.tsx} | 0 .../ui/{DropdownContainer.jsx => DropdownContainer.tsx} | 0 .../ui/{EditorPlaceholder.jsx => EditorPlaceholder.tsx} | 0 .../src/components/ui/{EmojiPicker.jsx => EmojiPicker.tsx} | 0 .../ui/{EmojiPickerPortal.jsx => EmojiPickerPortal.tsx} | 0 .../src/components/ui/{FileUploadForm.jsx => FileUploadForm.tsx} | 0 .../ui/{FloatingFormatToolbar.jsx => FloatingFormatToolbar.tsx} | 0 .../ui/{FloatingLinkToolbar.jsx => FloatingLinkToolbar.tsx} | 0 .../components/ui/{FloatingToolbar.jsx => FloatingToolbar.tsx} | 0 .../src/components/ui/{FormatToolbar.jsx => FormatToolbar.tsx} | 0 .../src/components/ui/{GifPlugin.jsx => GifPlugin.tsx} | 0 .../ui/{GifSelector.stories.jsx => GifSelector.stories.tsx} | 0 .../src/components/ui/{GifSelector.jsx => GifSelector.tsx} | 0 .../ui/{HighlightedString.jsx => HighlightedString.tsx} | 0 .../ui/{IconButton.stories.jsx => IconButton.stories.tsx} | 0 .../src/components/ui/{IconButton.jsx => IconButton.tsx} | 0 .../components/ui/{ImageUploadForm.jsx => ImageUploadForm.tsx} | 0 .../ui/{ImageUploadSwatch.jsx => ImageUploadSwatch.tsx} | 0 .../src/components/ui/{Input.stories.jsx => Input.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Input.jsx => Input.tsx} | 0 .../ui/{InputList.stories.jsx => InputList.stories.tsx} | 0 .../src/components/ui/{InputList.jsx => InputList.tsx} | 0 .../ui/{KeyboardSelection.jsx => KeyboardSelection.tsx} | 0 ...ardSelectionWithGroups.jsx => KeyboardSelectionWithGroups.tsx} | 0 .../ui/{LinkActionToolbar.jsx => LinkActionToolbar.tsx} | 0 ...ctionToolbarWithSearch.jsx => LinkActionToolbarWithSearch.tsx} | 0 .../ui/{LinkInput.stories.jsx => LinkInput.stories.tsx} | 0 .../src/components/ui/{LinkInput.jsx => LinkInput.tsx} | 0 .../ui/{LinkInputSearchItem.jsx => LinkInputSearchItem.tsx} | 0 ...nputWithSearch.stories.jsx => LinkInputWithSearch.stories.tsx} | 0 .../ui/{LinkInputWithSearch.jsx => LinkInputWithSearch.tsx} | 0 .../ui/{LinkToolbar.stories.jsx => LinkToolbar.stories.tsx} | 0 .../src/components/ui/{LinkToolbar.jsx => LinkToolbar.tsx} | 0 ...{MediaPlaceholder.stories.jsx => MediaPlaceholder.stories.tsx} | 0 .../components/ui/{MediaPlaceholder.jsx => MediaPlaceholder.tsx} | 0 .../ui/{MediaPlayer.stories.jsx => MediaPlayer.stories.tsx} | 0 .../src/components/ui/{MediaPlayer.jsx => MediaPlayer.tsx} | 0 .../src/components/ui/{MediaUploader.jsx => MediaUploader.tsx} | 0 .../src/components/ui/{Modal.stories.jsx => Modal.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Modal.jsx => Modal.tsx} | 0 .../ui/{MultiSelectDropdown.jsx => MultiSelectDropdown.tsx} | 0 .../components/ui/{PlusMenu.stories.jsx => PlusMenu.stories.tsx} | 0 .../src/components/ui/{PlusMenu.jsx => PlusMenu.tsx} | 0 .../koenig-lexical/src/components/ui/{Portal.jsx => Portal.tsx} | 0 .../ui/{ProgressBar.stories.jsx => ProgressBar.stories.tsx} | 0 .../src/components/ui/{ProgressBar.jsx => ProgressBar.tsx} | 0 .../components/ui/{ReadOnlyOverlay.jsx => ReadOnlyOverlay.tsx} | 0 .../ui/{SettingsPanel.stories.jsx => SettingsPanel.stories.tsx} | 0 .../src/components/ui/{SettingsPanel.jsx => SettingsPanel.tsx} | 0 .../src/components/ui/{SlashMenu.jsx => SlashMenu.tsx} | 0 .../src/components/ui/{Slider.stories.jsx => Slider.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Slider.jsx => Slider.tsx} | 0 .../ui/{SnippetActionToolbar.jsx => SnippetActionToolbar.tsx} | 0 .../ui/{SnippetInput.stories.jsx => SnippetInput.stories.tsx} | 0 .../src/components/ui/{SnippetInput.jsx => SnippetInput.tsx} | 0 .../src/components/ui/SnippetInput/{Dropdown.jsx => Dropdown.tsx} | 0 .../src/components/ui/SnippetInput/{Input.jsx => Input.tsx} | 0 .../koenig-lexical/src/components/ui/{Spinner.jsx => Spinner.tsx} | 0 .../ui/{SubscribeForm.stories.jsx => SubscribeForm.stories.tsx} | 0 .../src/components/ui/{SubscribeForm.jsx => SubscribeForm.tsx} | 0 .../koenig-lexical/src/components/ui/{TabView.jsx => TabView.tsx} | 0 .../src/components/ui/{TextInput.jsx => TextInput.tsx} | 0 .../src/components/ui/{Toggle.stories.jsx => Toggle.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Toggle.jsx => Toggle.tsx} | 0 .../ui/{ToolbarMenu.stories.jsx => ToolbarMenu.stories.tsx} | 0 .../src/components/ui/{ToolbarMenu.jsx => ToolbarMenu.tsx} | 0 .../{ToolbarMenuItem.stories.jsx => ToolbarMenuItem.stories.tsx} | 0 .../koenig-lexical/src/components/ui/{Tooltip.jsx => Tooltip.tsx} | 0 .../src/components/ui/{UnsplashPlugin.jsx => UnsplashPlugin.tsx} | 0 .../components/ui/{UrlInput.stories.jsx => UrlInput.stories.tsx} | 0 .../src/components/ui/{UrlInput.jsx => UrlInput.tsx} | 0 .../ui/{UrlSearchInput.stories.jsx => UrlSearchInput.stories.tsx} | 0 .../src/components/ui/{UrlSearchInput.jsx => UrlSearchInput.tsx} | 0 .../ui/{VisibilitySettings.jsx => VisibilitySettings.tsx} | 0 .../ui/cards/{AudioCard.stories.jsx => AudioCard.stories.tsx} | 0 .../src/components/ui/cards/{AudioCard.jsx => AudioCard.tsx} | 0 .../cards/{BookmarkCard.stories.jsx => BookmarkCard.stories.tsx} | 0 .../components/ui/cards/{BookmarkCard.jsx => BookmarkCard.tsx} | 0 .../ui/cards/{ButtonCard.stories.jsx => ButtonCard.stories.tsx} | 0 .../src/components/ui/cards/{ButtonCard.jsx => ButtonCard.tsx} | 0 ...{CallToActionCard.stories.jsx => CallToActionCard.stories.tsx} | 0 .../ui/cards/{CallToActionCard.jsx => CallToActionCard.tsx} | 0 .../ui/cards/{CalloutCard.stories.jsx => CalloutCard.stories.tsx} | 0 .../src/components/ui/cards/{CalloutCard.jsx => CalloutCard.tsx} | 0 .../{CodeBlockCard.stories.jsx => CodeBlockCard.stories.tsx} | 0 .../components/ui/cards/{CodeBlockCard.jsx => CodeBlockCard.tsx} | 0 .../ui/cards/{EmailCard.stories.jsx => EmailCard.stories.tsx} | 0 .../src/components/ui/cards/{EmailCard.jsx => EmailCard.tsx} | 0 .../cards/{EmailCtaCard.stories.jsx => EmailCtaCard.stories.tsx} | 0 .../components/ui/cards/{EmailCtaCard.jsx => EmailCtaCard.tsx} | 0 .../ui/cards/{EmbedCard.stories.jsx => EmbedCard.stories.tsx} | 0 .../src/components/ui/cards/{EmbedCard.jsx => EmbedCard.tsx} | 0 .../ui/cards/{FileCard.stories.jsx => FileCard.stories.tsx} | 0 .../src/components/ui/cards/{FileCard.jsx => FileCard.tsx} | 0 .../ui/cards/{GalleryCard.stories.jsx => GalleryCard.stories.tsx} | 0 .../src/components/ui/cards/{GalleryCard.jsx => GalleryCard.tsx} | 0 .../ui/cards/HeaderCard/v1/{HeaderCard.jsx => HeaderCard.tsx} | 0 .../v1/{HeaderCard.v1.stories.jsx => HeaderCard.v1.stories.tsx} | 0 .../ui/cards/HeaderCard/v2/{HeaderCard.jsx => HeaderCard.tsx} | 0 .../v2/{HeaderCard.v2.stories.jsx => HeaderCard.v2.stories.tsx} | 0 ...izontalRuleCard.stories.jsx => HorizontalRuleCard.stories.tsx} | 0 .../ui/cards/{HorizontalRuleCard.jsx => HorizontalRuleCard.tsx} | 0 .../ui/cards/{HtmlCard.stories.jsx => HtmlCard.stories.tsx} | 0 .../src/components/ui/cards/{HtmlCard.jsx => HtmlCard.tsx} | 0 .../ui/cards/HtmlCard/{HtmlEditor.jsx => HtmlEditor.tsx} | 0 .../ui/cards/{ImageCard.stories.jsx => ImageCard.stories.tsx} | 0 .../src/components/ui/cards/{ImageCard.jsx => ImageCard.tsx} | 0 .../cards/{MarkdownCard.stories.jsx => MarkdownCard.stories.tsx} | 0 .../components/ui/cards/{MarkdownCard.jsx => MarkdownCard.tsx} | 0 .../cards/MarkdownCard/{MarkdownEditor.jsx => MarkdownEditor.tsx} | 0 .../{MarkdownHelpDialog.jsx => MarkdownHelpDialog.tsx} | 0 .../{MarkdownImageUploader.jsx => MarkdownImageUploader.tsx} | 0 .../{useMarkdownImageUploader.js => useMarkdownImageUploader.ts} | 0 .../ui/cards/{PaywallCard.stories.jsx => PaywallCard.stories.tsx} | 0 .../src/components/ui/cards/{PaywallCard.jsx => PaywallCard.tsx} | 0 .../ui/cards/{ProductCard.stories.jsx => ProductCard.stories.tsx} | 0 .../src/components/ui/cards/{ProductCard.jsx => ProductCard.tsx} | 0 .../ProductCard/{ProductCardImage.jsx => ProductCardImage.tsx} | 0 .../ui/cards/ProductCard/{RatingButton.jsx => RatingButton.tsx} | 0 .../ui/cards/{SignupCard.stories.jsx => SignupCard.stories.tsx} | 0 .../src/components/ui/cards/{SignupCard.jsx => SignupCard.tsx} | 0 .../ui/cards/{ToggleCard.stories.jsx => ToggleCard.stories.tsx} | 0 .../src/components/ui/cards/{ToggleCard.jsx => ToggleCard.tsx} | 0 .../ui/cards/{TransistorCard.jsx => TransistorCard.tsx} | 0 .../ui/cards/{VideoCard.stories.jsx => VideoCard.stories.tsx} | 0 .../src/components/ui/cards/{VideoCard.jsx => VideoCard.tsx} | 0 .../src/components/ui/file-selectors/Gif/{Error.jsx => Error.tsx} | 0 .../src/components/ui/file-selectors/Gif/{Gif.jsx => Gif.tsx} | 0 .../components/ui/file-selectors/Gif/{Loader.jsx => Loader.tsx} | 0 .../Unsplash/{UnsplashButton.jsx => UnsplashButton.tsx} | 0 .../Unsplash/{UnsplashGallery.jsx => UnsplashGallery.tsx} | 0 .../Unsplash/{UnsplashImage.jsx => UnsplashImage.tsx} | 0 ...{UnsplashSelector.stories.jsx => UnsplashSelector.stories.tsx} | 0 .../Unsplash/{UnsplashSelector.jsx => UnsplashSelector.tsx} | 0 .../Unsplash/{UnsplashZoomed.jsx => UnsplashZoomed.tsx} | 0 .../ui/file-selectors/{UnsplashModal.jsx => UnsplashModal.tsx} | 0 .../src/context/{CardContext.jsx => CardContext.tsx} | 0 .../{KoenigComposerContext.jsx => KoenigComposerContext.tsx} | 0 ...oenigSelectedCardContext.jsx => KoenigSelectedCardContext.tsx} | 0 .../{SharedHistoryContext.jsx => SharedHistoryContext.tsx} | 0 .../{SharedOnChangeContext.jsx => SharedOnChangeContext.tsx} | 0 .../koenig-lexical/src/context/{TKContext.jsx => TKContext.tsx} | 0 .../src/hooks/{useCardDragAndDrop.js => useCardDragAndDrop.ts} | 0 .../src/hooks/{useClickOutside.js => useClickOutside.ts} | 0 .../src/hooks/{useFileDragAndDrop.js => useFileDragAndDrop.ts} | 0 .../src/hooks/{useGalleryReorder.js => useGalleryReorder.ts} | 0 .../src/hooks/{useInputSelection.js => useInputSelection.ts} | 0 .../src/hooks/{useKoenigTextEntity.js => useKoenigTextEntity.ts} | 0 .../koenig-lexical/src/hooks/{useMovable.js => useMovable.ts} | 0 .../src/hooks/{usePinturaEditor.js => usePinturaEditor.ts} | 0 .../src/hooks/{usePreviousFocus.js => usePreviousFocus.ts} | 0 .../src/hooks/{useSearchLinks.js => useSearchLinks.ts} | 0 ...seSettingsPanelReposition.js => useSettingsPanelReposition.ts} | 0 .../{useTypeaheadTriggerMatch.js => useTypeaheadTriggerMatch.ts} | 0 .../src/hooks/{useVisibilityToggle.js => useVisibilityToggle.ts} | 0 packages/koenig-lexical/src/{index.js => index.ts} | 0 packages/koenig-lexical/src/nodes/{AsideNode.js => AsideNode.ts} | 0 .../koenig-lexical/src/nodes/{AudioNode.jsx => AudioNode.tsx} | 0 .../src/nodes/{AudioNodeComponent.jsx => AudioNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{BasicNodes.js => BasicNodes.ts} | 0 .../src/nodes/{BookmarkNode.jsx => BookmarkNode.tsx} | 0 .../{BookmarkNodeComponent.jsx => BookmarkNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{ButtonNode.jsx => ButtonNode.tsx} | 0 .../nodes/{ButtonNodeComponent.jsx => ButtonNodeComponent.tsx} | 0 .../src/nodes/{CallToActionNode.jsx => CallToActionNode.tsx} | 0 ...allToActionNodeComponent.jsx => CallToActionNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{CalloutNode.jsx => CalloutNode.tsx} | 0 .../nodes/{CalloutNodeComponent.jsx => CalloutNodeComponent.tsx} | 0 .../src/nodes/{CodeBlockNode.jsx => CodeBlockNode.tsx} | 0 .../{CodeBlockNodeComponent.jsx => CodeBlockNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{DefaultNodes.js => DefaultNodes.ts} | 0 .../src/nodes/{EmailCtaNode.jsx => EmailCtaNode.tsx} | 0 .../{EmailCtaNodeComponent.jsx => EmailCtaNodeComponent.tsx} | 0 .../src/nodes/{EmailEditorNodes.js => EmailEditorNodes.ts} | 0 .../src/nodes/{EmailEmbedNode.jsx => EmailEmbedNode.tsx} | 0 .../koenig-lexical/src/nodes/{EmailNode.jsx => EmailNode.tsx} | 0 .../src/nodes/{EmailNodeComponent.jsx => EmailNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{EmailNodes.js => EmailNodes.ts} | 0 .../koenig-lexical/src/nodes/{EmbedNode.jsx => EmbedNode.tsx} | 0 .../src/nodes/{EmbedNodeComponent.jsx => EmbedNodeComponent.tsx} | 0 packages/koenig-lexical/src/nodes/{FileNode.jsx => FileNode.tsx} | 0 .../src/nodes/{FileNodeComponent.jsx => FileNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{GalleryNode.jsx => GalleryNode.tsx} | 0 .../nodes/{GalleryNodeComponent.jsx => GalleryNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{HeaderNode.jsx => HeaderNode.tsx} | 0 .../src/nodes/{HorizontalRuleNode.jsx => HorizontalRuleNode.tsx} | 0 packages/koenig-lexical/src/nodes/{HtmlNode.jsx => HtmlNode.tsx} | 0 .../src/nodes/{HtmlNodeComponent.jsx => HtmlNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{ImageNode.jsx => ImageNode.tsx} | 0 .../src/nodes/{ImageNodeComponent.jsx => ImageNodeComponent.tsx} | 0 .../src/nodes/{MarkdownNode.jsx => MarkdownNode.tsx} | 0 .../{MarkdownNodeComponent.jsx => MarkdownNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{MinimalNodes.js => MinimalNodes.ts} | 0 .../koenig-lexical/src/nodes/{PaywallNode.jsx => PaywallNode.tsx} | 0 .../koenig-lexical/src/nodes/{ProductNode.jsx => ProductNode.tsx} | 0 .../nodes/{ProductNodeComponent.jsx => ProductNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{SignupNode.jsx => SignupNode.tsx} | 0 .../nodes/{SignupNodeComponent.jsx => SignupNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{ToggleNode.jsx => ToggleNode.tsx} | 0 .../nodes/{ToggleNodeComponent.jsx => ToggleNodeComponent.tsx} | 0 .../src/nodes/{TransistorNode.jsx => TransistorNode.tsx} | 0 .../{TransistorNodeComponent.jsx => TransistorNodeComponent.tsx} | 0 .../koenig-lexical/src/nodes/{VideoNode.jsx => VideoNode.tsx} | 0 .../src/nodes/{VideoNodeComponent.jsx => VideoNodeComponent.tsx} | 0 .../v1/{HeaderNodeComponent.jsx => HeaderNodeComponent.tsx} | 0 .../v2/{HeaderNodeComponent.jsx => HeaderNodeComponent.tsx} | 0 .../src/plugins/{AllDefaultPlugins.jsx => AllDefaultPlugins.tsx} | 0 .../src/plugins/{AtLinkPlugin.jsx => AtLinkPlugin.tsx} | 0 .../src/plugins/{AudioPlugin.jsx => AudioPlugin.tsx} | 0 .../src/plugins/{BookmarkPlugin.jsx => BookmarkPlugin.tsx} | 0 .../src/plugins/{ButtonPlugin.jsx => ButtonPlugin.tsx} | 0 .../plugins/{CallToActionPlugin.jsx => CallToActionPlugin.tsx} | 0 .../src/plugins/{CalloutPlugin.jsx => CalloutPlugin.tsx} | 0 .../src/plugins/{CardMenuPlugin.jsx => CardMenuPlugin.tsx} | 0 .../plugins/{DragDropPastePlugin.jsx => DragDropPastePlugin.tsx} | 0 .../{DragDropReorderPlugin.jsx => DragDropReorderPlugin.tsx} | 0 .../src/plugins/{EmEnDashPlugin.jsx => EmEnDashPlugin.tsx} | 0 .../src/plugins/{EmailCtaPlugin.jsx => EmailCtaPlugin.tsx} | 0 .../src/plugins/{EmailPlugin.jsx => EmailPlugin.tsx} | 0 .../src/plugins/{EmbedPlugin.jsx => EmbedPlugin.tsx} | 0 .../src/plugins/{EmojiPickerPlugin.jsx => EmojiPickerPlugin.tsx} | 0 .../{ExternalControlPlugin.jsx => ExternalControlPlugin.tsx} | 0 .../koenig-lexical/src/plugins/{FilePlugin.jsx => FilePlugin.tsx} | 0 .../{FloatingToolbarPlugin.jsx => FloatingToolbarPlugin.tsx} | 0 .../src/plugins/{GalleryPlugin.jsx => GalleryPlugin.tsx} | 0 .../src/plugins/{HeaderPlugin.jsx => HeaderPlugin.tsx} | 0 .../{HorizontalRulePlugin.jsx => HorizontalRulePlugin.tsx} | 0 .../src/plugins/{HtmlOutputPlugin.jsx => HtmlOutputPlugin.tsx} | 0 .../koenig-lexical/src/plugins/{HtmlPlugin.jsx => HtmlPlugin.tsx} | 0 .../src/plugins/{ImagePlugin.jsx => ImagePlugin.tsx} | 0 .../{KoenigBehaviourPlugin.jsx => KoenigBehaviourPlugin.tsx} | 0 .../src/plugins/{KoenigBlurPlugin.jsx => KoenigBlurPlugin.tsx} | 0 .../src/plugins/{KoenigFocusPlugin.jsx => KoenigFocusPlugin.tsx} | 0 ...{KoenigNestedEditorPlugin.jsx => KoenigNestedEditorPlugin.tsx} | 0 .../{KoenigSelectorPlugin.jsx => KoenigSelectorPlugin.tsx} | 0 .../plugins/{KoenigSnippetPlugin.jsx => KoenigSnippetPlugin.tsx} | 0 .../plugins/{MarkdownPastePlugin.jsx => MarkdownPastePlugin.tsx} | 0 .../src/plugins/{MarkdownPlugin.jsx => MarkdownPlugin.tsx} | 0 .../{MarkdownShortcutPlugin.jsx => MarkdownShortcutPlugin.tsx} | 0 .../src/plugins/{PaywallPlugin.jsx => PaywallPlugin.tsx} | 0 .../plugins/{PlusCardMenuPlugin.jsx => PlusCardMenuPlugin.tsx} | 0 .../src/plugins/{ProductPlugin.jsx => ProductPlugin.tsx} | 0 ...{ReplacementStringsPlugin.jsx => ReplacementStringsPlugin.tsx} | 0 .../{RestrictContentPlugin.jsx => RestrictContentPlugin.tsx} | 0 .../src/plugins/{SignupPlugin.jsx => SignupPlugin.tsx} | 0 .../plugins/{SlashCardMenuPlugin.jsx => SlashCardMenuPlugin.tsx} | 0 .../src/plugins/{TKCountPlugin.jsx => TKCountPlugin.tsx} | 0 .../koenig-lexical/src/plugins/{TKPlugin.jsx => TKPlugin.tsx} | 0 .../src/plugins/{TogglePlugin.jsx => TogglePlugin.tsx} | 0 .../src/plugins/{TransistorPlugin.jsx => TransistorPlugin.tsx} | 0 .../src/plugins/{VideoPlugin.jsx => VideoPlugin.tsx} | 0 .../src/plugins/{WordCountPlugin.jsx => WordCountPlugin.tsx} | 0 packages/koenig-lexical/src/themes/{default.js => default.ts} | 0 .../{$getSelectionRangeRect.js => $getSelectionRangeRect.ts} | 0 .../utils/{$insertAndSelectNode.js => $insertAndSelectNode.ts} | 0 .../utils/{$isAtStartOfDocument.js => $isAtStartOfDocument.ts} | 0 .../src/utils/{$isAtTopOfNode.js => $isAtTopOfNode.ts} | 0 .../utils/{$selectDecoratorNode.js => $selectDecoratorNode.ts} | 0 packages/koenig-lexical/src/utils/{analytics.js => analytics.ts} | 0 .../src/utils/{audioUploadHandler.js => audioUploadHandler.ts} | 0 .../src/utils/{autoExpandTextArea.js => autoExpandTextArea.ts} | 0 .../src/utils/{buildCardMenu.js => buildCardMenu.ts} | 0 .../src/utils/{callToActionColors.js => callToActionColors.ts} | 0 .../src/utils/{codemirror-config.js => codemirror-config.ts} | 0 packages/koenig-lexical/src/utils/{constants.js => constants.ts} | 0 packages/koenig-lexical/src/utils/{ctrlOrCmd.js => ctrlOrCmd.ts} | 0 .../src/utils/{dataSrcToFile.js => dataSrcToFile.ts} | 0 .../draggable/{DragDropContainer.js => DragDropContainer.ts} | 0 .../utils/draggable/{DragDropHandler.jsx => DragDropHandler.tsx} | 0 .../src/utils/draggable/{ScrollHandler.js => ScrollHandler.ts} | 0 .../draggable/{draggable-constants.js => draggable-constants.ts} | 0 .../utils/draggable/{draggable-utils.js => draggable-utils.ts} | 0 .../utils/{extractVideoMetadata.js => extractVideoMetadata.ts} | 0 .../src/utils/{fileUploadHandler.js => fileUploadHandler.ts} | 0 .../src/utils/{generateEditorState.js => generateEditorState.ts} | 0 .../src/utils/{getAccentColor.js => getAccentColor.ts} | 0 .../src/utils/{getAudioMetadata.js => getAudioMetadata.ts} | 0 .../src/utils/{getDOMRangeRect.js => getDOMRangeRect.ts} | 0 .../src/utils/{getEditorCardNodes.js => getEditorCardNodes.ts} | 0 .../src/utils/{getImageDimensions.js => getImageDimensions.ts} | 0 .../{getImageFilenameFromSrc.js => getImageFilenameFromSrc.ts} | 0 .../src/utils/{getScrollParent.js => getScrollParent.ts} | 0 .../src/utils/{getSelectedNode.js => getSelectedNode.ts} | 0 .../{getTopLevelNativeElement.js => getTopLevelNativeElement.ts} | 0 .../src/utils/{image-card-widths.js => image-card-widths.ts} | 0 .../src/utils/{imageUploadHandler.js => imageUploadHandler.ts} | 0 packages/koenig-lexical/src/utils/{index.js => index.ts} | 0 .../src/utils/{isEditorEmpty.js => isEditorEmpty.ts} | 0 packages/koenig-lexical/src/utils/{isGif.js => isGif.ts} | 0 .../src/utils/{isInternalUrl.js => isInternalUrl.ts} | 0 .../src/utils/{nested-editors.js => nested-editors.ts} | 0 .../src/utils/{openFileSelection.js => openFileSelection.ts} | 0 .../src/utils/{prettifyFileName.js => prettifyFileName.ts} | 0 .../src/utils/{sanitize-html.js => sanitize-html.ts} | 0 packages/koenig-lexical/src/utils/services/{gif.js => gif.ts} | 0 .../{setFloatingElemPosition.js => setFloatingElemPosition.ts} | 0 .../src/utils/{shortcutSymbols.js => shortcutSymbols.ts} | 0 .../src/utils/{shouldIgnoreEvent.js => shouldIgnoreEvent.ts} | 0 ...{populate-storybook-editor.js => populate-storybook-editor.ts} | 0 .../{thumbnailUploadHandler.js => thumbnailUploadHandler.ts} | 0 .../koenig-lexical/src/utils/{visibility.js => visibility.ts} | 0 packages/koenig-lexical/{svgo.config.js => svgo.config.cjs} | 0 .../test/e2e/{card-behaviour.test.js => card-behaviour.test.ts} | 0 .../test/e2e/cards/{audio-card.test.js => audio-card.test.ts} | 0 ...card-with-search.test.js => bookmark-card-with-search.test.ts} | 0 ...ithout-search.test.js => bookmark-card-without-search.test.ts} | 0 .../test/e2e/cards/{button-card.test.js => button-card.test.ts} | 0 .../{call-to-action-card.test.js => call-to-action-card.test.ts} | 0 .../test/e2e/cards/{callout-card.test.js => callout-card.test.ts} | 0 .../cards/{code-block-card.test.js => code-block-card.test.ts} | 0 .../test/e2e/cards/{email-card.test.js => email-card.test.ts} | 0 .../e2e/cards/{email-cta-card.test.js => email-cta-card.test.ts} | 0 .../test/e2e/cards/{embed-card.test.js => embed-card.test.ts} | 0 .../test/e2e/cards/{file-card.test.js => file-card.test.ts} | 0 .../test/e2e/cards/{gallery-card.test.js => gallery-card.test.ts} | 0 .../test/e2e/cards/{header-card.test.js => header-card.test.ts} | 0 .../test/e2e/cards/{html-card.test.js => html-card.test.ts} | 0 .../test/e2e/cards/{image-card.test.js => image-card.test.ts} | 0 .../e2e/cards/{markdown-card.test.js => markdown-card.test.ts} | 0 .../test/e2e/cards/{paywall-card.test.js => paywall-card.test.ts} | 0 .../test/e2e/cards/{product-card.test.js => product-card.test.ts} | 0 .../test/e2e/cards/{signup-card.test.js => signup-card.test.ts} | 0 .../test/e2e/cards/{toggle-card.test.js => toggle-card.test.ts} | 0 .../cards/{transistor-card.test.js => transistor-card.test.ts} | 0 .../{video-card.firefox.test.js => video-card.firefox.test.ts} | 0 .../{content-visibility.test.js => content-visibility.test.ts} | 0 .../e2e/editors/{basic-editor.test.js => basic-editor.test.ts} | 0 .../e2e/editors/{email-editor.test.js => email-editor.test.ts} | 0 .../editors/{minimal-editor.test.js => minimal-editor.test.ts} | 0 .../e2e/{floating-toolbar.test.js => floating-toolbar.test.ts} | 0 .../e2e/{format-shortcuts.test.js => format-shortcuts.test.ts} | 0 .../koenig-lexical/test/e2e/{linking.test.js => linking.test.ts} | 0 .../test/e2e/{list-behaviour.test.js => list-behaviour.test.ts} | 0 .../modals/{UnsplashSelector.test.js => UnsplashSelector.test.ts} | 0 .../test/e2e/{node-transforms.test.js => node-transforms.test.ts} | 0 .../test/e2e/{paste-behaviour.test.js => paste-behaviour.test.ts} | 0 ...Plugin.firefox.test.js => DragDropPastePlugin.firefox.test.ts} | 0 .../{DragDropPastePlugin.test.js => DragDropPastePlugin.test.ts} | 0 ...ragDropReorderPlugin.test.js => DragDropReorderPlugin.test.ts} | 0 .../{EmojiPickerPlugin.test.js => EmojiPickerPlugin.test.ts} | 0 .../{HtmlOutputPlugin.test.js => HtmlOutputPlugin.test.ts} | 0 .../{KoenigSnippetPlugin.test.js => KoenigSnippetPlugin.test.ts} | 0 ...mentStringsPlugin.test.js => ReplacementStringsPlugin.test.ts} | 0 ...estrictContentPlugin.test.js => RestrictContentPlugin.test.ts} | 0 .../test/e2e/plugins/{TKPlugin.test.js => TKPlugin.test.ts} | 0 .../plugins/{WordCountPlugin.test.js => WordCountPlugin.test.ts} | 0 .../test/e2e/{plus-button.test.js => plus-button.test.ts} | 0 .../test/e2e/{selection.test.js => selection.test.ts} | 0 .../test/e2e/{slash-menu.test.js => slash-menu.test.ts} | 0 .../text-transforms/{code-block.test.js => code-block.test.ts} | 0 .../{emdash-endash.test.js => emdash-endash.test.ts} | 0 .../e2e/text-transforms/{headings.test.js => headings.test.ts} | 0 ...{horizontal-line-rule.test.js => horizontal-line-rule.test.ts} | 0 .../test/e2e/text-transforms/{links.test.js => links.test.ts} | 0 .../e2e/text-transforms/{markdown.test.js => markdown.test.ts} | 0 .../test/e2e/text-transforms/{paywall.test.js => paywall.test.ts} | 0 .../test/e2e/{title-behaviour.test.js => title-behaviour.test.ts} | 0 .../{getImageDimensions.test.js => getImageDimensions.test.ts} | 0 packages/koenig-lexical/test/{test-setup.js => test-setup.ts} | 0 .../test/unit/{EmailEditor.test.js => EmailEditor.test.ts} | 0 .../unit/{KoenigComposer.test.jsx => KoenigComposer.test.tsx} | 0 .../test/unit/{build-output.test.js => build-output.test.ts} | 0 .../test/unit/{buildCardMenu.test.js => buildCardMenu.test.ts} | 0 .../test/unit/{headerCardv2.test.js => headerCardv2.test.ts} | 0 .../{useVisibilityToggle.test.js => useVisibilityToggle.test.ts} | 0 .../test/unit/{productCard.test.js => productCard.test.ts} | 0 .../test/unit/{signupCard.test.js => signupCard.test.ts} | 0 .../test/unit/{toggleCard.test.js => toggleCard.test.ts} | 0 .../{generateEditorState.test.js => generateEditorState.test.ts} | 0 .../unit/utils/{gif-provider.test.js => gif-provider.test.ts} | 0 .../{image-card-widths.test.js => image-card-widths.test.ts} | 0 .../unit/utils/{sanitize-html.test.js => sanitize-html.test.ts} | 0 .../test/unit/utils/{visibility.test.js => visibility.test.ts} | 0 .../test/utils/{color-select-helper.js => color-select-helper.ts} | 0 packages/koenig-lexical/test/utils/{e2e.js => e2e.ts} | 0 packages/koenig-lexical/test/utils/{isTestEnv.js => isTestEnv.ts} | 0 .../koenig-lexical/{vite.config.demo.js => vite.config.demo.ts} | 0 packages/koenig-lexical/{vite.config.js => vite.config.ts} | 0 430 files changed, 0 insertions(+), 0 deletions(-) rename packages/koenig-lexical/.storybook/{editorEmptyState.js => editorEmptyState.ts} (100%) rename packages/koenig-lexical/.storybook/{preview.jsx => preview.tsx} (100%) rename packages/koenig-lexical/demo/{DemoApp.jsx => DemoApp.tsx} (100%) rename packages/koenig-lexical/demo/{HtmlOutputDemo.jsx => HtmlOutputDemo.tsx} (100%) rename packages/koenig-lexical/demo/{RestrictedContentDemo.jsx => RestrictedContentDemo.tsx} (100%) rename packages/koenig-lexical/demo/components/{DarkModeToggle.jsx => DarkModeToggle.tsx} (100%) rename packages/koenig-lexical/demo/components/{EmailEditorWrapper.jsx => EmailEditorWrapper.tsx} (100%) rename packages/koenig-lexical/demo/components/{FloatingButton.jsx => FloatingButton.tsx} (100%) rename packages/koenig-lexical/demo/components/{InitialContentToggle.jsx => InitialContentToggle.tsx} (100%) rename packages/koenig-lexical/demo/components/{Navigator.jsx => Navigator.tsx} (100%) rename packages/koenig-lexical/demo/components/{SerializedStateTextarea.jsx => SerializedStateTextarea.tsx} (100%) rename packages/koenig-lexical/demo/components/{Sidebar.jsx => Sidebar.tsx} (100%) rename packages/koenig-lexical/demo/components/{TitleTextBox.jsx => TitleTextBox.tsx} (100%) rename packages/koenig-lexical/demo/components/{TreeView.jsx => TreeView.tsx} (100%) rename packages/koenig-lexical/demo/components/{Watermark.jsx => Watermark.tsx} (100%) rename packages/koenig-lexical/demo/components/{WordCount.jsx => WordCount.tsx} (100%) rename packages/koenig-lexical/demo/{demo.jsx => demo.tsx} (100%) rename packages/koenig-lexical/demo/utils/{fetchEmbed.js => fetchEmbed.ts} (100%) rename packages/koenig-lexical/demo/utils/{gifConfig.js => gifConfig.ts} (100%) rename packages/koenig-lexical/demo/utils/{unsplashConfig.js => unsplashConfig.ts} (100%) rename packages/koenig-lexical/demo/utils/{useFileUpload.js => useFileUpload.ts} (100%) rename packages/koenig-lexical/demo/utils/{useSnippets.js => useSnippets.ts} (100%) rename packages/koenig-lexical/{eslint.config.js => eslint.config.mjs} (100%) rename packages/koenig-lexical/{playwright.config.js => playwright.config.ts} (100%) rename packages/koenig-lexical/src/components/{DesignSandbox.jsx => DesignSandbox.tsx} (100%) rename packages/koenig-lexical/src/components/{EmailEditor.jsx => EmailEditor.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigCaptionEditor.jsx => KoenigCaptionEditor.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigCardWrapper.jsx => KoenigCardWrapper.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigComposableEditor.jsx => KoenigComposableEditor.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigComposer.jsx => KoenigComposer.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigEditor.jsx => KoenigEditor.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigErrorBoundary.jsx => KoenigErrorBoundary.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigNestedComposer.jsx => KoenigNestedComposer.tsx} (100%) rename packages/koenig-lexical/src/components/{KoenigNestedEditor.jsx => KoenigNestedEditor.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ActionToolbar.jsx => ActionToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{AtLinkResultsPopup.jsx => AtLinkResultsPopup.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{AudioUploadForm.jsx => AudioUploadForm.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{BackgroundImagePicker.jsx => BackgroundImagePicker.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Button.stories.jsx => Button.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Button.jsx => Button.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ButtonGroup.stories.jsx => ButtonGroup.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ButtonGroup.jsx => ButtonGroup.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{CardCaptionEditor.jsx => CardCaptionEditor.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{CardMenu.stories.jsx => CardMenu.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{CardMenu.jsx => CardMenu.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{CardVisibilityMessage.jsx => CardVisibilityMessage.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{CardWrapper.jsx => CardWrapper.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ColorOptionButtons.jsx => ColorOptionButtons.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ColorPicker.stories.jsx => ColorPicker.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ColorPicker.jsx => ColorPicker.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Delayed.jsx => Delayed.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Dropdown.stories.jsx => Dropdown.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Dropdown.jsx => Dropdown.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{DropdownContainer.jsx => DropdownContainer.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{EditorPlaceholder.jsx => EditorPlaceholder.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{EmojiPicker.jsx => EmojiPicker.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{EmojiPickerPortal.jsx => EmojiPickerPortal.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{FileUploadForm.jsx => FileUploadForm.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{FloatingFormatToolbar.jsx => FloatingFormatToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{FloatingLinkToolbar.jsx => FloatingLinkToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{FloatingToolbar.jsx => FloatingToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{FormatToolbar.jsx => FormatToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{GifPlugin.jsx => GifPlugin.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{GifSelector.stories.jsx => GifSelector.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{GifSelector.jsx => GifSelector.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{HighlightedString.jsx => HighlightedString.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{IconButton.stories.jsx => IconButton.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{IconButton.jsx => IconButton.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ImageUploadForm.jsx => ImageUploadForm.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ImageUploadSwatch.jsx => ImageUploadSwatch.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Input.stories.jsx => Input.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Input.jsx => Input.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{InputList.stories.jsx => InputList.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{InputList.jsx => InputList.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{KeyboardSelection.jsx => KeyboardSelection.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{KeyboardSelectionWithGroups.jsx => KeyboardSelectionWithGroups.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkActionToolbar.jsx => LinkActionToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkActionToolbarWithSearch.jsx => LinkActionToolbarWithSearch.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkInput.stories.jsx => LinkInput.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkInput.jsx => LinkInput.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkInputSearchItem.jsx => LinkInputSearchItem.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkInputWithSearch.stories.jsx => LinkInputWithSearch.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkInputWithSearch.jsx => LinkInputWithSearch.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkToolbar.stories.jsx => LinkToolbar.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{LinkToolbar.jsx => LinkToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MediaPlaceholder.stories.jsx => MediaPlaceholder.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MediaPlaceholder.jsx => MediaPlaceholder.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MediaPlayer.stories.jsx => MediaPlayer.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MediaPlayer.jsx => MediaPlayer.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MediaUploader.jsx => MediaUploader.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Modal.stories.jsx => Modal.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Modal.jsx => Modal.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{MultiSelectDropdown.jsx => MultiSelectDropdown.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{PlusMenu.stories.jsx => PlusMenu.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{PlusMenu.jsx => PlusMenu.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Portal.jsx => Portal.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ProgressBar.stories.jsx => ProgressBar.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ProgressBar.jsx => ProgressBar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ReadOnlyOverlay.jsx => ReadOnlyOverlay.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SettingsPanel.stories.jsx => SettingsPanel.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SettingsPanel.jsx => SettingsPanel.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SlashMenu.jsx => SlashMenu.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Slider.stories.jsx => Slider.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Slider.jsx => Slider.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SnippetActionToolbar.jsx => SnippetActionToolbar.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SnippetInput.stories.jsx => SnippetInput.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SnippetInput.jsx => SnippetInput.tsx} (100%) rename packages/koenig-lexical/src/components/ui/SnippetInput/{Dropdown.jsx => Dropdown.tsx} (100%) rename packages/koenig-lexical/src/components/ui/SnippetInput/{Input.jsx => Input.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Spinner.jsx => Spinner.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SubscribeForm.stories.jsx => SubscribeForm.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{SubscribeForm.jsx => SubscribeForm.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{TabView.jsx => TabView.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{TextInput.jsx => TextInput.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Toggle.stories.jsx => Toggle.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Toggle.jsx => Toggle.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ToolbarMenu.stories.jsx => ToolbarMenu.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ToolbarMenu.jsx => ToolbarMenu.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{ToolbarMenuItem.stories.jsx => ToolbarMenuItem.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{Tooltip.jsx => Tooltip.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{UnsplashPlugin.jsx => UnsplashPlugin.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{UrlInput.stories.jsx => UrlInput.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{UrlInput.jsx => UrlInput.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{UrlSearchInput.stories.jsx => UrlSearchInput.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{UrlSearchInput.jsx => UrlSearchInput.tsx} (100%) rename packages/koenig-lexical/src/components/ui/{VisibilitySettings.jsx => VisibilitySettings.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{AudioCard.stories.jsx => AudioCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{AudioCard.jsx => AudioCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{BookmarkCard.stories.jsx => BookmarkCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{BookmarkCard.jsx => BookmarkCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ButtonCard.stories.jsx => ButtonCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ButtonCard.jsx => ButtonCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CallToActionCard.stories.jsx => CallToActionCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CallToActionCard.jsx => CallToActionCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CalloutCard.stories.jsx => CalloutCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CalloutCard.jsx => CalloutCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CodeBlockCard.stories.jsx => CodeBlockCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{CodeBlockCard.jsx => CodeBlockCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmailCard.stories.jsx => EmailCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmailCard.jsx => EmailCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmailCtaCard.stories.jsx => EmailCtaCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmailCtaCard.jsx => EmailCtaCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmbedCard.stories.jsx => EmbedCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{EmbedCard.jsx => EmbedCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{FileCard.stories.jsx => FileCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{FileCard.jsx => FileCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{GalleryCard.stories.jsx => GalleryCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{GalleryCard.jsx => GalleryCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/{HeaderCard.jsx => HeaderCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/{HeaderCard.v1.stories.jsx => HeaderCard.v1.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/{HeaderCard.jsx => HeaderCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/{HeaderCard.v2.stories.jsx => HeaderCard.v2.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{HorizontalRuleCard.stories.jsx => HorizontalRuleCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{HorizontalRuleCard.jsx => HorizontalRuleCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{HtmlCard.stories.jsx => HtmlCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{HtmlCard.jsx => HtmlCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/HtmlCard/{HtmlEditor.jsx => HtmlEditor.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ImageCard.stories.jsx => ImageCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ImageCard.jsx => ImageCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{MarkdownCard.stories.jsx => MarkdownCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{MarkdownCard.jsx => MarkdownCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/MarkdownCard/{MarkdownEditor.jsx => MarkdownEditor.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/MarkdownCard/{MarkdownHelpDialog.jsx => MarkdownHelpDialog.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/MarkdownCard/{MarkdownImageUploader.jsx => MarkdownImageUploader.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/MarkdownCard/{useMarkdownImageUploader.js => useMarkdownImageUploader.ts} (100%) rename packages/koenig-lexical/src/components/ui/cards/{PaywallCard.stories.jsx => PaywallCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{PaywallCard.jsx => PaywallCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ProductCard.stories.jsx => ProductCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ProductCard.jsx => ProductCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/ProductCard/{ProductCardImage.jsx => ProductCardImage.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/ProductCard/{RatingButton.jsx => RatingButton.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{SignupCard.stories.jsx => SignupCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{SignupCard.jsx => SignupCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ToggleCard.stories.jsx => ToggleCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{ToggleCard.jsx => ToggleCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{TransistorCard.jsx => TransistorCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{VideoCard.stories.jsx => VideoCard.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/cards/{VideoCard.jsx => VideoCard.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Gif/{Error.jsx => Error.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Gif/{Gif.jsx => Gif.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Gif/{Loader.jsx => Loader.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashButton.jsx => UnsplashButton.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashGallery.jsx => UnsplashGallery.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashImage.jsx => UnsplashImage.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashSelector.stories.jsx => UnsplashSelector.stories.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashSelector.jsx => UnsplashSelector.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/{UnsplashZoomed.jsx => UnsplashZoomed.tsx} (100%) rename packages/koenig-lexical/src/components/ui/file-selectors/{UnsplashModal.jsx => UnsplashModal.tsx} (100%) rename packages/koenig-lexical/src/context/{CardContext.jsx => CardContext.tsx} (100%) rename packages/koenig-lexical/src/context/{KoenigComposerContext.jsx => KoenigComposerContext.tsx} (100%) rename packages/koenig-lexical/src/context/{KoenigSelectedCardContext.jsx => KoenigSelectedCardContext.tsx} (100%) rename packages/koenig-lexical/src/context/{SharedHistoryContext.jsx => SharedHistoryContext.tsx} (100%) rename packages/koenig-lexical/src/context/{SharedOnChangeContext.jsx => SharedOnChangeContext.tsx} (100%) rename packages/koenig-lexical/src/context/{TKContext.jsx => TKContext.tsx} (100%) rename packages/koenig-lexical/src/hooks/{useCardDragAndDrop.js => useCardDragAndDrop.ts} (100%) rename packages/koenig-lexical/src/hooks/{useClickOutside.js => useClickOutside.ts} (100%) rename packages/koenig-lexical/src/hooks/{useFileDragAndDrop.js => useFileDragAndDrop.ts} (100%) rename packages/koenig-lexical/src/hooks/{useGalleryReorder.js => useGalleryReorder.ts} (100%) rename packages/koenig-lexical/src/hooks/{useInputSelection.js => useInputSelection.ts} (100%) rename packages/koenig-lexical/src/hooks/{useKoenigTextEntity.js => useKoenigTextEntity.ts} (100%) rename packages/koenig-lexical/src/hooks/{useMovable.js => useMovable.ts} (100%) rename packages/koenig-lexical/src/hooks/{usePinturaEditor.js => usePinturaEditor.ts} (100%) rename packages/koenig-lexical/src/hooks/{usePreviousFocus.js => usePreviousFocus.ts} (100%) rename packages/koenig-lexical/src/hooks/{useSearchLinks.js => useSearchLinks.ts} (100%) rename packages/koenig-lexical/src/hooks/{useSettingsPanelReposition.js => useSettingsPanelReposition.ts} (100%) rename packages/koenig-lexical/src/hooks/{useTypeaheadTriggerMatch.js => useTypeaheadTriggerMatch.ts} (100%) rename packages/koenig-lexical/src/hooks/{useVisibilityToggle.js => useVisibilityToggle.ts} (100%) rename packages/koenig-lexical/src/{index.js => index.ts} (100%) rename packages/koenig-lexical/src/nodes/{AsideNode.js => AsideNode.ts} (100%) rename packages/koenig-lexical/src/nodes/{AudioNode.jsx => AudioNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{AudioNodeComponent.jsx => AudioNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{BasicNodes.js => BasicNodes.ts} (100%) rename packages/koenig-lexical/src/nodes/{BookmarkNode.jsx => BookmarkNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{BookmarkNodeComponent.jsx => BookmarkNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ButtonNode.jsx => ButtonNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ButtonNodeComponent.jsx => ButtonNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CallToActionNode.jsx => CallToActionNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CallToActionNodeComponent.jsx => CallToActionNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CalloutNode.jsx => CalloutNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CalloutNodeComponent.jsx => CalloutNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CodeBlockNode.jsx => CodeBlockNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{CodeBlockNodeComponent.jsx => CodeBlockNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{DefaultNodes.js => DefaultNodes.ts} (100%) rename packages/koenig-lexical/src/nodes/{EmailCtaNode.jsx => EmailCtaNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmailCtaNodeComponent.jsx => EmailCtaNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmailEditorNodes.js => EmailEditorNodes.ts} (100%) rename packages/koenig-lexical/src/nodes/{EmailEmbedNode.jsx => EmailEmbedNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmailNode.jsx => EmailNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmailNodeComponent.jsx => EmailNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmailNodes.js => EmailNodes.ts} (100%) rename packages/koenig-lexical/src/nodes/{EmbedNode.jsx => EmbedNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{EmbedNodeComponent.jsx => EmbedNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{FileNode.jsx => FileNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{FileNodeComponent.jsx => FileNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{GalleryNode.jsx => GalleryNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{GalleryNodeComponent.jsx => GalleryNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{HeaderNode.jsx => HeaderNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{HorizontalRuleNode.jsx => HorizontalRuleNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{HtmlNode.jsx => HtmlNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{HtmlNodeComponent.jsx => HtmlNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ImageNode.jsx => ImageNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ImageNodeComponent.jsx => ImageNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{MarkdownNode.jsx => MarkdownNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{MarkdownNodeComponent.jsx => MarkdownNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{MinimalNodes.js => MinimalNodes.ts} (100%) rename packages/koenig-lexical/src/nodes/{PaywallNode.jsx => PaywallNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ProductNode.jsx => ProductNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ProductNodeComponent.jsx => ProductNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{SignupNode.jsx => SignupNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{SignupNodeComponent.jsx => SignupNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ToggleNode.jsx => ToggleNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{ToggleNodeComponent.jsx => ToggleNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{TransistorNode.jsx => TransistorNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{TransistorNodeComponent.jsx => TransistorNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/{VideoNode.jsx => VideoNode.tsx} (100%) rename packages/koenig-lexical/src/nodes/{VideoNodeComponent.jsx => VideoNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/header/v1/{HeaderNodeComponent.jsx => HeaderNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/nodes/header/v2/{HeaderNodeComponent.jsx => HeaderNodeComponent.tsx} (100%) rename packages/koenig-lexical/src/plugins/{AllDefaultPlugins.jsx => AllDefaultPlugins.tsx} (100%) rename packages/koenig-lexical/src/plugins/{AtLinkPlugin.jsx => AtLinkPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{AudioPlugin.jsx => AudioPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{BookmarkPlugin.jsx => BookmarkPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{ButtonPlugin.jsx => ButtonPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{CallToActionPlugin.jsx => CallToActionPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{CalloutPlugin.jsx => CalloutPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{CardMenuPlugin.jsx => CardMenuPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{DragDropPastePlugin.jsx => DragDropPastePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{DragDropReorderPlugin.jsx => DragDropReorderPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{EmEnDashPlugin.jsx => EmEnDashPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{EmailCtaPlugin.jsx => EmailCtaPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{EmailPlugin.jsx => EmailPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{EmbedPlugin.jsx => EmbedPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{EmojiPickerPlugin.jsx => EmojiPickerPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{ExternalControlPlugin.jsx => ExternalControlPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{FilePlugin.jsx => FilePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{FloatingToolbarPlugin.jsx => FloatingToolbarPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{GalleryPlugin.jsx => GalleryPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{HeaderPlugin.jsx => HeaderPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{HorizontalRulePlugin.jsx => HorizontalRulePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{HtmlOutputPlugin.jsx => HtmlOutputPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{HtmlPlugin.jsx => HtmlPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{ImagePlugin.jsx => ImagePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigBehaviourPlugin.jsx => KoenigBehaviourPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigBlurPlugin.jsx => KoenigBlurPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigFocusPlugin.jsx => KoenigFocusPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigNestedEditorPlugin.jsx => KoenigNestedEditorPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigSelectorPlugin.jsx => KoenigSelectorPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{KoenigSnippetPlugin.jsx => KoenigSnippetPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{MarkdownPastePlugin.jsx => MarkdownPastePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{MarkdownPlugin.jsx => MarkdownPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{MarkdownShortcutPlugin.jsx => MarkdownShortcutPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{PaywallPlugin.jsx => PaywallPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{PlusCardMenuPlugin.jsx => PlusCardMenuPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{ProductPlugin.jsx => ProductPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{ReplacementStringsPlugin.jsx => ReplacementStringsPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{RestrictContentPlugin.jsx => RestrictContentPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{SignupPlugin.jsx => SignupPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{SlashCardMenuPlugin.jsx => SlashCardMenuPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{TKCountPlugin.jsx => TKCountPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{TKPlugin.jsx => TKPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{TogglePlugin.jsx => TogglePlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{TransistorPlugin.jsx => TransistorPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{VideoPlugin.jsx => VideoPlugin.tsx} (100%) rename packages/koenig-lexical/src/plugins/{WordCountPlugin.jsx => WordCountPlugin.tsx} (100%) rename packages/koenig-lexical/src/themes/{default.js => default.ts} (100%) rename packages/koenig-lexical/src/utils/{$getSelectionRangeRect.js => $getSelectionRangeRect.ts} (100%) rename packages/koenig-lexical/src/utils/{$insertAndSelectNode.js => $insertAndSelectNode.ts} (100%) rename packages/koenig-lexical/src/utils/{$isAtStartOfDocument.js => $isAtStartOfDocument.ts} (100%) rename packages/koenig-lexical/src/utils/{$isAtTopOfNode.js => $isAtTopOfNode.ts} (100%) rename packages/koenig-lexical/src/utils/{$selectDecoratorNode.js => $selectDecoratorNode.ts} (100%) rename packages/koenig-lexical/src/utils/{analytics.js => analytics.ts} (100%) rename packages/koenig-lexical/src/utils/{audioUploadHandler.js => audioUploadHandler.ts} (100%) rename packages/koenig-lexical/src/utils/{autoExpandTextArea.js => autoExpandTextArea.ts} (100%) rename packages/koenig-lexical/src/utils/{buildCardMenu.js => buildCardMenu.ts} (100%) rename packages/koenig-lexical/src/utils/{callToActionColors.js => callToActionColors.ts} (100%) rename packages/koenig-lexical/src/utils/{codemirror-config.js => codemirror-config.ts} (100%) rename packages/koenig-lexical/src/utils/{constants.js => constants.ts} (100%) rename packages/koenig-lexical/src/utils/{ctrlOrCmd.js => ctrlOrCmd.ts} (100%) rename packages/koenig-lexical/src/utils/{dataSrcToFile.js => dataSrcToFile.ts} (100%) rename packages/koenig-lexical/src/utils/draggable/{DragDropContainer.js => DragDropContainer.ts} (100%) rename packages/koenig-lexical/src/utils/draggable/{DragDropHandler.jsx => DragDropHandler.tsx} (100%) rename packages/koenig-lexical/src/utils/draggable/{ScrollHandler.js => ScrollHandler.ts} (100%) rename packages/koenig-lexical/src/utils/draggable/{draggable-constants.js => draggable-constants.ts} (100%) rename packages/koenig-lexical/src/utils/draggable/{draggable-utils.js => draggable-utils.ts} (100%) rename packages/koenig-lexical/src/utils/{extractVideoMetadata.js => extractVideoMetadata.ts} (100%) rename packages/koenig-lexical/src/utils/{fileUploadHandler.js => fileUploadHandler.ts} (100%) rename packages/koenig-lexical/src/utils/{generateEditorState.js => generateEditorState.ts} (100%) rename packages/koenig-lexical/src/utils/{getAccentColor.js => getAccentColor.ts} (100%) rename packages/koenig-lexical/src/utils/{getAudioMetadata.js => getAudioMetadata.ts} (100%) rename packages/koenig-lexical/src/utils/{getDOMRangeRect.js => getDOMRangeRect.ts} (100%) rename packages/koenig-lexical/src/utils/{getEditorCardNodes.js => getEditorCardNodes.ts} (100%) rename packages/koenig-lexical/src/utils/{getImageDimensions.js => getImageDimensions.ts} (100%) rename packages/koenig-lexical/src/utils/{getImageFilenameFromSrc.js => getImageFilenameFromSrc.ts} (100%) rename packages/koenig-lexical/src/utils/{getScrollParent.js => getScrollParent.ts} (100%) rename packages/koenig-lexical/src/utils/{getSelectedNode.js => getSelectedNode.ts} (100%) rename packages/koenig-lexical/src/utils/{getTopLevelNativeElement.js => getTopLevelNativeElement.ts} (100%) rename packages/koenig-lexical/src/utils/{image-card-widths.js => image-card-widths.ts} (100%) rename packages/koenig-lexical/src/utils/{imageUploadHandler.js => imageUploadHandler.ts} (100%) rename packages/koenig-lexical/src/utils/{index.js => index.ts} (100%) rename packages/koenig-lexical/src/utils/{isEditorEmpty.js => isEditorEmpty.ts} (100%) rename packages/koenig-lexical/src/utils/{isGif.js => isGif.ts} (100%) rename packages/koenig-lexical/src/utils/{isInternalUrl.js => isInternalUrl.ts} (100%) rename packages/koenig-lexical/src/utils/{nested-editors.js => nested-editors.ts} (100%) rename packages/koenig-lexical/src/utils/{openFileSelection.js => openFileSelection.ts} (100%) rename packages/koenig-lexical/src/utils/{prettifyFileName.js => prettifyFileName.ts} (100%) rename packages/koenig-lexical/src/utils/{sanitize-html.js => sanitize-html.ts} (100%) rename packages/koenig-lexical/src/utils/services/{gif.js => gif.ts} (100%) rename packages/koenig-lexical/src/utils/{setFloatingElemPosition.js => setFloatingElemPosition.ts} (100%) rename packages/koenig-lexical/src/utils/{shortcutSymbols.js => shortcutSymbols.ts} (100%) rename packages/koenig-lexical/src/utils/{shouldIgnoreEvent.js => shouldIgnoreEvent.ts} (100%) rename packages/koenig-lexical/src/utils/storybook/{populate-storybook-editor.js => populate-storybook-editor.ts} (100%) rename packages/koenig-lexical/src/utils/{thumbnailUploadHandler.js => thumbnailUploadHandler.ts} (100%) rename packages/koenig-lexical/src/utils/{visibility.js => visibility.ts} (100%) rename packages/koenig-lexical/{svgo.config.js => svgo.config.cjs} (100%) rename packages/koenig-lexical/test/e2e/{card-behaviour.test.js => card-behaviour.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{audio-card.test.js => audio-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{bookmark-card-with-search.test.js => bookmark-card-with-search.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{bookmark-card-without-search.test.js => bookmark-card-without-search.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{button-card.test.js => button-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{call-to-action-card.test.js => call-to-action-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{callout-card.test.js => callout-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{code-block-card.test.js => code-block-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{email-card.test.js => email-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{email-cta-card.test.js => email-cta-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{embed-card.test.js => embed-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{file-card.test.js => file-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{gallery-card.test.js => gallery-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{header-card.test.js => header-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{html-card.test.js => html-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{image-card.test.js => image-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{markdown-card.test.js => markdown-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{paywall-card.test.js => paywall-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{product-card.test.js => product-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{signup-card.test.js => signup-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{toggle-card.test.js => toggle-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{transistor-card.test.js => transistor-card.test.ts} (100%) rename packages/koenig-lexical/test/e2e/cards/{video-card.firefox.test.js => video-card.firefox.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{content-visibility.test.js => content-visibility.test.ts} (100%) rename packages/koenig-lexical/test/e2e/editors/{basic-editor.test.js => basic-editor.test.ts} (100%) rename packages/koenig-lexical/test/e2e/editors/{email-editor.test.js => email-editor.test.ts} (100%) rename packages/koenig-lexical/test/e2e/editors/{minimal-editor.test.js => minimal-editor.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{floating-toolbar.test.js => floating-toolbar.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{format-shortcuts.test.js => format-shortcuts.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{linking.test.js => linking.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{list-behaviour.test.js => list-behaviour.test.ts} (100%) rename packages/koenig-lexical/test/e2e/modals/{UnsplashSelector.test.js => UnsplashSelector.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{node-transforms.test.js => node-transforms.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{paste-behaviour.test.js => paste-behaviour.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{DragDropPastePlugin.firefox.test.js => DragDropPastePlugin.firefox.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{DragDropPastePlugin.test.js => DragDropPastePlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{DragDropReorderPlugin.test.js => DragDropReorderPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{EmojiPickerPlugin.test.js => EmojiPickerPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{HtmlOutputPlugin.test.js => HtmlOutputPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{KoenigSnippetPlugin.test.js => KoenigSnippetPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{ReplacementStringsPlugin.test.js => ReplacementStringsPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{RestrictContentPlugin.test.js => RestrictContentPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{TKPlugin.test.js => TKPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/plugins/{WordCountPlugin.test.js => WordCountPlugin.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{plus-button.test.js => plus-button.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{selection.test.js => selection.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{slash-menu.test.js => slash-menu.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{code-block.test.js => code-block.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{emdash-endash.test.js => emdash-endash.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{headings.test.js => headings.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{horizontal-line-rule.test.js => horizontal-line-rule.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{links.test.js => links.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{markdown.test.js => markdown.test.ts} (100%) rename packages/koenig-lexical/test/e2e/text-transforms/{paywall.test.js => paywall.test.ts} (100%) rename packages/koenig-lexical/test/e2e/{title-behaviour.test.js => title-behaviour.test.ts} (100%) rename packages/koenig-lexical/test/e2e/utils/{getImageDimensions.test.js => getImageDimensions.test.ts} (100%) rename packages/koenig-lexical/test/{test-setup.js => test-setup.ts} (100%) rename packages/koenig-lexical/test/unit/{EmailEditor.test.js => EmailEditor.test.ts} (100%) rename packages/koenig-lexical/test/unit/{KoenigComposer.test.jsx => KoenigComposer.test.tsx} (100%) rename packages/koenig-lexical/test/unit/{build-output.test.js => build-output.test.ts} (100%) rename packages/koenig-lexical/test/unit/{buildCardMenu.test.js => buildCardMenu.test.ts} (100%) rename packages/koenig-lexical/test/unit/{headerCardv2.test.js => headerCardv2.test.ts} (100%) rename packages/koenig-lexical/test/unit/hooks/{useVisibilityToggle.test.js => useVisibilityToggle.test.ts} (100%) rename packages/koenig-lexical/test/unit/{productCard.test.js => productCard.test.ts} (100%) rename packages/koenig-lexical/test/unit/{signupCard.test.js => signupCard.test.ts} (100%) rename packages/koenig-lexical/test/unit/{toggleCard.test.js => toggleCard.test.ts} (100%) rename packages/koenig-lexical/test/unit/utils/{generateEditorState.test.js => generateEditorState.test.ts} (100%) rename packages/koenig-lexical/test/unit/utils/{gif-provider.test.js => gif-provider.test.ts} (100%) rename packages/koenig-lexical/test/unit/utils/{image-card-widths.test.js => image-card-widths.test.ts} (100%) rename packages/koenig-lexical/test/unit/utils/{sanitize-html.test.js => sanitize-html.test.ts} (100%) rename packages/koenig-lexical/test/unit/utils/{visibility.test.js => visibility.test.ts} (100%) rename packages/koenig-lexical/test/utils/{color-select-helper.js => color-select-helper.ts} (100%) rename packages/koenig-lexical/test/utils/{e2e.js => e2e.ts} (100%) rename packages/koenig-lexical/test/utils/{isTestEnv.js => isTestEnv.ts} (100%) rename packages/koenig-lexical/{vite.config.demo.js => vite.config.demo.ts} (100%) rename packages/koenig-lexical/{vite.config.js => vite.config.ts} (100%) diff --git a/packages/koenig-lexical/.storybook/editorEmptyState.js b/packages/koenig-lexical/.storybook/editorEmptyState.ts similarity index 100% rename from packages/koenig-lexical/.storybook/editorEmptyState.js rename to packages/koenig-lexical/.storybook/editorEmptyState.ts diff --git a/packages/koenig-lexical/.storybook/preview.jsx b/packages/koenig-lexical/.storybook/preview.tsx similarity index 100% rename from packages/koenig-lexical/.storybook/preview.jsx rename to packages/koenig-lexical/.storybook/preview.tsx diff --git a/packages/koenig-lexical/demo/DemoApp.jsx b/packages/koenig-lexical/demo/DemoApp.tsx similarity index 100% rename from packages/koenig-lexical/demo/DemoApp.jsx rename to packages/koenig-lexical/demo/DemoApp.tsx diff --git a/packages/koenig-lexical/demo/HtmlOutputDemo.jsx b/packages/koenig-lexical/demo/HtmlOutputDemo.tsx similarity index 100% rename from packages/koenig-lexical/demo/HtmlOutputDemo.jsx rename to packages/koenig-lexical/demo/HtmlOutputDemo.tsx diff --git a/packages/koenig-lexical/demo/RestrictedContentDemo.jsx b/packages/koenig-lexical/demo/RestrictedContentDemo.tsx similarity index 100% rename from packages/koenig-lexical/demo/RestrictedContentDemo.jsx rename to packages/koenig-lexical/demo/RestrictedContentDemo.tsx diff --git a/packages/koenig-lexical/demo/components/DarkModeToggle.jsx b/packages/koenig-lexical/demo/components/DarkModeToggle.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/DarkModeToggle.jsx rename to packages/koenig-lexical/demo/components/DarkModeToggle.tsx diff --git a/packages/koenig-lexical/demo/components/EmailEditorWrapper.jsx b/packages/koenig-lexical/demo/components/EmailEditorWrapper.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/EmailEditorWrapper.jsx rename to packages/koenig-lexical/demo/components/EmailEditorWrapper.tsx diff --git a/packages/koenig-lexical/demo/components/FloatingButton.jsx b/packages/koenig-lexical/demo/components/FloatingButton.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/FloatingButton.jsx rename to packages/koenig-lexical/demo/components/FloatingButton.tsx diff --git a/packages/koenig-lexical/demo/components/InitialContentToggle.jsx b/packages/koenig-lexical/demo/components/InitialContentToggle.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/InitialContentToggle.jsx rename to packages/koenig-lexical/demo/components/InitialContentToggle.tsx diff --git a/packages/koenig-lexical/demo/components/Navigator.jsx b/packages/koenig-lexical/demo/components/Navigator.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/Navigator.jsx rename to packages/koenig-lexical/demo/components/Navigator.tsx diff --git a/packages/koenig-lexical/demo/components/SerializedStateTextarea.jsx b/packages/koenig-lexical/demo/components/SerializedStateTextarea.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/SerializedStateTextarea.jsx rename to packages/koenig-lexical/demo/components/SerializedStateTextarea.tsx diff --git a/packages/koenig-lexical/demo/components/Sidebar.jsx b/packages/koenig-lexical/demo/components/Sidebar.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/Sidebar.jsx rename to packages/koenig-lexical/demo/components/Sidebar.tsx diff --git a/packages/koenig-lexical/demo/components/TitleTextBox.jsx b/packages/koenig-lexical/demo/components/TitleTextBox.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/TitleTextBox.jsx rename to packages/koenig-lexical/demo/components/TitleTextBox.tsx diff --git a/packages/koenig-lexical/demo/components/TreeView.jsx b/packages/koenig-lexical/demo/components/TreeView.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/TreeView.jsx rename to packages/koenig-lexical/demo/components/TreeView.tsx diff --git a/packages/koenig-lexical/demo/components/Watermark.jsx b/packages/koenig-lexical/demo/components/Watermark.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/Watermark.jsx rename to packages/koenig-lexical/demo/components/Watermark.tsx diff --git a/packages/koenig-lexical/demo/components/WordCount.jsx b/packages/koenig-lexical/demo/components/WordCount.tsx similarity index 100% rename from packages/koenig-lexical/demo/components/WordCount.jsx rename to packages/koenig-lexical/demo/components/WordCount.tsx diff --git a/packages/koenig-lexical/demo/demo.jsx b/packages/koenig-lexical/demo/demo.tsx similarity index 100% rename from packages/koenig-lexical/demo/demo.jsx rename to packages/koenig-lexical/demo/demo.tsx diff --git a/packages/koenig-lexical/demo/utils/fetchEmbed.js b/packages/koenig-lexical/demo/utils/fetchEmbed.ts similarity index 100% rename from packages/koenig-lexical/demo/utils/fetchEmbed.js rename to packages/koenig-lexical/demo/utils/fetchEmbed.ts diff --git a/packages/koenig-lexical/demo/utils/gifConfig.js b/packages/koenig-lexical/demo/utils/gifConfig.ts similarity index 100% rename from packages/koenig-lexical/demo/utils/gifConfig.js rename to packages/koenig-lexical/demo/utils/gifConfig.ts diff --git a/packages/koenig-lexical/demo/utils/unsplashConfig.js b/packages/koenig-lexical/demo/utils/unsplashConfig.ts similarity index 100% rename from packages/koenig-lexical/demo/utils/unsplashConfig.js rename to packages/koenig-lexical/demo/utils/unsplashConfig.ts diff --git a/packages/koenig-lexical/demo/utils/useFileUpload.js b/packages/koenig-lexical/demo/utils/useFileUpload.ts similarity index 100% rename from packages/koenig-lexical/demo/utils/useFileUpload.js rename to packages/koenig-lexical/demo/utils/useFileUpload.ts diff --git a/packages/koenig-lexical/demo/utils/useSnippets.js b/packages/koenig-lexical/demo/utils/useSnippets.ts similarity index 100% rename from packages/koenig-lexical/demo/utils/useSnippets.js rename to packages/koenig-lexical/demo/utils/useSnippets.ts diff --git a/packages/koenig-lexical/eslint.config.js b/packages/koenig-lexical/eslint.config.mjs similarity index 100% rename from packages/koenig-lexical/eslint.config.js rename to packages/koenig-lexical/eslint.config.mjs diff --git a/packages/koenig-lexical/playwright.config.js b/packages/koenig-lexical/playwright.config.ts similarity index 100% rename from packages/koenig-lexical/playwright.config.js rename to packages/koenig-lexical/playwright.config.ts diff --git a/packages/koenig-lexical/src/components/DesignSandbox.jsx b/packages/koenig-lexical/src/components/DesignSandbox.tsx similarity index 100% rename from packages/koenig-lexical/src/components/DesignSandbox.jsx rename to packages/koenig-lexical/src/components/DesignSandbox.tsx diff --git a/packages/koenig-lexical/src/components/EmailEditor.jsx b/packages/koenig-lexical/src/components/EmailEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/EmailEditor.jsx rename to packages/koenig-lexical/src/components/EmailEditor.tsx diff --git a/packages/koenig-lexical/src/components/KoenigCaptionEditor.jsx b/packages/koenig-lexical/src/components/KoenigCaptionEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigCaptionEditor.jsx rename to packages/koenig-lexical/src/components/KoenigCaptionEditor.tsx diff --git a/packages/koenig-lexical/src/components/KoenigCardWrapper.jsx b/packages/koenig-lexical/src/components/KoenigCardWrapper.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigCardWrapper.jsx rename to packages/koenig-lexical/src/components/KoenigCardWrapper.tsx diff --git a/packages/koenig-lexical/src/components/KoenigComposableEditor.jsx b/packages/koenig-lexical/src/components/KoenigComposableEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigComposableEditor.jsx rename to packages/koenig-lexical/src/components/KoenigComposableEditor.tsx diff --git a/packages/koenig-lexical/src/components/KoenigComposer.jsx b/packages/koenig-lexical/src/components/KoenigComposer.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigComposer.jsx rename to packages/koenig-lexical/src/components/KoenigComposer.tsx diff --git a/packages/koenig-lexical/src/components/KoenigEditor.jsx b/packages/koenig-lexical/src/components/KoenigEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigEditor.jsx rename to packages/koenig-lexical/src/components/KoenigEditor.tsx diff --git a/packages/koenig-lexical/src/components/KoenigErrorBoundary.jsx b/packages/koenig-lexical/src/components/KoenigErrorBoundary.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigErrorBoundary.jsx rename to packages/koenig-lexical/src/components/KoenigErrorBoundary.tsx diff --git a/packages/koenig-lexical/src/components/KoenigNestedComposer.jsx b/packages/koenig-lexical/src/components/KoenigNestedComposer.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigNestedComposer.jsx rename to packages/koenig-lexical/src/components/KoenigNestedComposer.tsx diff --git a/packages/koenig-lexical/src/components/KoenigNestedEditor.jsx b/packages/koenig-lexical/src/components/KoenigNestedEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/KoenigNestedEditor.jsx rename to packages/koenig-lexical/src/components/KoenigNestedEditor.tsx diff --git a/packages/koenig-lexical/src/components/ui/ActionToolbar.jsx b/packages/koenig-lexical/src/components/ui/ActionToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ActionToolbar.jsx rename to packages/koenig-lexical/src/components/ui/ActionToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/AtLinkResultsPopup.jsx b/packages/koenig-lexical/src/components/ui/AtLinkResultsPopup.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/AtLinkResultsPopup.jsx rename to packages/koenig-lexical/src/components/ui/AtLinkResultsPopup.tsx diff --git a/packages/koenig-lexical/src/components/ui/AudioUploadForm.jsx b/packages/koenig-lexical/src/components/ui/AudioUploadForm.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/AudioUploadForm.jsx rename to packages/koenig-lexical/src/components/ui/AudioUploadForm.tsx diff --git a/packages/koenig-lexical/src/components/ui/BackgroundImagePicker.jsx b/packages/koenig-lexical/src/components/ui/BackgroundImagePicker.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/BackgroundImagePicker.jsx rename to packages/koenig-lexical/src/components/ui/BackgroundImagePicker.tsx diff --git a/packages/koenig-lexical/src/components/ui/Button.stories.jsx b/packages/koenig-lexical/src/components/ui/Button.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Button.stories.jsx rename to packages/koenig-lexical/src/components/ui/Button.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Button.jsx b/packages/koenig-lexical/src/components/ui/Button.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Button.jsx rename to packages/koenig-lexical/src/components/ui/Button.tsx diff --git a/packages/koenig-lexical/src/components/ui/ButtonGroup.stories.jsx b/packages/koenig-lexical/src/components/ui/ButtonGroup.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ButtonGroup.stories.jsx rename to packages/koenig-lexical/src/components/ui/ButtonGroup.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/ButtonGroup.jsx b/packages/koenig-lexical/src/components/ui/ButtonGroup.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ButtonGroup.jsx rename to packages/koenig-lexical/src/components/ui/ButtonGroup.tsx diff --git a/packages/koenig-lexical/src/components/ui/CardCaptionEditor.jsx b/packages/koenig-lexical/src/components/ui/CardCaptionEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/CardCaptionEditor.jsx rename to packages/koenig-lexical/src/components/ui/CardCaptionEditor.tsx diff --git a/packages/koenig-lexical/src/components/ui/CardMenu.stories.jsx b/packages/koenig-lexical/src/components/ui/CardMenu.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/CardMenu.stories.jsx rename to packages/koenig-lexical/src/components/ui/CardMenu.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/CardMenu.jsx b/packages/koenig-lexical/src/components/ui/CardMenu.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/CardMenu.jsx rename to packages/koenig-lexical/src/components/ui/CardMenu.tsx diff --git a/packages/koenig-lexical/src/components/ui/CardVisibilityMessage.jsx b/packages/koenig-lexical/src/components/ui/CardVisibilityMessage.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/CardVisibilityMessage.jsx rename to packages/koenig-lexical/src/components/ui/CardVisibilityMessage.tsx diff --git a/packages/koenig-lexical/src/components/ui/CardWrapper.jsx b/packages/koenig-lexical/src/components/ui/CardWrapper.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/CardWrapper.jsx rename to packages/koenig-lexical/src/components/ui/CardWrapper.tsx diff --git a/packages/koenig-lexical/src/components/ui/ColorOptionButtons.jsx b/packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ColorOptionButtons.jsx rename to packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx diff --git a/packages/koenig-lexical/src/components/ui/ColorPicker.stories.jsx b/packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ColorPicker.stories.jsx rename to packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/ColorPicker.jsx b/packages/koenig-lexical/src/components/ui/ColorPicker.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ColorPicker.jsx rename to packages/koenig-lexical/src/components/ui/ColorPicker.tsx diff --git a/packages/koenig-lexical/src/components/ui/Delayed.jsx b/packages/koenig-lexical/src/components/ui/Delayed.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Delayed.jsx rename to packages/koenig-lexical/src/components/ui/Delayed.tsx diff --git a/packages/koenig-lexical/src/components/ui/Dropdown.stories.jsx b/packages/koenig-lexical/src/components/ui/Dropdown.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Dropdown.stories.jsx rename to packages/koenig-lexical/src/components/ui/Dropdown.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Dropdown.jsx b/packages/koenig-lexical/src/components/ui/Dropdown.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Dropdown.jsx rename to packages/koenig-lexical/src/components/ui/Dropdown.tsx diff --git a/packages/koenig-lexical/src/components/ui/DropdownContainer.jsx b/packages/koenig-lexical/src/components/ui/DropdownContainer.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/DropdownContainer.jsx rename to packages/koenig-lexical/src/components/ui/DropdownContainer.tsx diff --git a/packages/koenig-lexical/src/components/ui/EditorPlaceholder.jsx b/packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/EditorPlaceholder.jsx rename to packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx diff --git a/packages/koenig-lexical/src/components/ui/EmojiPicker.jsx b/packages/koenig-lexical/src/components/ui/EmojiPicker.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/EmojiPicker.jsx rename to packages/koenig-lexical/src/components/ui/EmojiPicker.tsx diff --git a/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.jsx b/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/EmojiPickerPortal.jsx rename to packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx diff --git a/packages/koenig-lexical/src/components/ui/FileUploadForm.jsx b/packages/koenig-lexical/src/components/ui/FileUploadForm.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/FileUploadForm.jsx rename to packages/koenig-lexical/src/components/ui/FileUploadForm.tsx diff --git a/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.jsx b/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.jsx rename to packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.jsx b/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.jsx rename to packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/FloatingToolbar.jsx b/packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/FloatingToolbar.jsx rename to packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/FormatToolbar.jsx b/packages/koenig-lexical/src/components/ui/FormatToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/FormatToolbar.jsx rename to packages/koenig-lexical/src/components/ui/FormatToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/GifPlugin.jsx b/packages/koenig-lexical/src/components/ui/GifPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/GifPlugin.jsx rename to packages/koenig-lexical/src/components/ui/GifPlugin.tsx diff --git a/packages/koenig-lexical/src/components/ui/GifSelector.stories.jsx b/packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/GifSelector.stories.jsx rename to packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/GifSelector.jsx b/packages/koenig-lexical/src/components/ui/GifSelector.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/GifSelector.jsx rename to packages/koenig-lexical/src/components/ui/GifSelector.tsx diff --git a/packages/koenig-lexical/src/components/ui/HighlightedString.jsx b/packages/koenig-lexical/src/components/ui/HighlightedString.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/HighlightedString.jsx rename to packages/koenig-lexical/src/components/ui/HighlightedString.tsx diff --git a/packages/koenig-lexical/src/components/ui/IconButton.stories.jsx b/packages/koenig-lexical/src/components/ui/IconButton.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/IconButton.stories.jsx rename to packages/koenig-lexical/src/components/ui/IconButton.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/IconButton.jsx b/packages/koenig-lexical/src/components/ui/IconButton.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/IconButton.jsx rename to packages/koenig-lexical/src/components/ui/IconButton.tsx diff --git a/packages/koenig-lexical/src/components/ui/ImageUploadForm.jsx b/packages/koenig-lexical/src/components/ui/ImageUploadForm.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ImageUploadForm.jsx rename to packages/koenig-lexical/src/components/ui/ImageUploadForm.tsx diff --git a/packages/koenig-lexical/src/components/ui/ImageUploadSwatch.jsx b/packages/koenig-lexical/src/components/ui/ImageUploadSwatch.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ImageUploadSwatch.jsx rename to packages/koenig-lexical/src/components/ui/ImageUploadSwatch.tsx diff --git a/packages/koenig-lexical/src/components/ui/Input.stories.jsx b/packages/koenig-lexical/src/components/ui/Input.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Input.stories.jsx rename to packages/koenig-lexical/src/components/ui/Input.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Input.jsx b/packages/koenig-lexical/src/components/ui/Input.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Input.jsx rename to packages/koenig-lexical/src/components/ui/Input.tsx diff --git a/packages/koenig-lexical/src/components/ui/InputList.stories.jsx b/packages/koenig-lexical/src/components/ui/InputList.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/InputList.stories.jsx rename to packages/koenig-lexical/src/components/ui/InputList.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/InputList.jsx b/packages/koenig-lexical/src/components/ui/InputList.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/InputList.jsx rename to packages/koenig-lexical/src/components/ui/InputList.tsx diff --git a/packages/koenig-lexical/src/components/ui/KeyboardSelection.jsx b/packages/koenig-lexical/src/components/ui/KeyboardSelection.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/KeyboardSelection.jsx rename to packages/koenig-lexical/src/components/ui/KeyboardSelection.tsx diff --git a/packages/koenig-lexical/src/components/ui/KeyboardSelectionWithGroups.jsx b/packages/koenig-lexical/src/components/ui/KeyboardSelectionWithGroups.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/KeyboardSelectionWithGroups.jsx rename to packages/koenig-lexical/src/components/ui/KeyboardSelectionWithGroups.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkActionToolbar.jsx b/packages/koenig-lexical/src/components/ui/LinkActionToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkActionToolbar.jsx rename to packages/koenig-lexical/src/components/ui/LinkActionToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkActionToolbarWithSearch.jsx b/packages/koenig-lexical/src/components/ui/LinkActionToolbarWithSearch.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkActionToolbarWithSearch.jsx rename to packages/koenig-lexical/src/components/ui/LinkActionToolbarWithSearch.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkInput.stories.jsx b/packages/koenig-lexical/src/components/ui/LinkInput.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkInput.stories.jsx rename to packages/koenig-lexical/src/components/ui/LinkInput.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkInput.jsx b/packages/koenig-lexical/src/components/ui/LinkInput.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkInput.jsx rename to packages/koenig-lexical/src/components/ui/LinkInput.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.jsx b/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkInputSearchItem.jsx rename to packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.stories.jsx b/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkInputWithSearch.stories.jsx rename to packages/koenig-lexical/src/components/ui/LinkInputWithSearch.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.jsx b/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkInputWithSearch.jsx rename to packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.jsx b/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkToolbar.stories.jsx rename to packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/LinkToolbar.jsx b/packages/koenig-lexical/src/components/ui/LinkToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/LinkToolbar.jsx rename to packages/koenig-lexical/src/components/ui/LinkToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.jsx b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.jsx rename to packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.jsx b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MediaPlaceholder.jsx rename to packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx diff --git a/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.jsx b/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MediaPlayer.stories.jsx rename to packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/MediaPlayer.jsx b/packages/koenig-lexical/src/components/ui/MediaPlayer.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MediaPlayer.jsx rename to packages/koenig-lexical/src/components/ui/MediaPlayer.tsx diff --git a/packages/koenig-lexical/src/components/ui/MediaUploader.jsx b/packages/koenig-lexical/src/components/ui/MediaUploader.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MediaUploader.jsx rename to packages/koenig-lexical/src/components/ui/MediaUploader.tsx diff --git a/packages/koenig-lexical/src/components/ui/Modal.stories.jsx b/packages/koenig-lexical/src/components/ui/Modal.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Modal.stories.jsx rename to packages/koenig-lexical/src/components/ui/Modal.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Modal.jsx b/packages/koenig-lexical/src/components/ui/Modal.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Modal.jsx rename to packages/koenig-lexical/src/components/ui/Modal.tsx diff --git a/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.jsx b/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/MultiSelectDropdown.jsx rename to packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx diff --git a/packages/koenig-lexical/src/components/ui/PlusMenu.stories.jsx b/packages/koenig-lexical/src/components/ui/PlusMenu.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/PlusMenu.stories.jsx rename to packages/koenig-lexical/src/components/ui/PlusMenu.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/PlusMenu.jsx b/packages/koenig-lexical/src/components/ui/PlusMenu.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/PlusMenu.jsx rename to packages/koenig-lexical/src/components/ui/PlusMenu.tsx diff --git a/packages/koenig-lexical/src/components/ui/Portal.jsx b/packages/koenig-lexical/src/components/ui/Portal.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Portal.jsx rename to packages/koenig-lexical/src/components/ui/Portal.tsx diff --git a/packages/koenig-lexical/src/components/ui/ProgressBar.stories.jsx b/packages/koenig-lexical/src/components/ui/ProgressBar.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ProgressBar.stories.jsx rename to packages/koenig-lexical/src/components/ui/ProgressBar.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/ProgressBar.jsx b/packages/koenig-lexical/src/components/ui/ProgressBar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ProgressBar.jsx rename to packages/koenig-lexical/src/components/ui/ProgressBar.tsx diff --git a/packages/koenig-lexical/src/components/ui/ReadOnlyOverlay.jsx b/packages/koenig-lexical/src/components/ui/ReadOnlyOverlay.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ReadOnlyOverlay.jsx rename to packages/koenig-lexical/src/components/ui/ReadOnlyOverlay.tsx diff --git a/packages/koenig-lexical/src/components/ui/SettingsPanel.stories.jsx b/packages/koenig-lexical/src/components/ui/SettingsPanel.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SettingsPanel.stories.jsx rename to packages/koenig-lexical/src/components/ui/SettingsPanel.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/SettingsPanel.jsx b/packages/koenig-lexical/src/components/ui/SettingsPanel.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SettingsPanel.jsx rename to packages/koenig-lexical/src/components/ui/SettingsPanel.tsx diff --git a/packages/koenig-lexical/src/components/ui/SlashMenu.jsx b/packages/koenig-lexical/src/components/ui/SlashMenu.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SlashMenu.jsx rename to packages/koenig-lexical/src/components/ui/SlashMenu.tsx diff --git a/packages/koenig-lexical/src/components/ui/Slider.stories.jsx b/packages/koenig-lexical/src/components/ui/Slider.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Slider.stories.jsx rename to packages/koenig-lexical/src/components/ui/Slider.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Slider.jsx b/packages/koenig-lexical/src/components/ui/Slider.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Slider.jsx rename to packages/koenig-lexical/src/components/ui/Slider.tsx diff --git a/packages/koenig-lexical/src/components/ui/SnippetActionToolbar.jsx b/packages/koenig-lexical/src/components/ui/SnippetActionToolbar.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SnippetActionToolbar.jsx rename to packages/koenig-lexical/src/components/ui/SnippetActionToolbar.tsx diff --git a/packages/koenig-lexical/src/components/ui/SnippetInput.stories.jsx b/packages/koenig-lexical/src/components/ui/SnippetInput.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SnippetInput.stories.jsx rename to packages/koenig-lexical/src/components/ui/SnippetInput.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/SnippetInput.jsx b/packages/koenig-lexical/src/components/ui/SnippetInput.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SnippetInput.jsx rename to packages/koenig-lexical/src/components/ui/SnippetInput.tsx diff --git a/packages/koenig-lexical/src/components/ui/SnippetInput/Dropdown.jsx b/packages/koenig-lexical/src/components/ui/SnippetInput/Dropdown.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SnippetInput/Dropdown.jsx rename to packages/koenig-lexical/src/components/ui/SnippetInput/Dropdown.tsx diff --git a/packages/koenig-lexical/src/components/ui/SnippetInput/Input.jsx b/packages/koenig-lexical/src/components/ui/SnippetInput/Input.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SnippetInput/Input.jsx rename to packages/koenig-lexical/src/components/ui/SnippetInput/Input.tsx diff --git a/packages/koenig-lexical/src/components/ui/Spinner.jsx b/packages/koenig-lexical/src/components/ui/Spinner.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Spinner.jsx rename to packages/koenig-lexical/src/components/ui/Spinner.tsx diff --git a/packages/koenig-lexical/src/components/ui/SubscribeForm.stories.jsx b/packages/koenig-lexical/src/components/ui/SubscribeForm.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SubscribeForm.stories.jsx rename to packages/koenig-lexical/src/components/ui/SubscribeForm.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/SubscribeForm.jsx b/packages/koenig-lexical/src/components/ui/SubscribeForm.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/SubscribeForm.jsx rename to packages/koenig-lexical/src/components/ui/SubscribeForm.tsx diff --git a/packages/koenig-lexical/src/components/ui/TabView.jsx b/packages/koenig-lexical/src/components/ui/TabView.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/TabView.jsx rename to packages/koenig-lexical/src/components/ui/TabView.tsx diff --git a/packages/koenig-lexical/src/components/ui/TextInput.jsx b/packages/koenig-lexical/src/components/ui/TextInput.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/TextInput.jsx rename to packages/koenig-lexical/src/components/ui/TextInput.tsx diff --git a/packages/koenig-lexical/src/components/ui/Toggle.stories.jsx b/packages/koenig-lexical/src/components/ui/Toggle.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Toggle.stories.jsx rename to packages/koenig-lexical/src/components/ui/Toggle.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Toggle.jsx b/packages/koenig-lexical/src/components/ui/Toggle.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Toggle.jsx rename to packages/koenig-lexical/src/components/ui/Toggle.tsx diff --git a/packages/koenig-lexical/src/components/ui/ToolbarMenu.stories.jsx b/packages/koenig-lexical/src/components/ui/ToolbarMenu.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ToolbarMenu.stories.jsx rename to packages/koenig-lexical/src/components/ui/ToolbarMenu.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/ToolbarMenu.jsx b/packages/koenig-lexical/src/components/ui/ToolbarMenu.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ToolbarMenu.jsx rename to packages/koenig-lexical/src/components/ui/ToolbarMenu.tsx diff --git a/packages/koenig-lexical/src/components/ui/ToolbarMenuItem.stories.jsx b/packages/koenig-lexical/src/components/ui/ToolbarMenuItem.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/ToolbarMenuItem.stories.jsx rename to packages/koenig-lexical/src/components/ui/ToolbarMenuItem.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/Tooltip.jsx b/packages/koenig-lexical/src/components/ui/Tooltip.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/Tooltip.jsx rename to packages/koenig-lexical/src/components/ui/Tooltip.tsx diff --git a/packages/koenig-lexical/src/components/ui/UnsplashPlugin.jsx b/packages/koenig-lexical/src/components/ui/UnsplashPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/UnsplashPlugin.jsx rename to packages/koenig-lexical/src/components/ui/UnsplashPlugin.tsx diff --git a/packages/koenig-lexical/src/components/ui/UrlInput.stories.jsx b/packages/koenig-lexical/src/components/ui/UrlInput.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/UrlInput.stories.jsx rename to packages/koenig-lexical/src/components/ui/UrlInput.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/UrlInput.jsx b/packages/koenig-lexical/src/components/ui/UrlInput.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/UrlInput.jsx rename to packages/koenig-lexical/src/components/ui/UrlInput.tsx diff --git a/packages/koenig-lexical/src/components/ui/UrlSearchInput.stories.jsx b/packages/koenig-lexical/src/components/ui/UrlSearchInput.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/UrlSearchInput.stories.jsx rename to packages/koenig-lexical/src/components/ui/UrlSearchInput.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/UrlSearchInput.jsx b/packages/koenig-lexical/src/components/ui/UrlSearchInput.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/UrlSearchInput.jsx rename to packages/koenig-lexical/src/components/ui/UrlSearchInput.tsx diff --git a/packages/koenig-lexical/src/components/ui/VisibilitySettings.jsx b/packages/koenig-lexical/src/components/ui/VisibilitySettings.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/VisibilitySettings.jsx rename to packages/koenig-lexical/src/components/ui/VisibilitySettings.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/AudioCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/AudioCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/AudioCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/AudioCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/AudioCard.jsx b/packages/koenig-lexical/src/components/ui/cards/AudioCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/AudioCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/AudioCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.jsx b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/BookmarkCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.jsx b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ButtonCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.jsx b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CallToActionCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.jsx b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CalloutCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.jsx b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCard.jsx b/packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmailCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.jsx b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.jsx b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/EmbedCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/FileCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/FileCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/FileCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/FileCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/FileCard.jsx b/packages/koenig-lexical/src/components/ui/cards/FileCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/FileCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/FileCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/GalleryCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/GalleryCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/GalleryCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/GalleryCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/GalleryCard.jsx b/packages/koenig-lexical/src/components/ui/cards/GalleryCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/GalleryCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/GalleryCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.jsx b/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.v1.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.v1.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.v1.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/HeaderCard/v1/HeaderCard.v1.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.jsx b/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.v2.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.v2.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.v2.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/HeaderCard/v2/HeaderCard.v2.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.jsx b/packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/HorizontalRuleCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HtmlCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/HtmlCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HtmlCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/HtmlCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HtmlCard.jsx b/packages/koenig-lexical/src/components/ui/cards/HtmlCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HtmlCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/HtmlCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/HtmlCard/HtmlEditor.jsx b/packages/koenig-lexical/src/components/ui/cards/HtmlCard/HtmlEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/HtmlCard/HtmlEditor.jsx rename to packages/koenig-lexical/src/components/ui/cards/HtmlCard/HtmlEditor.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ImageCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/ImageCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ImageCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/ImageCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ImageCard.jsx b/packages/koenig-lexical/src/components/ui/cards/ImageCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ImageCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/ImageCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard.jsx b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownEditor.jsx b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownEditor.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownEditor.jsx rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownEditor.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownHelpDialog.jsx b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownHelpDialog.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownHelpDialog.jsx rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownHelpDialog.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownImageUploader.jsx b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownImageUploader.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownImageUploader.jsx rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard/MarkdownImageUploader.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/useMarkdownImageUploader.js b/packages/koenig-lexical/src/components/ui/cards/MarkdownCard/useMarkdownImageUploader.ts similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/MarkdownCard/useMarkdownImageUploader.js rename to packages/koenig-lexical/src/components/ui/cards/MarkdownCard/useMarkdownImageUploader.ts diff --git a/packages/koenig-lexical/src/components/ui/cards/PaywallCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/PaywallCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/PaywallCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/PaywallCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/PaywallCard.jsx b/packages/koenig-lexical/src/components/ui/cards/PaywallCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/PaywallCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/PaywallCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ProductCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/ProductCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ProductCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/ProductCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ProductCard.jsx b/packages/koenig-lexical/src/components/ui/cards/ProductCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ProductCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/ProductCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ProductCard/ProductCardImage.jsx b/packages/koenig-lexical/src/components/ui/cards/ProductCard/ProductCardImage.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ProductCard/ProductCardImage.jsx rename to packages/koenig-lexical/src/components/ui/cards/ProductCard/ProductCardImage.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ProductCard/RatingButton.jsx b/packages/koenig-lexical/src/components/ui/cards/ProductCard/RatingButton.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ProductCard/RatingButton.jsx rename to packages/koenig-lexical/src/components/ui/cards/ProductCard/RatingButton.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/SignupCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/SignupCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/SignupCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/SignupCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/SignupCard.jsx b/packages/koenig-lexical/src/components/ui/cards/SignupCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/SignupCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/SignupCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ToggleCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/ToggleCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ToggleCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/ToggleCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/ToggleCard.jsx b/packages/koenig-lexical/src/components/ui/cards/ToggleCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/ToggleCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/ToggleCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/TransistorCard.jsx b/packages/koenig-lexical/src/components/ui/cards/TransistorCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/TransistorCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/TransistorCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/VideoCard.stories.jsx b/packages/koenig-lexical/src/components/ui/cards/VideoCard.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/VideoCard.stories.jsx rename to packages/koenig-lexical/src/components/ui/cards/VideoCard.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/cards/VideoCard.jsx b/packages/koenig-lexical/src/components/ui/cards/VideoCard.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/cards/VideoCard.jsx rename to packages/koenig-lexical/src/components/ui/cards/VideoCard.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Error.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Error.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Gif/Error.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Gif/Error.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Gif.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Gif.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Gif/Gif.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Gif/Gif.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Loader.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Gif/Loader.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Gif/Loader.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Gif/Loader.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashButton.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashButton.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashButton.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashButton.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashGallery.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashGallery.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashGallery.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashGallery.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashImage.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashImage.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashImage.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashImage.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.stories.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.stories.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.stories.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.stories.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashSelector.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashZoomed.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashZoomed.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashZoomed.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/Unsplash/UnsplashZoomed.tsx diff --git a/packages/koenig-lexical/src/components/ui/file-selectors/UnsplashModal.jsx b/packages/koenig-lexical/src/components/ui/file-selectors/UnsplashModal.tsx similarity index 100% rename from packages/koenig-lexical/src/components/ui/file-selectors/UnsplashModal.jsx rename to packages/koenig-lexical/src/components/ui/file-selectors/UnsplashModal.tsx diff --git a/packages/koenig-lexical/src/context/CardContext.jsx b/packages/koenig-lexical/src/context/CardContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/CardContext.jsx rename to packages/koenig-lexical/src/context/CardContext.tsx diff --git a/packages/koenig-lexical/src/context/KoenigComposerContext.jsx b/packages/koenig-lexical/src/context/KoenigComposerContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/KoenigComposerContext.jsx rename to packages/koenig-lexical/src/context/KoenigComposerContext.tsx diff --git a/packages/koenig-lexical/src/context/KoenigSelectedCardContext.jsx b/packages/koenig-lexical/src/context/KoenigSelectedCardContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/KoenigSelectedCardContext.jsx rename to packages/koenig-lexical/src/context/KoenigSelectedCardContext.tsx diff --git a/packages/koenig-lexical/src/context/SharedHistoryContext.jsx b/packages/koenig-lexical/src/context/SharedHistoryContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/SharedHistoryContext.jsx rename to packages/koenig-lexical/src/context/SharedHistoryContext.tsx diff --git a/packages/koenig-lexical/src/context/SharedOnChangeContext.jsx b/packages/koenig-lexical/src/context/SharedOnChangeContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/SharedOnChangeContext.jsx rename to packages/koenig-lexical/src/context/SharedOnChangeContext.tsx diff --git a/packages/koenig-lexical/src/context/TKContext.jsx b/packages/koenig-lexical/src/context/TKContext.tsx similarity index 100% rename from packages/koenig-lexical/src/context/TKContext.jsx rename to packages/koenig-lexical/src/context/TKContext.tsx diff --git a/packages/koenig-lexical/src/hooks/useCardDragAndDrop.js b/packages/koenig-lexical/src/hooks/useCardDragAndDrop.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useCardDragAndDrop.js rename to packages/koenig-lexical/src/hooks/useCardDragAndDrop.ts diff --git a/packages/koenig-lexical/src/hooks/useClickOutside.js b/packages/koenig-lexical/src/hooks/useClickOutside.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useClickOutside.js rename to packages/koenig-lexical/src/hooks/useClickOutside.ts diff --git a/packages/koenig-lexical/src/hooks/useFileDragAndDrop.js b/packages/koenig-lexical/src/hooks/useFileDragAndDrop.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useFileDragAndDrop.js rename to packages/koenig-lexical/src/hooks/useFileDragAndDrop.ts diff --git a/packages/koenig-lexical/src/hooks/useGalleryReorder.js b/packages/koenig-lexical/src/hooks/useGalleryReorder.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useGalleryReorder.js rename to packages/koenig-lexical/src/hooks/useGalleryReorder.ts diff --git a/packages/koenig-lexical/src/hooks/useInputSelection.js b/packages/koenig-lexical/src/hooks/useInputSelection.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useInputSelection.js rename to packages/koenig-lexical/src/hooks/useInputSelection.ts diff --git a/packages/koenig-lexical/src/hooks/useKoenigTextEntity.js b/packages/koenig-lexical/src/hooks/useKoenigTextEntity.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useKoenigTextEntity.js rename to packages/koenig-lexical/src/hooks/useKoenigTextEntity.ts diff --git a/packages/koenig-lexical/src/hooks/useMovable.js b/packages/koenig-lexical/src/hooks/useMovable.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useMovable.js rename to packages/koenig-lexical/src/hooks/useMovable.ts diff --git a/packages/koenig-lexical/src/hooks/usePinturaEditor.js b/packages/koenig-lexical/src/hooks/usePinturaEditor.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/usePinturaEditor.js rename to packages/koenig-lexical/src/hooks/usePinturaEditor.ts diff --git a/packages/koenig-lexical/src/hooks/usePreviousFocus.js b/packages/koenig-lexical/src/hooks/usePreviousFocus.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/usePreviousFocus.js rename to packages/koenig-lexical/src/hooks/usePreviousFocus.ts diff --git a/packages/koenig-lexical/src/hooks/useSearchLinks.js b/packages/koenig-lexical/src/hooks/useSearchLinks.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useSearchLinks.js rename to packages/koenig-lexical/src/hooks/useSearchLinks.ts diff --git a/packages/koenig-lexical/src/hooks/useSettingsPanelReposition.js b/packages/koenig-lexical/src/hooks/useSettingsPanelReposition.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useSettingsPanelReposition.js rename to packages/koenig-lexical/src/hooks/useSettingsPanelReposition.ts diff --git a/packages/koenig-lexical/src/hooks/useTypeaheadTriggerMatch.js b/packages/koenig-lexical/src/hooks/useTypeaheadTriggerMatch.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useTypeaheadTriggerMatch.js rename to packages/koenig-lexical/src/hooks/useTypeaheadTriggerMatch.ts diff --git a/packages/koenig-lexical/src/hooks/useVisibilityToggle.js b/packages/koenig-lexical/src/hooks/useVisibilityToggle.ts similarity index 100% rename from packages/koenig-lexical/src/hooks/useVisibilityToggle.js rename to packages/koenig-lexical/src/hooks/useVisibilityToggle.ts diff --git a/packages/koenig-lexical/src/index.js b/packages/koenig-lexical/src/index.ts similarity index 100% rename from packages/koenig-lexical/src/index.js rename to packages/koenig-lexical/src/index.ts diff --git a/packages/koenig-lexical/src/nodes/AsideNode.js b/packages/koenig-lexical/src/nodes/AsideNode.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/AsideNode.js rename to packages/koenig-lexical/src/nodes/AsideNode.ts diff --git a/packages/koenig-lexical/src/nodes/AudioNode.jsx b/packages/koenig-lexical/src/nodes/AudioNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/AudioNode.jsx rename to packages/koenig-lexical/src/nodes/AudioNode.tsx diff --git a/packages/koenig-lexical/src/nodes/AudioNodeComponent.jsx b/packages/koenig-lexical/src/nodes/AudioNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/AudioNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/AudioNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/BasicNodes.js b/packages/koenig-lexical/src/nodes/BasicNodes.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/BasicNodes.js rename to packages/koenig-lexical/src/nodes/BasicNodes.ts diff --git a/packages/koenig-lexical/src/nodes/BookmarkNode.jsx b/packages/koenig-lexical/src/nodes/BookmarkNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/BookmarkNode.jsx rename to packages/koenig-lexical/src/nodes/BookmarkNode.tsx diff --git a/packages/koenig-lexical/src/nodes/BookmarkNodeComponent.jsx b/packages/koenig-lexical/src/nodes/BookmarkNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/BookmarkNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/BookmarkNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/ButtonNode.jsx b/packages/koenig-lexical/src/nodes/ButtonNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ButtonNode.jsx rename to packages/koenig-lexical/src/nodes/ButtonNode.tsx diff --git a/packages/koenig-lexical/src/nodes/ButtonNodeComponent.jsx b/packages/koenig-lexical/src/nodes/ButtonNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ButtonNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/ButtonNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/CallToActionNode.jsx b/packages/koenig-lexical/src/nodes/CallToActionNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CallToActionNode.jsx rename to packages/koenig-lexical/src/nodes/CallToActionNode.tsx diff --git a/packages/koenig-lexical/src/nodes/CallToActionNodeComponent.jsx b/packages/koenig-lexical/src/nodes/CallToActionNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CallToActionNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/CallToActionNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/CalloutNode.jsx b/packages/koenig-lexical/src/nodes/CalloutNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CalloutNode.jsx rename to packages/koenig-lexical/src/nodes/CalloutNode.tsx diff --git a/packages/koenig-lexical/src/nodes/CalloutNodeComponent.jsx b/packages/koenig-lexical/src/nodes/CalloutNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CalloutNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/CalloutNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/CodeBlockNode.jsx b/packages/koenig-lexical/src/nodes/CodeBlockNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CodeBlockNode.jsx rename to packages/koenig-lexical/src/nodes/CodeBlockNode.tsx diff --git a/packages/koenig-lexical/src/nodes/CodeBlockNodeComponent.jsx b/packages/koenig-lexical/src/nodes/CodeBlockNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/CodeBlockNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/CodeBlockNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/DefaultNodes.js b/packages/koenig-lexical/src/nodes/DefaultNodes.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/DefaultNodes.js rename to packages/koenig-lexical/src/nodes/DefaultNodes.ts diff --git a/packages/koenig-lexical/src/nodes/EmailCtaNode.jsx b/packages/koenig-lexical/src/nodes/EmailCtaNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailCtaNode.jsx rename to packages/koenig-lexical/src/nodes/EmailCtaNode.tsx diff --git a/packages/koenig-lexical/src/nodes/EmailCtaNodeComponent.jsx b/packages/koenig-lexical/src/nodes/EmailCtaNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailCtaNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/EmailCtaNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/EmailEditorNodes.js b/packages/koenig-lexical/src/nodes/EmailEditorNodes.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailEditorNodes.js rename to packages/koenig-lexical/src/nodes/EmailEditorNodes.ts diff --git a/packages/koenig-lexical/src/nodes/EmailEmbedNode.jsx b/packages/koenig-lexical/src/nodes/EmailEmbedNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailEmbedNode.jsx rename to packages/koenig-lexical/src/nodes/EmailEmbedNode.tsx diff --git a/packages/koenig-lexical/src/nodes/EmailNode.jsx b/packages/koenig-lexical/src/nodes/EmailNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailNode.jsx rename to packages/koenig-lexical/src/nodes/EmailNode.tsx diff --git a/packages/koenig-lexical/src/nodes/EmailNodeComponent.jsx b/packages/koenig-lexical/src/nodes/EmailNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/EmailNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/EmailNodes.js b/packages/koenig-lexical/src/nodes/EmailNodes.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/EmailNodes.js rename to packages/koenig-lexical/src/nodes/EmailNodes.ts diff --git a/packages/koenig-lexical/src/nodes/EmbedNode.jsx b/packages/koenig-lexical/src/nodes/EmbedNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmbedNode.jsx rename to packages/koenig-lexical/src/nodes/EmbedNode.tsx diff --git a/packages/koenig-lexical/src/nodes/EmbedNodeComponent.jsx b/packages/koenig-lexical/src/nodes/EmbedNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/EmbedNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/EmbedNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/FileNode.jsx b/packages/koenig-lexical/src/nodes/FileNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/FileNode.jsx rename to packages/koenig-lexical/src/nodes/FileNode.tsx diff --git a/packages/koenig-lexical/src/nodes/FileNodeComponent.jsx b/packages/koenig-lexical/src/nodes/FileNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/FileNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/FileNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/GalleryNode.jsx b/packages/koenig-lexical/src/nodes/GalleryNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/GalleryNode.jsx rename to packages/koenig-lexical/src/nodes/GalleryNode.tsx diff --git a/packages/koenig-lexical/src/nodes/GalleryNodeComponent.jsx b/packages/koenig-lexical/src/nodes/GalleryNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/GalleryNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/GalleryNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/HeaderNode.jsx b/packages/koenig-lexical/src/nodes/HeaderNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/HeaderNode.jsx rename to packages/koenig-lexical/src/nodes/HeaderNode.tsx diff --git a/packages/koenig-lexical/src/nodes/HorizontalRuleNode.jsx b/packages/koenig-lexical/src/nodes/HorizontalRuleNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/HorizontalRuleNode.jsx rename to packages/koenig-lexical/src/nodes/HorizontalRuleNode.tsx diff --git a/packages/koenig-lexical/src/nodes/HtmlNode.jsx b/packages/koenig-lexical/src/nodes/HtmlNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/HtmlNode.jsx rename to packages/koenig-lexical/src/nodes/HtmlNode.tsx diff --git a/packages/koenig-lexical/src/nodes/HtmlNodeComponent.jsx b/packages/koenig-lexical/src/nodes/HtmlNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/HtmlNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/HtmlNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/ImageNode.jsx b/packages/koenig-lexical/src/nodes/ImageNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ImageNode.jsx rename to packages/koenig-lexical/src/nodes/ImageNode.tsx diff --git a/packages/koenig-lexical/src/nodes/ImageNodeComponent.jsx b/packages/koenig-lexical/src/nodes/ImageNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ImageNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/ImageNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/MarkdownNode.jsx b/packages/koenig-lexical/src/nodes/MarkdownNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/MarkdownNode.jsx rename to packages/koenig-lexical/src/nodes/MarkdownNode.tsx diff --git a/packages/koenig-lexical/src/nodes/MarkdownNodeComponent.jsx b/packages/koenig-lexical/src/nodes/MarkdownNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/MarkdownNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/MarkdownNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/MinimalNodes.js b/packages/koenig-lexical/src/nodes/MinimalNodes.ts similarity index 100% rename from packages/koenig-lexical/src/nodes/MinimalNodes.js rename to packages/koenig-lexical/src/nodes/MinimalNodes.ts diff --git a/packages/koenig-lexical/src/nodes/PaywallNode.jsx b/packages/koenig-lexical/src/nodes/PaywallNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/PaywallNode.jsx rename to packages/koenig-lexical/src/nodes/PaywallNode.tsx diff --git a/packages/koenig-lexical/src/nodes/ProductNode.jsx b/packages/koenig-lexical/src/nodes/ProductNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ProductNode.jsx rename to packages/koenig-lexical/src/nodes/ProductNode.tsx diff --git a/packages/koenig-lexical/src/nodes/ProductNodeComponent.jsx b/packages/koenig-lexical/src/nodes/ProductNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ProductNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/ProductNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/SignupNode.jsx b/packages/koenig-lexical/src/nodes/SignupNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/SignupNode.jsx rename to packages/koenig-lexical/src/nodes/SignupNode.tsx diff --git a/packages/koenig-lexical/src/nodes/SignupNodeComponent.jsx b/packages/koenig-lexical/src/nodes/SignupNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/SignupNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/SignupNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/ToggleNode.jsx b/packages/koenig-lexical/src/nodes/ToggleNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ToggleNode.jsx rename to packages/koenig-lexical/src/nodes/ToggleNode.tsx diff --git a/packages/koenig-lexical/src/nodes/ToggleNodeComponent.jsx b/packages/koenig-lexical/src/nodes/ToggleNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/ToggleNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/ToggleNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/TransistorNode.jsx b/packages/koenig-lexical/src/nodes/TransistorNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/TransistorNode.jsx rename to packages/koenig-lexical/src/nodes/TransistorNode.tsx diff --git a/packages/koenig-lexical/src/nodes/TransistorNodeComponent.jsx b/packages/koenig-lexical/src/nodes/TransistorNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/TransistorNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/TransistorNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/VideoNode.jsx b/packages/koenig-lexical/src/nodes/VideoNode.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/VideoNode.jsx rename to packages/koenig-lexical/src/nodes/VideoNode.tsx diff --git a/packages/koenig-lexical/src/nodes/VideoNodeComponent.jsx b/packages/koenig-lexical/src/nodes/VideoNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/VideoNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/VideoNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/header/v1/HeaderNodeComponent.jsx b/packages/koenig-lexical/src/nodes/header/v1/HeaderNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/header/v1/HeaderNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/header/v1/HeaderNodeComponent.tsx diff --git a/packages/koenig-lexical/src/nodes/header/v2/HeaderNodeComponent.jsx b/packages/koenig-lexical/src/nodes/header/v2/HeaderNodeComponent.tsx similarity index 100% rename from packages/koenig-lexical/src/nodes/header/v2/HeaderNodeComponent.jsx rename to packages/koenig-lexical/src/nodes/header/v2/HeaderNodeComponent.tsx diff --git a/packages/koenig-lexical/src/plugins/AllDefaultPlugins.jsx b/packages/koenig-lexical/src/plugins/AllDefaultPlugins.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/AllDefaultPlugins.jsx rename to packages/koenig-lexical/src/plugins/AllDefaultPlugins.tsx diff --git a/packages/koenig-lexical/src/plugins/AtLinkPlugin.jsx b/packages/koenig-lexical/src/plugins/AtLinkPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/AtLinkPlugin.jsx rename to packages/koenig-lexical/src/plugins/AtLinkPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/AudioPlugin.jsx b/packages/koenig-lexical/src/plugins/AudioPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/AudioPlugin.jsx rename to packages/koenig-lexical/src/plugins/AudioPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/BookmarkPlugin.jsx b/packages/koenig-lexical/src/plugins/BookmarkPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/BookmarkPlugin.jsx rename to packages/koenig-lexical/src/plugins/BookmarkPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/ButtonPlugin.jsx b/packages/koenig-lexical/src/plugins/ButtonPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/ButtonPlugin.jsx rename to packages/koenig-lexical/src/plugins/ButtonPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/CallToActionPlugin.jsx b/packages/koenig-lexical/src/plugins/CallToActionPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/CallToActionPlugin.jsx rename to packages/koenig-lexical/src/plugins/CallToActionPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/CalloutPlugin.jsx b/packages/koenig-lexical/src/plugins/CalloutPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/CalloutPlugin.jsx rename to packages/koenig-lexical/src/plugins/CalloutPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/CardMenuPlugin.jsx b/packages/koenig-lexical/src/plugins/CardMenuPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/CardMenuPlugin.jsx rename to packages/koenig-lexical/src/plugins/CardMenuPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/DragDropPastePlugin.jsx b/packages/koenig-lexical/src/plugins/DragDropPastePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/DragDropPastePlugin.jsx rename to packages/koenig-lexical/src/plugins/DragDropPastePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/DragDropReorderPlugin.jsx b/packages/koenig-lexical/src/plugins/DragDropReorderPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/DragDropReorderPlugin.jsx rename to packages/koenig-lexical/src/plugins/DragDropReorderPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/EmEnDashPlugin.jsx b/packages/koenig-lexical/src/plugins/EmEnDashPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/EmEnDashPlugin.jsx rename to packages/koenig-lexical/src/plugins/EmEnDashPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/EmailCtaPlugin.jsx b/packages/koenig-lexical/src/plugins/EmailCtaPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/EmailCtaPlugin.jsx rename to packages/koenig-lexical/src/plugins/EmailCtaPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/EmailPlugin.jsx b/packages/koenig-lexical/src/plugins/EmailPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/EmailPlugin.jsx rename to packages/koenig-lexical/src/plugins/EmailPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/EmbedPlugin.jsx b/packages/koenig-lexical/src/plugins/EmbedPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/EmbedPlugin.jsx rename to packages/koenig-lexical/src/plugins/EmbedPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/EmojiPickerPlugin.jsx b/packages/koenig-lexical/src/plugins/EmojiPickerPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/EmojiPickerPlugin.jsx rename to packages/koenig-lexical/src/plugins/EmojiPickerPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/ExternalControlPlugin.jsx b/packages/koenig-lexical/src/plugins/ExternalControlPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/ExternalControlPlugin.jsx rename to packages/koenig-lexical/src/plugins/ExternalControlPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/FilePlugin.jsx b/packages/koenig-lexical/src/plugins/FilePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/FilePlugin.jsx rename to packages/koenig-lexical/src/plugins/FilePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/FloatingToolbarPlugin.jsx b/packages/koenig-lexical/src/plugins/FloatingToolbarPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/FloatingToolbarPlugin.jsx rename to packages/koenig-lexical/src/plugins/FloatingToolbarPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/GalleryPlugin.jsx b/packages/koenig-lexical/src/plugins/GalleryPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/GalleryPlugin.jsx rename to packages/koenig-lexical/src/plugins/GalleryPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/HeaderPlugin.jsx b/packages/koenig-lexical/src/plugins/HeaderPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/HeaderPlugin.jsx rename to packages/koenig-lexical/src/plugins/HeaderPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/HorizontalRulePlugin.jsx b/packages/koenig-lexical/src/plugins/HorizontalRulePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/HorizontalRulePlugin.jsx rename to packages/koenig-lexical/src/plugins/HorizontalRulePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/HtmlOutputPlugin.jsx b/packages/koenig-lexical/src/plugins/HtmlOutputPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/HtmlOutputPlugin.jsx rename to packages/koenig-lexical/src/plugins/HtmlOutputPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/HtmlPlugin.jsx b/packages/koenig-lexical/src/plugins/HtmlPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/HtmlPlugin.jsx rename to packages/koenig-lexical/src/plugins/HtmlPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/ImagePlugin.jsx b/packages/koenig-lexical/src/plugins/ImagePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/ImagePlugin.jsx rename to packages/koenig-lexical/src/plugins/ImagePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigBehaviourPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigBehaviourPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigBehaviourPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigBehaviourPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigBlurPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigBlurPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigBlurPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigBlurPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigFocusPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigFocusPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigFocusPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigFocusPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigNestedEditorPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigNestedEditorPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigNestedEditorPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigNestedEditorPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigSelectorPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigSelectorPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigSelectorPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigSelectorPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/KoenigSnippetPlugin.jsx b/packages/koenig-lexical/src/plugins/KoenigSnippetPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/KoenigSnippetPlugin.jsx rename to packages/koenig-lexical/src/plugins/KoenigSnippetPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/MarkdownPastePlugin.jsx b/packages/koenig-lexical/src/plugins/MarkdownPastePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/MarkdownPastePlugin.jsx rename to packages/koenig-lexical/src/plugins/MarkdownPastePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/MarkdownPlugin.jsx b/packages/koenig-lexical/src/plugins/MarkdownPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/MarkdownPlugin.jsx rename to packages/koenig-lexical/src/plugins/MarkdownPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/MarkdownShortcutPlugin.jsx b/packages/koenig-lexical/src/plugins/MarkdownShortcutPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/MarkdownShortcutPlugin.jsx rename to packages/koenig-lexical/src/plugins/MarkdownShortcutPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/PaywallPlugin.jsx b/packages/koenig-lexical/src/plugins/PaywallPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/PaywallPlugin.jsx rename to packages/koenig-lexical/src/plugins/PaywallPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/PlusCardMenuPlugin.jsx b/packages/koenig-lexical/src/plugins/PlusCardMenuPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/PlusCardMenuPlugin.jsx rename to packages/koenig-lexical/src/plugins/PlusCardMenuPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/ProductPlugin.jsx b/packages/koenig-lexical/src/plugins/ProductPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/ProductPlugin.jsx rename to packages/koenig-lexical/src/plugins/ProductPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/ReplacementStringsPlugin.jsx b/packages/koenig-lexical/src/plugins/ReplacementStringsPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/ReplacementStringsPlugin.jsx rename to packages/koenig-lexical/src/plugins/ReplacementStringsPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/RestrictContentPlugin.jsx b/packages/koenig-lexical/src/plugins/RestrictContentPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/RestrictContentPlugin.jsx rename to packages/koenig-lexical/src/plugins/RestrictContentPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/SignupPlugin.jsx b/packages/koenig-lexical/src/plugins/SignupPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/SignupPlugin.jsx rename to packages/koenig-lexical/src/plugins/SignupPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/SlashCardMenuPlugin.jsx b/packages/koenig-lexical/src/plugins/SlashCardMenuPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/SlashCardMenuPlugin.jsx rename to packages/koenig-lexical/src/plugins/SlashCardMenuPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/TKCountPlugin.jsx b/packages/koenig-lexical/src/plugins/TKCountPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/TKCountPlugin.jsx rename to packages/koenig-lexical/src/plugins/TKCountPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/TKPlugin.jsx b/packages/koenig-lexical/src/plugins/TKPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/TKPlugin.jsx rename to packages/koenig-lexical/src/plugins/TKPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/TogglePlugin.jsx b/packages/koenig-lexical/src/plugins/TogglePlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/TogglePlugin.jsx rename to packages/koenig-lexical/src/plugins/TogglePlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/TransistorPlugin.jsx b/packages/koenig-lexical/src/plugins/TransistorPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/TransistorPlugin.jsx rename to packages/koenig-lexical/src/plugins/TransistorPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/VideoPlugin.jsx b/packages/koenig-lexical/src/plugins/VideoPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/VideoPlugin.jsx rename to packages/koenig-lexical/src/plugins/VideoPlugin.tsx diff --git a/packages/koenig-lexical/src/plugins/WordCountPlugin.jsx b/packages/koenig-lexical/src/plugins/WordCountPlugin.tsx similarity index 100% rename from packages/koenig-lexical/src/plugins/WordCountPlugin.jsx rename to packages/koenig-lexical/src/plugins/WordCountPlugin.tsx diff --git a/packages/koenig-lexical/src/themes/default.js b/packages/koenig-lexical/src/themes/default.ts similarity index 100% rename from packages/koenig-lexical/src/themes/default.js rename to packages/koenig-lexical/src/themes/default.ts diff --git a/packages/koenig-lexical/src/utils/$getSelectionRangeRect.js b/packages/koenig-lexical/src/utils/$getSelectionRangeRect.ts similarity index 100% rename from packages/koenig-lexical/src/utils/$getSelectionRangeRect.js rename to packages/koenig-lexical/src/utils/$getSelectionRangeRect.ts diff --git a/packages/koenig-lexical/src/utils/$insertAndSelectNode.js b/packages/koenig-lexical/src/utils/$insertAndSelectNode.ts similarity index 100% rename from packages/koenig-lexical/src/utils/$insertAndSelectNode.js rename to packages/koenig-lexical/src/utils/$insertAndSelectNode.ts diff --git a/packages/koenig-lexical/src/utils/$isAtStartOfDocument.js b/packages/koenig-lexical/src/utils/$isAtStartOfDocument.ts similarity index 100% rename from packages/koenig-lexical/src/utils/$isAtStartOfDocument.js rename to packages/koenig-lexical/src/utils/$isAtStartOfDocument.ts diff --git a/packages/koenig-lexical/src/utils/$isAtTopOfNode.js b/packages/koenig-lexical/src/utils/$isAtTopOfNode.ts similarity index 100% rename from packages/koenig-lexical/src/utils/$isAtTopOfNode.js rename to packages/koenig-lexical/src/utils/$isAtTopOfNode.ts diff --git a/packages/koenig-lexical/src/utils/$selectDecoratorNode.js b/packages/koenig-lexical/src/utils/$selectDecoratorNode.ts similarity index 100% rename from packages/koenig-lexical/src/utils/$selectDecoratorNode.js rename to packages/koenig-lexical/src/utils/$selectDecoratorNode.ts diff --git a/packages/koenig-lexical/src/utils/analytics.js b/packages/koenig-lexical/src/utils/analytics.ts similarity index 100% rename from packages/koenig-lexical/src/utils/analytics.js rename to packages/koenig-lexical/src/utils/analytics.ts diff --git a/packages/koenig-lexical/src/utils/audioUploadHandler.js b/packages/koenig-lexical/src/utils/audioUploadHandler.ts similarity index 100% rename from packages/koenig-lexical/src/utils/audioUploadHandler.js rename to packages/koenig-lexical/src/utils/audioUploadHandler.ts diff --git a/packages/koenig-lexical/src/utils/autoExpandTextArea.js b/packages/koenig-lexical/src/utils/autoExpandTextArea.ts similarity index 100% rename from packages/koenig-lexical/src/utils/autoExpandTextArea.js rename to packages/koenig-lexical/src/utils/autoExpandTextArea.ts diff --git a/packages/koenig-lexical/src/utils/buildCardMenu.js b/packages/koenig-lexical/src/utils/buildCardMenu.ts similarity index 100% rename from packages/koenig-lexical/src/utils/buildCardMenu.js rename to packages/koenig-lexical/src/utils/buildCardMenu.ts diff --git a/packages/koenig-lexical/src/utils/callToActionColors.js b/packages/koenig-lexical/src/utils/callToActionColors.ts similarity index 100% rename from packages/koenig-lexical/src/utils/callToActionColors.js rename to packages/koenig-lexical/src/utils/callToActionColors.ts diff --git a/packages/koenig-lexical/src/utils/codemirror-config.js b/packages/koenig-lexical/src/utils/codemirror-config.ts similarity index 100% rename from packages/koenig-lexical/src/utils/codemirror-config.js rename to packages/koenig-lexical/src/utils/codemirror-config.ts diff --git a/packages/koenig-lexical/src/utils/constants.js b/packages/koenig-lexical/src/utils/constants.ts similarity index 100% rename from packages/koenig-lexical/src/utils/constants.js rename to packages/koenig-lexical/src/utils/constants.ts diff --git a/packages/koenig-lexical/src/utils/ctrlOrCmd.js b/packages/koenig-lexical/src/utils/ctrlOrCmd.ts similarity index 100% rename from packages/koenig-lexical/src/utils/ctrlOrCmd.js rename to packages/koenig-lexical/src/utils/ctrlOrCmd.ts diff --git a/packages/koenig-lexical/src/utils/dataSrcToFile.js b/packages/koenig-lexical/src/utils/dataSrcToFile.ts similarity index 100% rename from packages/koenig-lexical/src/utils/dataSrcToFile.js rename to packages/koenig-lexical/src/utils/dataSrcToFile.ts diff --git a/packages/koenig-lexical/src/utils/draggable/DragDropContainer.js b/packages/koenig-lexical/src/utils/draggable/DragDropContainer.ts similarity index 100% rename from packages/koenig-lexical/src/utils/draggable/DragDropContainer.js rename to packages/koenig-lexical/src/utils/draggable/DragDropContainer.ts diff --git a/packages/koenig-lexical/src/utils/draggable/DragDropHandler.jsx b/packages/koenig-lexical/src/utils/draggable/DragDropHandler.tsx similarity index 100% rename from packages/koenig-lexical/src/utils/draggable/DragDropHandler.jsx rename to packages/koenig-lexical/src/utils/draggable/DragDropHandler.tsx diff --git a/packages/koenig-lexical/src/utils/draggable/ScrollHandler.js b/packages/koenig-lexical/src/utils/draggable/ScrollHandler.ts similarity index 100% rename from packages/koenig-lexical/src/utils/draggable/ScrollHandler.js rename to packages/koenig-lexical/src/utils/draggable/ScrollHandler.ts diff --git a/packages/koenig-lexical/src/utils/draggable/draggable-constants.js b/packages/koenig-lexical/src/utils/draggable/draggable-constants.ts similarity index 100% rename from packages/koenig-lexical/src/utils/draggable/draggable-constants.js rename to packages/koenig-lexical/src/utils/draggable/draggable-constants.ts diff --git a/packages/koenig-lexical/src/utils/draggable/draggable-utils.js b/packages/koenig-lexical/src/utils/draggable/draggable-utils.ts similarity index 100% rename from packages/koenig-lexical/src/utils/draggable/draggable-utils.js rename to packages/koenig-lexical/src/utils/draggable/draggable-utils.ts diff --git a/packages/koenig-lexical/src/utils/extractVideoMetadata.js b/packages/koenig-lexical/src/utils/extractVideoMetadata.ts similarity index 100% rename from packages/koenig-lexical/src/utils/extractVideoMetadata.js rename to packages/koenig-lexical/src/utils/extractVideoMetadata.ts diff --git a/packages/koenig-lexical/src/utils/fileUploadHandler.js b/packages/koenig-lexical/src/utils/fileUploadHandler.ts similarity index 100% rename from packages/koenig-lexical/src/utils/fileUploadHandler.js rename to packages/koenig-lexical/src/utils/fileUploadHandler.ts diff --git a/packages/koenig-lexical/src/utils/generateEditorState.js b/packages/koenig-lexical/src/utils/generateEditorState.ts similarity index 100% rename from packages/koenig-lexical/src/utils/generateEditorState.js rename to packages/koenig-lexical/src/utils/generateEditorState.ts diff --git a/packages/koenig-lexical/src/utils/getAccentColor.js b/packages/koenig-lexical/src/utils/getAccentColor.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getAccentColor.js rename to packages/koenig-lexical/src/utils/getAccentColor.ts diff --git a/packages/koenig-lexical/src/utils/getAudioMetadata.js b/packages/koenig-lexical/src/utils/getAudioMetadata.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getAudioMetadata.js rename to packages/koenig-lexical/src/utils/getAudioMetadata.ts diff --git a/packages/koenig-lexical/src/utils/getDOMRangeRect.js b/packages/koenig-lexical/src/utils/getDOMRangeRect.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getDOMRangeRect.js rename to packages/koenig-lexical/src/utils/getDOMRangeRect.ts diff --git a/packages/koenig-lexical/src/utils/getEditorCardNodes.js b/packages/koenig-lexical/src/utils/getEditorCardNodes.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getEditorCardNodes.js rename to packages/koenig-lexical/src/utils/getEditorCardNodes.ts diff --git a/packages/koenig-lexical/src/utils/getImageDimensions.js b/packages/koenig-lexical/src/utils/getImageDimensions.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getImageDimensions.js rename to packages/koenig-lexical/src/utils/getImageDimensions.ts diff --git a/packages/koenig-lexical/src/utils/getImageFilenameFromSrc.js b/packages/koenig-lexical/src/utils/getImageFilenameFromSrc.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getImageFilenameFromSrc.js rename to packages/koenig-lexical/src/utils/getImageFilenameFromSrc.ts diff --git a/packages/koenig-lexical/src/utils/getScrollParent.js b/packages/koenig-lexical/src/utils/getScrollParent.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getScrollParent.js rename to packages/koenig-lexical/src/utils/getScrollParent.ts diff --git a/packages/koenig-lexical/src/utils/getSelectedNode.js b/packages/koenig-lexical/src/utils/getSelectedNode.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getSelectedNode.js rename to packages/koenig-lexical/src/utils/getSelectedNode.ts diff --git a/packages/koenig-lexical/src/utils/getTopLevelNativeElement.js b/packages/koenig-lexical/src/utils/getTopLevelNativeElement.ts similarity index 100% rename from packages/koenig-lexical/src/utils/getTopLevelNativeElement.js rename to packages/koenig-lexical/src/utils/getTopLevelNativeElement.ts diff --git a/packages/koenig-lexical/src/utils/image-card-widths.js b/packages/koenig-lexical/src/utils/image-card-widths.ts similarity index 100% rename from packages/koenig-lexical/src/utils/image-card-widths.js rename to packages/koenig-lexical/src/utils/image-card-widths.ts diff --git a/packages/koenig-lexical/src/utils/imageUploadHandler.js b/packages/koenig-lexical/src/utils/imageUploadHandler.ts similarity index 100% rename from packages/koenig-lexical/src/utils/imageUploadHandler.js rename to packages/koenig-lexical/src/utils/imageUploadHandler.ts diff --git a/packages/koenig-lexical/src/utils/index.js b/packages/koenig-lexical/src/utils/index.ts similarity index 100% rename from packages/koenig-lexical/src/utils/index.js rename to packages/koenig-lexical/src/utils/index.ts diff --git a/packages/koenig-lexical/src/utils/isEditorEmpty.js b/packages/koenig-lexical/src/utils/isEditorEmpty.ts similarity index 100% rename from packages/koenig-lexical/src/utils/isEditorEmpty.js rename to packages/koenig-lexical/src/utils/isEditorEmpty.ts diff --git a/packages/koenig-lexical/src/utils/isGif.js b/packages/koenig-lexical/src/utils/isGif.ts similarity index 100% rename from packages/koenig-lexical/src/utils/isGif.js rename to packages/koenig-lexical/src/utils/isGif.ts diff --git a/packages/koenig-lexical/src/utils/isInternalUrl.js b/packages/koenig-lexical/src/utils/isInternalUrl.ts similarity index 100% rename from packages/koenig-lexical/src/utils/isInternalUrl.js rename to packages/koenig-lexical/src/utils/isInternalUrl.ts diff --git a/packages/koenig-lexical/src/utils/nested-editors.js b/packages/koenig-lexical/src/utils/nested-editors.ts similarity index 100% rename from packages/koenig-lexical/src/utils/nested-editors.js rename to packages/koenig-lexical/src/utils/nested-editors.ts diff --git a/packages/koenig-lexical/src/utils/openFileSelection.js b/packages/koenig-lexical/src/utils/openFileSelection.ts similarity index 100% rename from packages/koenig-lexical/src/utils/openFileSelection.js rename to packages/koenig-lexical/src/utils/openFileSelection.ts diff --git a/packages/koenig-lexical/src/utils/prettifyFileName.js b/packages/koenig-lexical/src/utils/prettifyFileName.ts similarity index 100% rename from packages/koenig-lexical/src/utils/prettifyFileName.js rename to packages/koenig-lexical/src/utils/prettifyFileName.ts diff --git a/packages/koenig-lexical/src/utils/sanitize-html.js b/packages/koenig-lexical/src/utils/sanitize-html.ts similarity index 100% rename from packages/koenig-lexical/src/utils/sanitize-html.js rename to packages/koenig-lexical/src/utils/sanitize-html.ts diff --git a/packages/koenig-lexical/src/utils/services/gif.js b/packages/koenig-lexical/src/utils/services/gif.ts similarity index 100% rename from packages/koenig-lexical/src/utils/services/gif.js rename to packages/koenig-lexical/src/utils/services/gif.ts diff --git a/packages/koenig-lexical/src/utils/setFloatingElemPosition.js b/packages/koenig-lexical/src/utils/setFloatingElemPosition.ts similarity index 100% rename from packages/koenig-lexical/src/utils/setFloatingElemPosition.js rename to packages/koenig-lexical/src/utils/setFloatingElemPosition.ts diff --git a/packages/koenig-lexical/src/utils/shortcutSymbols.js b/packages/koenig-lexical/src/utils/shortcutSymbols.ts similarity index 100% rename from packages/koenig-lexical/src/utils/shortcutSymbols.js rename to packages/koenig-lexical/src/utils/shortcutSymbols.ts diff --git a/packages/koenig-lexical/src/utils/shouldIgnoreEvent.js b/packages/koenig-lexical/src/utils/shouldIgnoreEvent.ts similarity index 100% rename from packages/koenig-lexical/src/utils/shouldIgnoreEvent.js rename to packages/koenig-lexical/src/utils/shouldIgnoreEvent.ts diff --git a/packages/koenig-lexical/src/utils/storybook/populate-storybook-editor.js b/packages/koenig-lexical/src/utils/storybook/populate-storybook-editor.ts similarity index 100% rename from packages/koenig-lexical/src/utils/storybook/populate-storybook-editor.js rename to packages/koenig-lexical/src/utils/storybook/populate-storybook-editor.ts diff --git a/packages/koenig-lexical/src/utils/thumbnailUploadHandler.js b/packages/koenig-lexical/src/utils/thumbnailUploadHandler.ts similarity index 100% rename from packages/koenig-lexical/src/utils/thumbnailUploadHandler.js rename to packages/koenig-lexical/src/utils/thumbnailUploadHandler.ts diff --git a/packages/koenig-lexical/src/utils/visibility.js b/packages/koenig-lexical/src/utils/visibility.ts similarity index 100% rename from packages/koenig-lexical/src/utils/visibility.js rename to packages/koenig-lexical/src/utils/visibility.ts diff --git a/packages/koenig-lexical/svgo.config.js b/packages/koenig-lexical/svgo.config.cjs similarity index 100% rename from packages/koenig-lexical/svgo.config.js rename to packages/koenig-lexical/svgo.config.cjs diff --git a/packages/koenig-lexical/test/e2e/card-behaviour.test.js b/packages/koenig-lexical/test/e2e/card-behaviour.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/card-behaviour.test.js rename to packages/koenig-lexical/test/e2e/card-behaviour.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/audio-card.test.js b/packages/koenig-lexical/test/e2e/cards/audio-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/audio-card.test.js rename to packages/koenig-lexical/test/e2e/cards/audio-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/bookmark-card-with-search.test.js b/packages/koenig-lexical/test/e2e/cards/bookmark-card-with-search.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/bookmark-card-with-search.test.js rename to packages/koenig-lexical/test/e2e/cards/bookmark-card-with-search.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/bookmark-card-without-search.test.js b/packages/koenig-lexical/test/e2e/cards/bookmark-card-without-search.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/bookmark-card-without-search.test.js rename to packages/koenig-lexical/test/e2e/cards/bookmark-card-without-search.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/button-card.test.js b/packages/koenig-lexical/test/e2e/cards/button-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/button-card.test.js rename to packages/koenig-lexical/test/e2e/cards/button-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/call-to-action-card.test.js b/packages/koenig-lexical/test/e2e/cards/call-to-action-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/call-to-action-card.test.js rename to packages/koenig-lexical/test/e2e/cards/call-to-action-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/callout-card.test.js b/packages/koenig-lexical/test/e2e/cards/callout-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/callout-card.test.js rename to packages/koenig-lexical/test/e2e/cards/callout-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/code-block-card.test.js b/packages/koenig-lexical/test/e2e/cards/code-block-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/code-block-card.test.js rename to packages/koenig-lexical/test/e2e/cards/code-block-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/email-card.test.js b/packages/koenig-lexical/test/e2e/cards/email-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/email-card.test.js rename to packages/koenig-lexical/test/e2e/cards/email-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/email-cta-card.test.js b/packages/koenig-lexical/test/e2e/cards/email-cta-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/email-cta-card.test.js rename to packages/koenig-lexical/test/e2e/cards/email-cta-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/embed-card.test.js b/packages/koenig-lexical/test/e2e/cards/embed-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/embed-card.test.js rename to packages/koenig-lexical/test/e2e/cards/embed-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/file-card.test.js b/packages/koenig-lexical/test/e2e/cards/file-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/file-card.test.js rename to packages/koenig-lexical/test/e2e/cards/file-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/gallery-card.test.js b/packages/koenig-lexical/test/e2e/cards/gallery-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/gallery-card.test.js rename to packages/koenig-lexical/test/e2e/cards/gallery-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/header-card.test.js b/packages/koenig-lexical/test/e2e/cards/header-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/header-card.test.js rename to packages/koenig-lexical/test/e2e/cards/header-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/html-card.test.js b/packages/koenig-lexical/test/e2e/cards/html-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/html-card.test.js rename to packages/koenig-lexical/test/e2e/cards/html-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/image-card.test.js b/packages/koenig-lexical/test/e2e/cards/image-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/image-card.test.js rename to packages/koenig-lexical/test/e2e/cards/image-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/markdown-card.test.js b/packages/koenig-lexical/test/e2e/cards/markdown-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/markdown-card.test.js rename to packages/koenig-lexical/test/e2e/cards/markdown-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/paywall-card.test.js b/packages/koenig-lexical/test/e2e/cards/paywall-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/paywall-card.test.js rename to packages/koenig-lexical/test/e2e/cards/paywall-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/product-card.test.js b/packages/koenig-lexical/test/e2e/cards/product-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/product-card.test.js rename to packages/koenig-lexical/test/e2e/cards/product-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/signup-card.test.js b/packages/koenig-lexical/test/e2e/cards/signup-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/signup-card.test.js rename to packages/koenig-lexical/test/e2e/cards/signup-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/toggle-card.test.js b/packages/koenig-lexical/test/e2e/cards/toggle-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/toggle-card.test.js rename to packages/koenig-lexical/test/e2e/cards/toggle-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/transistor-card.test.js b/packages/koenig-lexical/test/e2e/cards/transistor-card.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/transistor-card.test.js rename to packages/koenig-lexical/test/e2e/cards/transistor-card.test.ts diff --git a/packages/koenig-lexical/test/e2e/cards/video-card.firefox.test.js b/packages/koenig-lexical/test/e2e/cards/video-card.firefox.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/cards/video-card.firefox.test.js rename to packages/koenig-lexical/test/e2e/cards/video-card.firefox.test.ts diff --git a/packages/koenig-lexical/test/e2e/content-visibility.test.js b/packages/koenig-lexical/test/e2e/content-visibility.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/content-visibility.test.js rename to packages/koenig-lexical/test/e2e/content-visibility.test.ts diff --git a/packages/koenig-lexical/test/e2e/editors/basic-editor.test.js b/packages/koenig-lexical/test/e2e/editors/basic-editor.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/editors/basic-editor.test.js rename to packages/koenig-lexical/test/e2e/editors/basic-editor.test.ts diff --git a/packages/koenig-lexical/test/e2e/editors/email-editor.test.js b/packages/koenig-lexical/test/e2e/editors/email-editor.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/editors/email-editor.test.js rename to packages/koenig-lexical/test/e2e/editors/email-editor.test.ts diff --git a/packages/koenig-lexical/test/e2e/editors/minimal-editor.test.js b/packages/koenig-lexical/test/e2e/editors/minimal-editor.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/editors/minimal-editor.test.js rename to packages/koenig-lexical/test/e2e/editors/minimal-editor.test.ts diff --git a/packages/koenig-lexical/test/e2e/floating-toolbar.test.js b/packages/koenig-lexical/test/e2e/floating-toolbar.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/floating-toolbar.test.js rename to packages/koenig-lexical/test/e2e/floating-toolbar.test.ts diff --git a/packages/koenig-lexical/test/e2e/format-shortcuts.test.js b/packages/koenig-lexical/test/e2e/format-shortcuts.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/format-shortcuts.test.js rename to packages/koenig-lexical/test/e2e/format-shortcuts.test.ts diff --git a/packages/koenig-lexical/test/e2e/linking.test.js b/packages/koenig-lexical/test/e2e/linking.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/linking.test.js rename to packages/koenig-lexical/test/e2e/linking.test.ts diff --git a/packages/koenig-lexical/test/e2e/list-behaviour.test.js b/packages/koenig-lexical/test/e2e/list-behaviour.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/list-behaviour.test.js rename to packages/koenig-lexical/test/e2e/list-behaviour.test.ts diff --git a/packages/koenig-lexical/test/e2e/modals/UnsplashSelector.test.js b/packages/koenig-lexical/test/e2e/modals/UnsplashSelector.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/modals/UnsplashSelector.test.js rename to packages/koenig-lexical/test/e2e/modals/UnsplashSelector.test.ts diff --git a/packages/koenig-lexical/test/e2e/node-transforms.test.js b/packages/koenig-lexical/test/e2e/node-transforms.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/node-transforms.test.js rename to packages/koenig-lexical/test/e2e/node-transforms.test.ts diff --git a/packages/koenig-lexical/test/e2e/paste-behaviour.test.js b/packages/koenig-lexical/test/e2e/paste-behaviour.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/paste-behaviour.test.js rename to packages/koenig-lexical/test/e2e/paste-behaviour.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.firefox.test.js b/packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.firefox.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.firefox.test.js rename to packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.firefox.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/DragDropPastePlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/DragDropReorderPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/DragDropReorderPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/DragDropReorderPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/DragDropReorderPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/EmojiPickerPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/EmojiPickerPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/EmojiPickerPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/EmojiPickerPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/HtmlOutputPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/HtmlOutputPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/HtmlOutputPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/HtmlOutputPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/KoenigSnippetPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/KoenigSnippetPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/KoenigSnippetPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/KoenigSnippetPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/ReplacementStringsPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/ReplacementStringsPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/ReplacementStringsPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/ReplacementStringsPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/RestrictContentPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/RestrictContentPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/RestrictContentPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/RestrictContentPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/TKPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/TKPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/TKPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/TKPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plugins/WordCountPlugin.test.js b/packages/koenig-lexical/test/e2e/plugins/WordCountPlugin.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plugins/WordCountPlugin.test.js rename to packages/koenig-lexical/test/e2e/plugins/WordCountPlugin.test.ts diff --git a/packages/koenig-lexical/test/e2e/plus-button.test.js b/packages/koenig-lexical/test/e2e/plus-button.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/plus-button.test.js rename to packages/koenig-lexical/test/e2e/plus-button.test.ts diff --git a/packages/koenig-lexical/test/e2e/selection.test.js b/packages/koenig-lexical/test/e2e/selection.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/selection.test.js rename to packages/koenig-lexical/test/e2e/selection.test.ts diff --git a/packages/koenig-lexical/test/e2e/slash-menu.test.js b/packages/koenig-lexical/test/e2e/slash-menu.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/slash-menu.test.js rename to packages/koenig-lexical/test/e2e/slash-menu.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/code-block.test.js b/packages/koenig-lexical/test/e2e/text-transforms/code-block.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/code-block.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/code-block.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/emdash-endash.test.js b/packages/koenig-lexical/test/e2e/text-transforms/emdash-endash.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/emdash-endash.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/emdash-endash.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/headings.test.js b/packages/koenig-lexical/test/e2e/text-transforms/headings.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/headings.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/headings.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/horizontal-line-rule.test.js b/packages/koenig-lexical/test/e2e/text-transforms/horizontal-line-rule.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/horizontal-line-rule.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/horizontal-line-rule.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/links.test.js b/packages/koenig-lexical/test/e2e/text-transforms/links.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/links.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/links.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/markdown.test.js b/packages/koenig-lexical/test/e2e/text-transforms/markdown.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/markdown.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/markdown.test.ts diff --git a/packages/koenig-lexical/test/e2e/text-transforms/paywall.test.js b/packages/koenig-lexical/test/e2e/text-transforms/paywall.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/text-transforms/paywall.test.js rename to packages/koenig-lexical/test/e2e/text-transforms/paywall.test.ts diff --git a/packages/koenig-lexical/test/e2e/title-behaviour.test.js b/packages/koenig-lexical/test/e2e/title-behaviour.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/title-behaviour.test.js rename to packages/koenig-lexical/test/e2e/title-behaviour.test.ts diff --git a/packages/koenig-lexical/test/e2e/utils/getImageDimensions.test.js b/packages/koenig-lexical/test/e2e/utils/getImageDimensions.test.ts similarity index 100% rename from packages/koenig-lexical/test/e2e/utils/getImageDimensions.test.js rename to packages/koenig-lexical/test/e2e/utils/getImageDimensions.test.ts diff --git a/packages/koenig-lexical/test/test-setup.js b/packages/koenig-lexical/test/test-setup.ts similarity index 100% rename from packages/koenig-lexical/test/test-setup.js rename to packages/koenig-lexical/test/test-setup.ts diff --git a/packages/koenig-lexical/test/unit/EmailEditor.test.js b/packages/koenig-lexical/test/unit/EmailEditor.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/EmailEditor.test.js rename to packages/koenig-lexical/test/unit/EmailEditor.test.ts diff --git a/packages/koenig-lexical/test/unit/KoenigComposer.test.jsx b/packages/koenig-lexical/test/unit/KoenigComposer.test.tsx similarity index 100% rename from packages/koenig-lexical/test/unit/KoenigComposer.test.jsx rename to packages/koenig-lexical/test/unit/KoenigComposer.test.tsx diff --git a/packages/koenig-lexical/test/unit/build-output.test.js b/packages/koenig-lexical/test/unit/build-output.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/build-output.test.js rename to packages/koenig-lexical/test/unit/build-output.test.ts diff --git a/packages/koenig-lexical/test/unit/buildCardMenu.test.js b/packages/koenig-lexical/test/unit/buildCardMenu.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/buildCardMenu.test.js rename to packages/koenig-lexical/test/unit/buildCardMenu.test.ts diff --git a/packages/koenig-lexical/test/unit/headerCardv2.test.js b/packages/koenig-lexical/test/unit/headerCardv2.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/headerCardv2.test.js rename to packages/koenig-lexical/test/unit/headerCardv2.test.ts diff --git a/packages/koenig-lexical/test/unit/hooks/useVisibilityToggle.test.js b/packages/koenig-lexical/test/unit/hooks/useVisibilityToggle.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/hooks/useVisibilityToggle.test.js rename to packages/koenig-lexical/test/unit/hooks/useVisibilityToggle.test.ts diff --git a/packages/koenig-lexical/test/unit/productCard.test.js b/packages/koenig-lexical/test/unit/productCard.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/productCard.test.js rename to packages/koenig-lexical/test/unit/productCard.test.ts diff --git a/packages/koenig-lexical/test/unit/signupCard.test.js b/packages/koenig-lexical/test/unit/signupCard.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/signupCard.test.js rename to packages/koenig-lexical/test/unit/signupCard.test.ts diff --git a/packages/koenig-lexical/test/unit/toggleCard.test.js b/packages/koenig-lexical/test/unit/toggleCard.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/toggleCard.test.js rename to packages/koenig-lexical/test/unit/toggleCard.test.ts diff --git a/packages/koenig-lexical/test/unit/utils/generateEditorState.test.js b/packages/koenig-lexical/test/unit/utils/generateEditorState.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/utils/generateEditorState.test.js rename to packages/koenig-lexical/test/unit/utils/generateEditorState.test.ts diff --git a/packages/koenig-lexical/test/unit/utils/gif-provider.test.js b/packages/koenig-lexical/test/unit/utils/gif-provider.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/utils/gif-provider.test.js rename to packages/koenig-lexical/test/unit/utils/gif-provider.test.ts diff --git a/packages/koenig-lexical/test/unit/utils/image-card-widths.test.js b/packages/koenig-lexical/test/unit/utils/image-card-widths.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/utils/image-card-widths.test.js rename to packages/koenig-lexical/test/unit/utils/image-card-widths.test.ts diff --git a/packages/koenig-lexical/test/unit/utils/sanitize-html.test.js b/packages/koenig-lexical/test/unit/utils/sanitize-html.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/utils/sanitize-html.test.js rename to packages/koenig-lexical/test/unit/utils/sanitize-html.test.ts diff --git a/packages/koenig-lexical/test/unit/utils/visibility.test.js b/packages/koenig-lexical/test/unit/utils/visibility.test.ts similarity index 100% rename from packages/koenig-lexical/test/unit/utils/visibility.test.js rename to packages/koenig-lexical/test/unit/utils/visibility.test.ts diff --git a/packages/koenig-lexical/test/utils/color-select-helper.js b/packages/koenig-lexical/test/utils/color-select-helper.ts similarity index 100% rename from packages/koenig-lexical/test/utils/color-select-helper.js rename to packages/koenig-lexical/test/utils/color-select-helper.ts diff --git a/packages/koenig-lexical/test/utils/e2e.js b/packages/koenig-lexical/test/utils/e2e.ts similarity index 100% rename from packages/koenig-lexical/test/utils/e2e.js rename to packages/koenig-lexical/test/utils/e2e.ts diff --git a/packages/koenig-lexical/test/utils/isTestEnv.js b/packages/koenig-lexical/test/utils/isTestEnv.ts similarity index 100% rename from packages/koenig-lexical/test/utils/isTestEnv.js rename to packages/koenig-lexical/test/utils/isTestEnv.ts diff --git a/packages/koenig-lexical/vite.config.demo.js b/packages/koenig-lexical/vite.config.demo.ts similarity index 100% rename from packages/koenig-lexical/vite.config.demo.js rename to packages/koenig-lexical/vite.config.demo.ts diff --git a/packages/koenig-lexical/vite.config.js b/packages/koenig-lexical/vite.config.ts similarity index 100% rename from packages/koenig-lexical/vite.config.js rename to packages/koenig-lexical/vite.config.ts From a44314794e0f426ecee32818163ffcf4f2e4c7a4 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Mon, 16 Mar 2026 13:02:35 +0000 Subject: [PATCH 2/2] Migrate koenig-lexical to TypeScript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create tsconfig.json (strict, bundler moduleResolution, noEmit) - Rename all 328 source files (.js→.ts, .jsx→.tsx) - Rename all 71 test files (.js→.ts, .jsx→.tsx) - Add vite-env.d.ts for SVG and Vite type declarations - Rename vite.config.js/demo.js → .ts, playwright.config.js → .ts - Add type annotations to ~163 files (context, hooks, utils, components) - Replace .eslintrc.cjs with eslint.config.js (flat config) - Add typecheck script to package.json - tsc --noEmit passes with 0 errors --- .../src/generate-decorator-node.ts | 65 +- .../kg-default-nodes/src/kg-default-nodes.ts | 1 + .../kg-default-nodes/src/utils/card-widths.ts | 11 + .../kg-default-nodes/src/utils/visibility.ts | 2 +- packages/koenig-lexical/.storybook/main.ts | 3 + .../koenig-lexical/.storybook/preview.tsx | 3 +- packages/koenig-lexical/demo/DemoApp.tsx | 264 ++++--- .../koenig-lexical/demo/HtmlOutputDemo.tsx | 28 +- .../demo/RestrictedContentDemo.tsx | 36 +- .../demo/components/DarkModeToggle.tsx | 7 +- .../demo/components/EmailEditorWrapper.tsx | 4 +- .../demo/components/FloatingButton.tsx | 7 +- .../demo/components/InitialContentToggle.tsx | 9 +- .../demo/components/Navigator.tsx | 6 + .../components/SerializedStateTextarea.tsx | 2 +- .../demo/components/Sidebar.tsx | 8 +- .../demo/components/TitleTextBox.tsx | 24 +- .../demo/components/TreeView.tsx | 3 +- .../demo/components/Watermark.tsx | 4 +- .../demo/components/WordCount.tsx | 2 +- packages/koenig-lexical/demo/demo.tsx | 2 +- .../koenig-lexical/demo/utils/fetchEmbed.ts | 68 +- .../demo/utils/useFileUpload.ts | 58 +- .../koenig-lexical/demo/utils/useSnippets.ts | 19 +- packages/koenig-lexical/eslint.config.mjs | 82 ++- packages/koenig-lexical/package.json | 19 +- packages/koenig-lexical/playwright.config.ts | 6 +- .../src/components/DesignSandbox.tsx | 18 +- .../src/components/EmailEditor.tsx | 34 +- .../src/components/KoenigCaptionEditor.tsx | 52 +- .../src/components/KoenigCardWrapper.tsx | 46 +- .../src/components/KoenigComposableEditor.tsx | 48 +- .../src/components/KoenigComposer.tsx | 86 ++- .../src/components/KoenigEditor.tsx | 9 +- .../src/components/KoenigErrorBoundary.tsx | 6 +- .../src/components/KoenigNestedComposer.tsx | 20 +- .../src/components/KoenigNestedEditor.tsx | 43 +- .../src/components/ui/ActionToolbar.tsx | 8 +- .../src/components/ui/AtLinkResultsPopup.tsx | 38 +- .../src/components/ui/AudioUploadForm.tsx | 14 +- .../components/ui/BackgroundImagePicker.tsx | 40 +- .../src/components/ui/Button.stories.tsx | 5 +- .../src/components/ui/Button.tsx | 33 +- .../src/components/ui/ButtonGroup.stories.tsx | 5 +- .../src/components/ui/ButtonGroup.tsx | 45 +- .../src/components/ui/CardCaptionEditor.tsx | 46 +- .../src/components/ui/CardMenu.stories.tsx | 7 +- .../src/components/ui/CardMenu.tsx | 80 ++- .../components/ui/CardVisibilityMessage.tsx | 6 +- .../src/components/ui/CardWrapper.tsx | 48 +- .../src/components/ui/ColorOptionButtons.tsx | 31 +- .../src/components/ui/ColorPicker.stories.tsx | 15 +- .../src/components/ui/ColorPicker.tsx | 72 +- .../src/components/ui/Delayed.tsx | 7 +- .../src/components/ui/Dropdown.stories.tsx | 7 +- .../src/components/ui/Dropdown.tsx | 30 +- .../src/components/ui/DropdownContainer.tsx | 18 +- .../src/components/ui/EditorPlaceholder.tsx | 7 +- .../src/components/ui/EmojiPicker.tsx | 17 +- .../src/components/ui/EmojiPickerPortal.tsx | 62 +- .../src/components/ui/FileUploadForm.tsx | 13 +- .../components/ui/FloatingFormatToolbar.tsx | 40 +- .../src/components/ui/FloatingLinkToolbar.tsx | 48 +- .../src/components/ui/FloatingToolbar.tsx | 32 +- .../src/components/ui/FormatToolbar.tsx | 19 +- .../src/components/ui/GifPlugin.tsx | 41 +- .../src/components/ui/GifSelector.stories.tsx | 18 +- .../src/components/ui/GifSelector.tsx | 224 +++--- .../src/components/ui/HighlightedString.tsx | 19 +- .../src/components/ui/IconButton.stories.tsx | 5 +- .../src/components/ui/IconButton.tsx | 10 +- .../src/components/ui/ImageUploadForm.tsx | 15 +- .../src/components/ui/ImageUploadSwatch.tsx | 8 +- .../src/components/ui/Input.stories.tsx | 5 +- .../src/components/ui/Input.tsx | 14 +- .../src/components/ui/InputList.stories.tsx | 5 +- .../src/components/ui/InputList.tsx | 96 ++- .../src/components/ui/KeyboardSelection.tsx | 25 +- .../ui/KeyboardSelectionWithGroups.tsx | 42 +- .../src/components/ui/LinkActionToolbar.tsx | 24 +- .../ui/LinkActionToolbarWithSearch.tsx | 52 +- .../src/components/ui/LinkInput.stories.tsx | 5 +- .../src/components/ui/LinkInput.tsx | 31 +- .../src/components/ui/LinkInputSearchItem.tsx | 22 +- .../ui/LinkInputWithSearch.stories.tsx | 5 +- .../src/components/ui/LinkInputWithSearch.tsx | 42 +- .../src/components/ui/LinkToolbar.stories.tsx | 5 +- .../src/components/ui/LinkToolbar.tsx | 8 +- .../ui/MediaPlaceholder.stories.tsx | 5 +- .../src/components/ui/MediaPlaceholder.tsx | 42 +- .../src/components/ui/MediaPlayer.stories.tsx | 5 +- .../src/components/ui/MediaPlayer.tsx | 14 +- .../src/components/ui/MediaUploader.tsx | 85 ++- .../src/components/ui/Modal.stories.tsx | 5 +- .../src/components/ui/Modal.tsx | 18 +- .../src/components/ui/MultiSelectDropdown.tsx | 47 +- .../src/components/ui/PlusMenu.stories.tsx | 5 +- .../src/components/ui/PlusMenu.tsx | 13 +- .../src/components/ui/Portal.tsx | 11 +- .../src/components/ui/ProgressBar.stories.tsx | 5 +- .../src/components/ui/ProgressBar.tsx | 15 +- .../components/ui/SettingsPanel.stories.tsx | 66 +- .../src/components/ui/SettingsPanel.tsx | 222 ++++-- .../src/components/ui/SlashMenu.tsx | 8 +- .../src/components/ui/Slider.stories.tsx | 5 +- .../src/components/ui/Slider.tsx | 20 +- .../components/ui/SnippetActionToolbar.tsx | 27 +- .../components/ui/SnippetInput.stories.tsx | 5 +- .../src/components/ui/SnippetInput.tsx | 40 +- .../components/ui/SnippetInput/Dropdown.tsx | 30 +- .../src/components/ui/SnippetInput/Input.tsx | 9 +- .../src/components/ui/Spinner.tsx | 11 +- .../components/ui/SubscribeForm.stories.tsx | 5 +- .../src/components/ui/SubscribeForm.tsx | 19 +- .../src/components/ui/TabView.tsx | 31 +- .../src/components/ui/TextInput.tsx | 11 +- .../src/components/ui/Toggle.stories.tsx | 5 +- .../src/components/ui/Toggle.tsx | 15 +- .../src/components/ui/ToolbarMenu.stories.tsx | 56 +- .../src/components/ui/ToolbarMenu.tsx | 30 +- .../components/ui/ToolbarMenuItem.stories.tsx | 50 +- .../src/components/ui/Tooltip.tsx | 7 +- .../src/components/ui/UnsplashPlugin.tsx | 36 +- .../src/components/ui/UrlInput.stories.tsx | 10 +- .../src/components/ui/UrlInput.tsx | 34 +- .../components/ui/UrlSearchInput.stories.tsx | 10 +- .../src/components/ui/UrlSearchInput.tsx | 42 +- .../src/components/ui/VisibilitySettings.tsx | 19 +- .../components/ui/cards/AudioCard.stories.tsx | 36 +- .../src/components/ui/cards/AudioCard.tsx | 174 ++--- .../ui/cards/BookmarkCard.stories.tsx | 21 +- .../src/components/ui/cards/BookmarkCard.tsx | 84 +-- .../ui/cards/ButtonCard.stories.tsx | 15 +- .../src/components/ui/cards/ButtonCard.tsx | 34 +- .../ui/cards/CallToActionCard.stories.tsx | 34 +- .../components/ui/cards/CallToActionCard.tsx | 120 ++-- .../ui/cards/CalloutCard.stories.tsx | 23 +- .../src/components/ui/cards/CalloutCard.tsx | 53 +- .../ui/cards/CodeBlockCard.stories.tsx | 17 +- .../src/components/ui/cards/CodeBlockCard.tsx | 251 +++++-- .../components/ui/cards/EmailCard.stories.tsx | 17 +- .../src/components/ui/cards/EmailCard.tsx | 18 +- .../ui/cards/EmailCtaCard.stories.tsx | 31 +- .../src/components/ui/cards/EmailCtaCard.tsx | 54 +- .../components/ui/cards/EmbedCard.stories.tsx | 61 +- .../src/components/ui/cards/EmbedCard.tsx | 95 +-- .../components/ui/cards/FileCard.stories.tsx | 23 +- .../src/components/ui/cards/FileCard.tsx | 112 +-- .../ui/cards/GalleryCard.stories.tsx | 29 +- .../src/components/ui/cards/GalleryCard.tsx | 146 ++-- .../ui/cards/HeaderCard/v1/HeaderCard.tsx | 86 +-- .../HeaderCard/v1/HeaderCard.v1.stories.tsx | 27 +- .../ui/cards/HeaderCard/v2/HeaderCard.tsx | 153 +++-- .../HeaderCard/v2/HeaderCard.v2.stories.tsx | 19 +- .../ui/cards/HorizontalRuleCard.stories.tsx | 15 +- .../components/ui/cards/HtmlCard.stories.tsx | 17 +- .../src/components/ui/cards/HtmlCard.tsx | 25 +- .../ui/cards/HtmlCard/HtmlEditor.tsx | 12 +- .../components/ui/cards/ImageCard.stories.tsx | 23 +- .../src/components/ui/cards/ImageCard.tsx | 189 ++--- .../ui/cards/MarkdownCard.stories.tsx | 37 +- .../src/components/ui/cards/MarkdownCard.tsx | 25 +- .../ui/cards/MarkdownCard/MarkdownEditor.tsx | 75 +- .../cards/MarkdownCard/MarkdownHelpDialog.tsx | 8 +- .../MarkdownCard/MarkdownImageUploader.tsx | 13 +- .../MarkdownCard/useMarkdownImageUploader.ts | 50 +- .../ui/cards/PaywallCard.stories.tsx | 20 +- .../ui/cards/ProductCard.stories.tsx | 26 +- .../src/components/ui/cards/ProductCard.tsx | 64 +- .../ui/cards/ProductCard/ProductCardImage.tsx | 48 +- .../ui/cards/ProductCard/RatingButton.tsx | 9 +- .../ui/cards/SignupCard.stories.tsx | 17 +- .../src/components/ui/cards/SignupCard.tsx | 157 +++-- .../ui/cards/ToggleCard.stories.tsx | 22 +- .../src/components/ui/cards/ToggleCard.tsx | 24 +- .../components/ui/cards/TransistorCard.tsx | 106 +-- .../components/ui/cards/VideoCard.stories.tsx | 18 +- .../src/components/ui/cards/VideoCard.tsx | 133 ++-- .../ui/file-selectors/Gif/Error.tsx | 8 +- .../components/ui/file-selectors/Gif/Gif.tsx | 26 +- .../ui/file-selectors/Gif/Loader.tsx | 6 +- .../Unsplash/UnsplashButton.tsx | 15 +- .../Unsplash/UnsplashGallery.tsx | 45 +- .../file-selectors/Unsplash/UnsplashImage.tsx | 60 +- .../Unsplash/UnsplashSelector.stories.tsx | 65 +- .../Unsplash/UnsplashSelector.tsx | 16 +- .../Unsplash/UnsplashZoomed.tsx | 29 +- .../ui/file-selectors/UnsplashModal.tsx | 12 +- .../src/context/CardContext.tsx | 27 +- .../src/context/KoenigComposerContext.tsx | 120 +++- .../src/context/KoenigSelectedCardContext.tsx | 28 +- .../src/context/SharedHistoryContext.tsx | 11 +- .../src/context/SharedOnChangeContext.tsx | 9 +- .../koenig-lexical/src/context/TKContext.tsx | 52 +- .../src/hooks/useCardDragAndDrop.ts | 52 +- .../src/hooks/useClickOutside.ts | 6 +- .../src/hooks/useFileDragAndDrop.ts | 16 +- .../src/hooks/useGalleryReorder.ts | 97 +-- .../src/hooks/useInputSelection.ts | 10 +- .../src/hooks/useKoenigTextEntity.ts | 67 +- .../koenig-lexical/src/hooks/useMovable.ts | 163 ++--- .../src/hooks/usePinturaEditor.ts | 47 +- .../src/hooks/usePreviousFocus.ts | 12 +- .../src/hooks/useSearchLinks.ts | 57 +- .../src/hooks/useSettingsPanelReposition.ts | 98 ++- .../src/hooks/useTypeaheadTriggerMatch.ts | 10 +- .../src/hooks/useVisibilityToggle.ts | 30 +- packages/koenig-lexical/src/index.ts | 4 +- .../koenig-lexical/src/nodes/AsideNode.ts | 11 +- .../koenig-lexical/src/nodes/AudioNode.tsx | 20 +- .../src/nodes/AudioNodeComponent.tsx | 68 +- .../koenig-lexical/src/nodes/BookmarkNode.tsx | 33 +- .../src/nodes/BookmarkNodeComponent.tsx | 91 ++- .../koenig-lexical/src/nodes/ButtonNode.tsx | 10 +- .../src/nodes/ButtonNodeComponent.tsx | 29 +- .../src/nodes/CallToActionNode.tsx | 33 +- .../src/nodes/CallToActionNodeComponent.tsx | 142 ++-- .../koenig-lexical/src/nodes/CalloutNode.tsx | 13 +- .../src/nodes/CalloutNodeComponent.tsx | 46 +- .../src/nodes/CodeBlockNode.tsx | 19 +- .../src/nodes/CodeBlockNodeComponent.tsx | 36 +- .../koenig-lexical/src/nodes/EmailCtaNode.tsx | 31 +- .../src/nodes/EmailCtaNodeComponent.tsx | 62 +- .../src/nodes/EmailEmbedNode.tsx | 2 +- .../koenig-lexical/src/nodes/EmailNode.tsx | 15 +- .../src/nodes/EmailNodeComponent.tsx | 17 +- .../koenig-lexical/src/nodes/EmbedNode.tsx | 33 +- .../src/nodes/EmbedNodeComponent.tsx | 58 +- .../koenig-lexical/src/nodes/FileNode.tsx | 26 +- .../src/nodes/FileNodeComponent.tsx | 46 +- .../koenig-lexical/src/nodes/GalleryNode.tsx | 28 +- .../src/nodes/GalleryNodeComponent.tsx | 51 +- .../koenig-lexical/src/nodes/HeaderNode.tsx | 63 +- .../src/nodes/HorizontalRuleNode.tsx | 4 +- .../koenig-lexical/src/nodes/HtmlNode.tsx | 10 +- .../src/nodes/HtmlNodeComponent.tsx | 47 +- .../koenig-lexical/src/nodes/ImageNode.tsx | 47 +- .../src/nodes/ImageNodeComponent.tsx | 104 ++- .../koenig-lexical/src/nodes/MarkdownNode.tsx | 6 +- .../src/nodes/MarkdownNodeComponent.tsx | 24 +- .../koenig-lexical/src/nodes/PaywallNode.tsx | 4 +- .../koenig-lexical/src/nodes/ProductNode.tsx | 41 +- .../src/nodes/ProductNodeComponent.tsx | 89 ++- .../koenig-lexical/src/nodes/SignupNode.tsx | 68 +- .../src/nodes/SignupNodeComponent.tsx | 138 ++-- .../koenig-lexical/src/nodes/ToggleNode.tsx | 19 +- .../src/nodes/ToggleNodeComponent.tsx | 21 +- .../src/nodes/TransistorNode.tsx | 14 +- .../src/nodes/TransistorNodeComponent.tsx | 32 +- .../koenig-lexical/src/nodes/VideoNode.tsx | 42 +- .../src/nodes/VideoNodeComponent.tsx | 118 ++-- .../nodes/header/v1/HeaderNodeComponent.tsx | 77 ++- .../nodes/header/v2/HeaderNodeComponent.tsx | 147 ++-- .../src/plugins/AllDefaultPlugins.tsx | 4 +- .../src/plugins/AtLinkPlugin.tsx | 87 ++- .../src/plugins/AudioPlugin.tsx | 4 +- .../src/plugins/BookmarkPlugin.tsx | 2 +- .../src/plugins/ButtonPlugin.tsx | 2 +- .../src/plugins/CallToActionPlugin.tsx | 3 +- .../src/plugins/CalloutPlugin.tsx | 2 +- .../src/plugins/DragDropPastePlugin.tsx | 65 +- .../src/plugins/DragDropReorderPlugin.tsx | 99 +-- .../src/plugins/EmEnDashPlugin.tsx | 13 +- .../src/plugins/EmailCtaPlugin.tsx | 4 +- .../src/plugins/EmailPlugin.tsx | 2 +- .../src/plugins/EmbedPlugin.tsx | 2 +- .../src/plugins/EmojiPickerPlugin.tsx | 73 +- .../src/plugins/ExternalControlPlugin.tsx | 20 +- .../koenig-lexical/src/plugins/FilePlugin.tsx | 2 +- .../src/plugins/FloatingToolbarPlugin.tsx | 21 +- .../src/plugins/GalleryPlugin.tsx | 2 +- .../src/plugins/HeaderPlugin.tsx | 3 +- .../src/plugins/HorizontalRulePlugin.tsx | 9 +- .../src/plugins/HtmlOutputPlugin.tsx | 2 +- .../koenig-lexical/src/plugins/HtmlPlugin.tsx | 2 +- .../src/plugins/ImagePlugin.tsx | 6 +- .../src/plugins/KoenigBehaviourPlugin.tsx | 237 ++++--- .../src/plugins/KoenigBlurPlugin.tsx | 5 +- .../src/plugins/KoenigFocusPlugin.tsx | 3 +- .../src/plugins/KoenigNestedEditorPlugin.tsx | 36 +- .../src/plugins/KoenigSelectorPlugin.tsx | 10 +- .../src/plugins/KoenigSnippetPlugin.tsx | 8 +- .../src/plugins/MarkdownPastePlugin.tsx | 8 +- .../src/plugins/MarkdownPlugin.tsx | 2 +- .../src/plugins/MarkdownShortcutPlugin.tsx | 59 +- .../src/plugins/PaywallPlugin.tsx | 7 +- .../src/plugins/PlusCardMenuPlugin.tsx | 71 +- .../src/plugins/ProductPlugin.tsx | 3 +- .../src/plugins/ReplacementStringsPlugin.tsx | 16 +- .../src/plugins/RestrictContentPlugin.tsx | 20 +- .../src/plugins/SignupPlugin.tsx | 3 +- .../src/plugins/SlashCardMenuPlugin.tsx | 96 +-- .../src/plugins/TKCountPlugin.tsx | 4 +- .../koenig-lexical/src/plugins/TKPlugin.tsx | 49 +- .../src/plugins/TogglePlugin.tsx | 2 +- .../src/plugins/TransistorPlugin.tsx | 2 +- .../src/plugins/VideoPlugin.tsx | 6 +- .../src/plugins/WordCountPlugin.tsx | 8 +- .../koenig-lexical/src/types/GalleryImage.ts | 10 + .../src/utils/$getSelectionRangeRect.ts | 3 +- .../src/utils/$insertAndSelectNode.ts | 3 +- .../src/utils/$isAtStartOfDocument.ts | 9 +- .../src/utils/$isAtTopOfNode.ts | 18 +- .../src/utils/$selectDecoratorNode.ts | 3 +- .../koenig-lexical/src/utils/analytics.ts | 18 +- .../src/utils/audioUploadHandler.ts | 17 +- .../src/utils/autoExpandTextArea.ts | 2 +- .../koenig-lexical/src/utils/buildCardMenu.ts | 64 +- .../src/utils/createFileInputChangeEvent.ts | 30 + .../koenig-lexical/src/utils/dataSrcToFile.ts | 24 +- .../src/utils/draggable/DragDropContainer.ts | 101 ++- .../src/utils/draggable/DragDropHandler.tsx | 298 ++++---- .../src/utils/draggable/ScrollHandler.ts | 61 +- .../src/utils/draggable/draggable-utils.ts | 70 +- .../src/utils/extractVideoMetadata.ts | 15 +- .../src/utils/fileUploadHandler.ts | 21 +- .../src/utils/generateEditorState.ts | 5 +- .../src/utils/getAudioMetadata.ts | 6 +- .../src/utils/getDOMRangeRect.ts | 8 +- .../src/utils/getEditorCardNodes.ts | 16 +- .../src/utils/getImageDimensions.ts | 2 +- .../src/utils/getImageFilenameFromSrc.ts | 4 +- .../src/utils/getScrollParent.ts | 10 +- .../src/utils/getSelectedNode.ts | 3 +- .../src/utils/getTopLevelNativeElement.ts | 15 +- .../src/utils/image-card-widths.ts | 11 +- .../src/utils/imageUploadHandler.ts | 29 +- .../koenig-lexical/src/utils/isEditorEmpty.ts | 6 +- packages/koenig-lexical/src/utils/isGif.ts | 2 +- .../koenig-lexical/src/utils/isInternalUrl.ts | 4 +- .../src/utils/koenig-node-class.ts | 20 + .../src/utils/lexical-internals.ts | 18 + .../src/utils/nested-editors.ts | 35 +- .../src/utils/openFileSelection.ts | 2 +- .../src/utils/prettifyFileName.ts | 4 +- .../koenig-lexical/src/utils/sanitize-html.ts | 27 +- .../koenig-lexical/src/utils/services/gif.ts | 95 ++- .../src/utils/setFloatingElemPosition.ts | 19 +- .../src/utils/shouldIgnoreEvent.ts | 6 +- .../storybook/populate-storybook-editor.ts | 5 +- .../src/utils/thumbnailUploadHandler.ts | 17 +- .../koenig-lexical/src/utils/visibility.ts | 48 +- packages/koenig-lexical/src/vite-env.d.ts | 24 + .../test/e2e/card-behaviour.test.ts | 57 +- .../test/e2e/cards/audio-card.test.ts | 5 +- .../cards/bookmark-card-with-search.test.ts | 5 +- .../bookmark-card-without-search.test.ts | 3 +- .../test/e2e/cards/button-card.test.ts | 3 +- .../e2e/cards/call-to-action-card.test.ts | 25 +- .../test/e2e/cards/callout-card.test.ts | 3 +- .../test/e2e/cards/code-block-card.test.ts | 3 +- .../test/e2e/cards/email-card.test.ts | 11 +- .../test/e2e/cards/email-cta-card.test.ts | 5 +- .../test/e2e/cards/embed-card.test.ts | 5 +- .../test/e2e/cards/file-card.test.ts | 5 +- .../test/e2e/cards/gallery-card.test.ts | 11 +- .../test/e2e/cards/header-card.test.ts | 43 +- .../test/e2e/cards/html-card.test.ts | 3 +- .../test/e2e/cards/image-card.test.ts | 45 +- .../test/e2e/cards/markdown-card.test.ts | 7 +- .../test/e2e/cards/paywall-card.test.ts | 5 +- .../test/e2e/cards/product-card.test.ts | 5 +- .../test/e2e/cards/signup-card.test.ts | 9 +- .../test/e2e/cards/toggle-card.test.ts | 5 +- .../test/e2e/cards/transistor-card.test.ts | 3 +- .../test/e2e/cards/video-card.firefox.test.ts | 5 +- .../test/e2e/content-visibility.test.ts | 3 +- .../test/e2e/editors/basic-editor.test.ts | 3 +- .../test/e2e/editors/email-editor.test.ts | 5 +- .../test/e2e/editors/minimal-editor.test.ts | 3 +- .../test/e2e/floating-toolbar.test.ts | 3 +- .../test/e2e/format-shortcuts.test.ts | 3 +- .../koenig-lexical/test/e2e/linking.test.ts | 3 +- .../test/e2e/list-behaviour.test.ts | 5 +- .../test/e2e/modals/UnsplashSelector.test.ts | 5 +- .../test/e2e/node-transforms.test.ts | 3 +- .../test/e2e/paste-behaviour.test.ts | 3 +- .../DragDropPastePlugin.firefox.test.ts | 3 +- .../e2e/plugins/DragDropPastePlugin.test.ts | 3 +- .../e2e/plugins/DragDropReorderPlugin.test.ts | 16 +- .../e2e/plugins/EmojiPickerPlugin.test.ts | 3 +- .../test/e2e/plugins/HtmlOutputPlugin.test.ts | 7 +- .../e2e/plugins/KoenigSnippetPlugin.test.ts | 3 +- .../plugins/ReplacementStringsPlugin.test.ts | 3 +- .../e2e/plugins/RestrictContentPlugin.test.ts | 3 +- .../test/e2e/plugins/TKPlugin.test.ts | 7 +- .../test/e2e/plugins/WordCountPlugin.test.ts | 3 +- .../test/e2e/plus-button.test.ts | 31 +- .../koenig-lexical/test/e2e/selection.test.ts | 7 +- .../test/e2e/slash-menu.test.ts | 5 +- .../e2e/text-transforms/code-block.test.ts | 3 +- .../e2e/text-transforms/emdash-endash.test.ts | 9 +- .../test/e2e/text-transforms/headings.test.ts | 17 +- .../horizontal-line-rule.test.ts | 3 +- .../test/e2e/text-transforms/links.test.ts | 3 +- .../test/e2e/text-transforms/markdown.test.ts | 3 +- .../test/e2e/text-transforms/paywall.test.ts | 3 +- .../test/e2e/title-behaviour.test.ts | 49 +- .../test/e2e/utils/getImageDimensions.test.ts | 3 +- packages/koenig-lexical/test/types.d.ts | 19 + .../test/unit/EmailEditor.test.ts | 2 +- .../test/unit/buildCardMenu.test.ts | 34 +- .../test/unit/headerCardv2.test.ts | 15 +- .../unit/hooks/useVisibilityToggle.test.ts | 11 +- .../test/unit/productCard.test.ts | 15 +- .../test/unit/signupCard.test.ts | 17 +- .../test/unit/toggleCard.test.ts | 15 +- .../unit/utils/generateEditorState.test.ts | 19 +- .../test/unit/utils/gif-provider.test.ts | 12 +- .../test/unit/utils/image-card-widths.test.ts | 2 +- .../test/unit/utils/sanitize-html.test.ts | 10 + .../test/unit/utils/visibility.test.ts | 12 +- .../test/utils/color-select-helper.ts | 8 +- packages/koenig-lexical/test/utils/e2e.ts | 187 +++-- packages/koenig-lexical/tsconfig.json | 20 + packages/koenig-lexical/tsconfig.test.json | 7 + packages/koenig-lexical/tsconfig.types.json | 11 + packages/koenig-lexical/vite.config.demo.ts | 7 +- packages/koenig-lexical/vite.config.ts | 13 +- yarn.lock | 646 +++++++++--------- 420 files changed, 8378 insertions(+), 5304 deletions(-) create mode 100644 packages/kg-default-nodes/src/utils/card-widths.ts create mode 100644 packages/koenig-lexical/src/types/GalleryImage.ts create mode 100644 packages/koenig-lexical/src/utils/createFileInputChangeEvent.ts create mode 100644 packages/koenig-lexical/src/utils/koenig-node-class.ts create mode 100644 packages/koenig-lexical/src/utils/lexical-internals.ts create mode 100644 packages/koenig-lexical/src/vite-env.d.ts create mode 100644 packages/koenig-lexical/test/types.d.ts create mode 100644 packages/koenig-lexical/tsconfig.json create mode 100644 packages/koenig-lexical/tsconfig.test.json create mode 100644 packages/koenig-lexical/tsconfig.types.json diff --git a/packages/kg-default-nodes/src/generate-decorator-node.ts b/packages/kg-default-nodes/src/generate-decorator-node.ts index 4df86a07a2..2158f0d144 100644 --- a/packages/kg-default-nodes/src/generate-decorator-node.ts +++ b/packages/kg-default-nodes/src/generate-decorator-node.ts @@ -2,11 +2,13 @@ import {KoenigDecoratorNode} from './KoenigDecoratorNode.js'; import type {ExportDOMOptions, ExportDOMOutput} from './export-dom.js'; import readTextContent from './utils/read-text-content.js'; import {buildDefaultVisibility, isVisibilityRestricted, migrateOldVisibilityFormat} from './utils/visibility.js'; -import type {LexicalEditor} from 'lexical'; +import type {LexicalEditor, SerializedLexicalNode} from 'lexical'; import type {Visibility} from './utils/visibility.js'; -type RenderFn = (node: any, options: ExportDOMOptions) => TOutput; -type VersionedRenderFn = Record>; +type RenderFn = { + bivarianceHack(node: TNode, options: ExportDOMOptions): TOutput; +}['bivarianceHack']; +type VersionedRenderFn = Record>; type WidenLiteral = T extends string ? string : T extends number ? number : @@ -62,7 +64,7 @@ export interface DecoratorNodeProperty = { [Prop in Props[number] as Prop['name']]: WidenLiteral; -} & (HasVisibility extends true ? {visibility: Visibility} : {}); +} & (HasVisibility extends true ? {visibility: Visibility} : unknown); export type DecoratorNodeData = Partial>; @@ -70,6 +72,8 @@ type GeneratedDecoratorNodeInstance, TO exportDOM(editor: LexicalEditor, options?: ExportDOMOptions): TOutput; }; +export type SerializedGeneratedDecoratorNode = Record> = SerializedLexicalNode & TDataset; + export interface GeneratedDecoratorNodeClass, TOutput extends ExportDOMOutput = ExportDOMOutput> { new (data?: Partial, key?: string): GeneratedDecoratorNodeInstance; prototype: GeneratedDecoratorNodeInstance; @@ -135,19 +139,26 @@ export class GeneratedDecoratorNodeBase export function generateDecoratorNode< Props extends readonly DecoratorNodeProperty[] = readonly [], HasVisibility extends boolean = false, - TOutput extends ExportDOMOutput = ExportDOMOutput ->({nodeType, properties = [] as unknown as Props, defaultRenderFn, version = 1, hasVisibility = false as HasVisibility}: { + TOutput extends ExportDOMOutput = ExportDOMOutput, + TRenderNode = GeneratedDecoratorNodeInstance, TOutput> +>({nodeType, properties, defaultRenderFn, version = 1, hasVisibility}: { nodeType: string; properties?: Props; - defaultRenderFn?: RenderFn | VersionedRenderFn; + defaultRenderFn?: RenderFn | VersionedRenderFn; version?: number; hasVisibility?: HasVisibility; }): GeneratedDecoratorNodeClass, TOutput> { - validateArguments(nodeType, properties); + type GeneratedDataset = DecoratorNodeValueMap; + type GeneratedRenderFn = RenderFn; + type GeneratedVersionedRenderFn = VersionedRenderFn; + + const nodeProperties = properties ?? []; + + validateArguments(nodeType, nodeProperties); // Adds a `privateName` field to the properties for convenience (e.g. `__name`): // properties: [{name: 'name', privateName: '__name', type: 'string', default: 'hello'}, {...}] - const internalProps = properties.map((prop) => { + const internalProps = nodeProperties.map((prop) => { return Object.defineProperties({}, { ...Object.getOwnPropertyDescriptors(prop), privateName: { @@ -174,7 +185,7 @@ export function generateDecoratorNode< class GeneratedDecoratorNode extends KoenigDecoratorNode { [key: string]: unknown; - constructor(data: Partial> = {}, key?: string) { + constructor(data: Partial = {}, key?: string) { super(key); const dataset = data as Record; internalProps.forEach((prop) => { @@ -206,7 +217,7 @@ export function generateDecoratorNode< * @see https://lexical.dev/docs/concepts/nodes#extending-decoratornode */ static clone(node: GeneratedDecoratorNodeInstance, TOutput>) { - return new this(node.getDataset() as Partial>, node.__key); + return new this(node.getDataset() as Partial, node.__key); } /** @@ -217,7 +228,7 @@ export function generateDecoratorNode< return internalProps.reduce((obj: Record, prop) => { obj[prop.name] = prop.default; return obj; - }, {}) as DecoratorNodeValueMap; + }, {}) as GeneratedDataset; } /** @@ -272,7 +283,7 @@ export function generateDecoratorNode< data[prop.name] = serializedNode[prop.name]; }); - return new this(data as Partial>); + return new this(data as Partial); } /** @@ -280,54 +291,52 @@ export function generateDecoratorNode< * @extends DecoratorNode * @see https://lexical.dev/docs/concepts/serialization#lexicalnodeexportjson */ - // @ts-expect-error -- strict mode migration - exportJSON() { - const dataset: Record = { + exportJSON(): SerializedGeneratedDecoratorNode { + const dataset = { type: nodeType, version: version, ...internalProps.reduce((obj: Record, prop) => { obj[prop.name] = this[prop.name]; return obj; }, {}) - }; + } as SerializedGeneratedDecoratorNode; return dataset; } exportDOM(_editor: LexicalEditor, options: ExportDOMOptions = {}): TOutput { // this.__version is used when a node has a version property which // means it's set from the serialized version data at runtime - const nodeVersion = this.__version || version; + const nodeVersion = typeof this.__version === 'string' || typeof this.__version === 'number' ? this.__version : version; + const node = this as unknown as TRenderNode; - const nodeRenderers = options.nodeRenderers as Record | VersionedRenderFn> | undefined; + const nodeRenderers = options.nodeRenderers as Record | undefined; if (nodeRenderers?.[nodeType]) { const render = nodeRenderers[nodeType]; if (typeof render === 'object') { - const versionRenderer = (render as VersionedRenderFn)[nodeVersion as number]; + const versionRenderer = render[nodeVersion]; if (!versionRenderer) { throw new Error(`[generateDecoratorNode] ${nodeType}: options.nodeRenderers['${nodeType}'] for version ${nodeVersion} is required`); } - return versionRenderer(this, options); + return versionRenderer(node, options); } else { - return (render as RenderFn)(this, options); + return render(node, options); } } if (typeof defaultRenderFn === 'object') { - const render = (defaultRenderFn as VersionedRenderFn)[nodeVersion as number]; + const render = defaultRenderFn[nodeVersion]; if (!render) { throw new Error(`[generateDecoratorNode] ${nodeType}: "defaultRenderFn" for version ${nodeVersion} is required`); } - return render(this, options); + return render(node, options); } if (!defaultRenderFn) { throw new Error(`[generateDecoratorNode] ${nodeType}: "defaultRenderFn" is required`); } - const render = defaultRenderFn as RenderFn; - - return render(this, options); + return defaultRenderFn(node, options); } /* c8 ignore start */ @@ -380,7 +389,7 @@ export function generateDecoratorNode< */ getTextContent() { const self = this.getLatest(); - const propertiesWithText = properties.filter(prop => !!prop.wordCount); + const propertiesWithText = nodeProperties.filter(prop => !!prop.wordCount); const text = propertiesWithText.map( prop => readTextContent(self, prop.name) diff --git a/packages/kg-default-nodes/src/kg-default-nodes.ts b/packages/kg-default-nodes/src/kg-default-nodes.ts index 56e393566c..b32aea9ba6 100644 --- a/packages/kg-default-nodes/src/kg-default-nodes.ts +++ b/packages/kg-default-nodes/src/kg-default-nodes.ts @@ -64,6 +64,7 @@ export * from './nodes/ExtendedQuoteNode.js'; export * from './nodes/TKNode.js'; export * from './nodes/at-link/index.js'; export * from './nodes/zwnj/ZWNJNode.js'; +export * from './utils/card-widths.js'; // export utility functions that are useful in other packages or tests import * as visibilityUtils from './utils/visibility.js'; diff --git a/packages/kg-default-nodes/src/utils/card-widths.ts b/packages/kg-default-nodes/src/utils/card-widths.ts new file mode 100644 index 0000000000..c6270f9590 --- /dev/null +++ b/packages/kg-default-nodes/src/utils/card-widths.ts @@ -0,0 +1,11 @@ +export const CARD_WIDTHS = ['regular', 'wide', 'full'] as const; + +export type CardWidth = typeof CARD_WIDTHS[number]; + +export function isCardWidth(width: unknown): width is CardWidth { + return typeof width === 'string' && (CARD_WIDTHS as readonly string[]).includes(width); +} + +export function normalizeCardWidth(width: unknown): CardWidth | undefined { + return isCardWidth(width) ? width : undefined; +} diff --git a/packages/kg-default-nodes/src/utils/visibility.ts b/packages/kg-default-nodes/src/utils/visibility.ts index ce76e98a25..0e087f4d40 100644 --- a/packages/kg-default-nodes/src/utils/visibility.ts +++ b/packages/kg-default-nodes/src/utils/visibility.ts @@ -21,7 +21,7 @@ function isNullish(value: unknown) { } // ensure we always work with a deep copy to avoid accidental ref mutations -export function buildDefaultVisibility() { +export function buildDefaultVisibility(): typeof DEFAULT_VISIBILITY { return JSON.parse(JSON.stringify(DEFAULT_VISIBILITY)); } diff --git a/packages/koenig-lexical/.storybook/main.ts b/packages/koenig-lexical/.storybook/main.ts index 00c4f1604c..d552cce75e 100644 --- a/packages/koenig-lexical/.storybook/main.ts +++ b/packages/koenig-lexical/.storybook/main.ts @@ -1,7 +1,10 @@ import { dirname, join } from "path"; +import { createRequire } from "module"; import { mergeConfig } from 'vite'; import type {StorybookConfig} from '@storybook/react-vite'; +const require = createRequire(import.meta.url); + const config: StorybookConfig = { framework: { name: getAbsolutePath("@storybook/react-vite"), diff --git a/packages/koenig-lexical/.storybook/preview.tsx b/packages/koenig-lexical/.storybook/preview.tsx index 7934104fa6..da1e29d691 100644 --- a/packages/koenig-lexical/.storybook/preview.tsx +++ b/packages/koenig-lexical/.storybook/preview.tsx @@ -1,5 +1,6 @@ import '../src/styles/index.css'; import {LexicalComposer} from '@lexical/react/LexicalComposer'; +import type {FC} from 'react'; export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, @@ -54,7 +55,7 @@ export const parameters = { } export const decorators = [ - (Story) => { + (Story: FC) => { return (
diff --git a/packages/koenig-lexical/demo/DemoApp.tsx b/packages/koenig-lexical/demo/DemoApp.tsx index eb86e4502b..6eef311408 100644 --- a/packages/koenig-lexical/demo/DemoApp.tsx +++ b/packages/koenig-lexical/demo/DemoApp.tsx @@ -6,19 +6,23 @@ import InitialContentToggle from './components/InitialContentToggle'; import LockIcon from './assets/icons/kg-lock.svg?react'; import React, {useState} from 'react'; import Sidebar from './components/Sidebar'; -import TitleTextBox from './components/TitleTextBox'; +import TitleTextBox, {type TitleTextBoxHandle} from './components/TitleTextBox'; import Watermark from './components/Watermark'; import WordCount from './components/WordCount'; import basicContent from './content/basic-content.json'; import content from './content/content.json'; import emailContent from './content/email-content.json'; import minimalContent from './content/minimal-content.json'; -import {$getRoot, $isDecoratorNode} from 'lexical'; +import {$getRoot, $isDecoratorNode, type Klass, type LexicalNode, type LexicalNodeReplacement} from 'lexical'; import { - BASIC_NODES, BASIC_TRANSFORMERS, EmailEditor, - KoenigComposableEditor, KoenigComposer, KoenigEditor, MINIMAL_NODES, - MINIMAL_TRANSFORMERS, RestrictContentPlugin, TKCountPlugin, WordCountPlugin + BASIC_NODES, BASIC_TRANSFORMERS, BookmarkPlugin, + ButtonPlugin, CallToActionPlugin, CalloutPlugin, CardMenuPlugin, EMAIL_EDITOR_NODES, + EMAIL_TRANSFORMERS, EmEnDashPlugin, EmailCtaPlugin, EmbedPlugin, EmojiPickerPlugin, + HorizontalRulePlugin, HtmlPlugin, ImagePlugin, + KoenigComposableEditor, KoenigComposer, KoenigEditor, KoenigSelectorPlugin, KoenigSnippetPlugin, ListPlugin, MINIMAL_NODES, + MINIMAL_TRANSFORMERS, ProductPlugin, ReplacementStringsPlugin, RestrictContentPlugin, TKCountPlugin, TransistorPlugin, WordCountPlugin } from '../src'; +import {VISIBILITY_SETTINGS} from '../src/utils/visibility'; import {defaultHeaders as defaultUnsplashHeaders} from './utils/unsplashConfig'; import {fetchEmbed} from './utils/fetchEmbed'; import {fileTypes, useFileUpload} from './utils/useFileUpload'; @@ -33,7 +37,7 @@ const WEBSOCKET_ID = params.get('multiplayerId') || '0'; // show deprecated cards by default so they can be tested, unless explicitly hidden // so we can test they are removed from the menu when deprecated/behind a feature flag -function hideDeprecatedCardInMenu(searchParams) { +function hideDeprecatedCardInMenu(searchParams: URLSearchParams) { // allow tests to opt in to hiding deprecated cards if (searchParams.get('hideDeprecatedCards') === 'true') { return true; @@ -63,7 +67,7 @@ const defaultCardConfig = { transistor: false }, // this enables the internal linking feature, can be disabled with `/#/?searchLinks=false` - searchLinks: async (term) => { + searchLinks: async (term = '') => { // default to showing latest posts when search is empty // no delay to simulate posts being pre-loaded in editor if (!term) { @@ -111,7 +115,7 @@ const defaultCardConfig = { } }; -function getDefaultContent({editorType}) { +function getDefaultContent({editorType}: {editorType?: string}) { if (editorType === 'basic') { return basicContent; } else if (editorType === 'minimal') { @@ -122,16 +126,37 @@ function getDefaultContent({editorType}) { return content; } -function getAllowedNodes({editorType}) { +function getAllowedNodes({editorType}: {editorType?: string}): ReadonlyArray | LexicalNodeReplacement> | undefined { if (editorType === 'basic') { - return BASIC_NODES; + return BASIC_NODES as ReadonlyArray | LexicalNodeReplacement>; } else if (editorType === 'minimal') { - return MINIMAL_NODES; + return MINIMAL_NODES as ReadonlyArray | LexicalNodeReplacement>; + } else if (editorType === 'email') { + return EMAIL_EDITOR_NODES as ReadonlyArray | LexicalNodeReplacement>; } return undefined; } -function DemoEditor({editorType, registerAPI, cursorDidExitAtTop, darkMode, setWordCount, setTKCount}) { +interface DemoEditorAPI { + editorInstance: unknown; + editorIsEmpty: () => boolean; + insertParagraphAtTop: (options: {focus: boolean}) => void; + insertParagraphAtBottom: () => void; + focusEditor: (options: {position: string}) => void; + insertFiles: (files: File[]) => void; + serialize: () => string; + [key: string]: unknown; +} + +interface DemoEditorProps { + editorType?: string; + registerAPI: (api: unknown) => void; + cursorDidExitAtTop: () => void; + setWordCount: (count: number) => void; + setTKCount: (count: number) => void; +} + +function DemoEditor({editorType, registerAPI, cursorDidExitAtTop, setWordCount, setTKCount}: DemoEditorProps) { if (editorType === 'basic') { return ( ); + } else if (editorType === 'email') { + return ( + + + + + + + + + + + + + + + + + + + + + + ); } return ( @@ -168,7 +221,14 @@ function DemoEditor({editorType, registerAPI, cursorDidExitAtTop, darkMode, setW ); } -function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { +interface DemoComposerProps { + editorType?: string; + isMultiplayer?: boolean; + setWordCount: (count: number) => void; + setTKCount: (count: number) => void; +} + +function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}: DemoComposerProps) { const [searchParams, setSearchParams] = useSearchParams(); const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [sidebarView, setSidebarView] = useState('json'); @@ -196,9 +256,9 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { }, [isMultiplayer, contentParam, defaultContent]); const [title, setTitle] = useState(initialContent ? 'Meet the Koenig editor.' : ''); - const [editorAPI, setEditorAPI] = useState(null); - const titleRef = React.useRef(null); - const containerRef = React.useRef(null); + const [editorAPI, setEditorAPI] = useState(null); + const titleRef = React.useRef(null); + const containerRef = React.useRef(null); function openSidebar(view = 'json') { if (isSidebarOpen && sidebarView === view) { @@ -216,27 +276,29 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { // mouseup/click event can occur outside of the initially clicked node, in // which case we don't want to then "re-focus" the editor and cause unexpected // selection changes - function maybeSkipFocusEditor(event) { - const clickedOnDecorator = (event.target.closest('[data-lexical-decorator]') !== null) || event.target.hasAttribute('data-lexical-decorator'); - const clickedOnSlashMenu = (event.target.closest('[data-kg-slash-menu]') !== null) || event.target.hasAttribute('data-kg-slash-menu'); - const clickedOnPortal = (event.target.closest('[data-kg-portal]') !== null) || event.target.hasAttribute('data-kg-portal'); + function maybeSkipFocusEditor(event: React.MouseEvent) { + const target = event.target as HTMLElement; + const clickedOnDecorator = (target.closest('[data-lexical-decorator]') !== null) || target.hasAttribute('data-lexical-decorator'); + const clickedOnSlashMenu = (target.closest('[data-kg-slash-menu]') !== null) || target.hasAttribute('data-kg-slash-menu'); + const clickedOnPortal = (target.closest('[data-kg-portal]') !== null) || target.hasAttribute('data-kg-portal'); if (clickedOnDecorator || clickedOnSlashMenu || clickedOnPortal) { skipFocusEditor.current = true; } } - function focusEditor(event) { - const clickedOnDecorator = (event.target.closest('[data-lexical-decorator]') !== null) || event.target.hasAttribute('data-lexical-decorator'); - const clickedOnSlashMenu = (event.target.closest('[data-kg-slash-menu]') !== null) || event.target.hasAttribute('data-kg-slash-menu'); - const clickedOnPortal = (event.target.closest('[data-kg-portal]') !== null) || event.target.hasAttribute('data-kg-portal'); + function focusEditor(event: React.MouseEvent) { + const target = event.target as HTMLElement; + const clickedOnDecorator = (target.closest('[data-lexical-decorator]') !== null) || target.hasAttribute('data-lexical-decorator'); + const clickedOnSlashMenu = (target.closest('[data-kg-slash-menu]') !== null) || target.hasAttribute('data-kg-slash-menu'); + const clickedOnPortal = (target.closest('[data-kg-portal]') !== null) || target.hasAttribute('data-kg-portal'); if (!skipFocusEditor.current && editorAPI && !clickedOnDecorator && !clickedOnSlashMenu && !clickedOnPortal) { - let editor = editorAPI.editorInstance; + const editor = editorAPI.editorInstance as {_rootElement: HTMLElement; getEditorState: () => {read: (fn: () => void) => void}}; // if a mousedown and subsequent mouseup occurs below the editor // canvas, focus the editor and put the cursor at the end of the document - let {bottom} = editor._rootElement.getBoundingClientRect(); + const {bottom} = editor._rootElement.getBoundingClientRect(); if (event.pageY > bottom && event.clientY > bottom) { event.preventDefault(); @@ -262,7 +324,7 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { editorAPI.focusEditor({position: 'bottom'}); //scroll to the bottom of the container - containerRef.current.scrollTop = containerRef.current.scrollHeight; + containerRef.current!.scrollTop = containerRef.current!.scrollHeight; } } @@ -279,19 +341,19 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { } function saveContent() { - const serializedState = editorAPI.serialize(); + const serializedState = editorAPI!.serialize(); const encodedContent = encodeURIComponent(serializedState); searchParams.set('content', encodedContent); setSearchParams(searchParams); } React.useEffect(() => { - const handleFileDrag = (event) => { + const handleFileDrag = (event: DragEvent) => { event.preventDefault(); }; - const handleFileDrop = (event) => { - if (event.dataTransfer.files.length > 0) { + const handleFileDrop = (event: DragEvent) => { + if (event.dataTransfer && event.dataTransfer.files.length > 0) { event.preventDefault(); editorAPI?.insertFiles(Array.from(event.dataTransfer.files)); } @@ -306,7 +368,7 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { }; }, [editorAPI]); - const showTitle = !isMultiplayer && !['basic', 'minimal', 'email'].includes(editorType); + const showTitle = !isMultiplayer && !['basic', 'minimal', 'email'].includes(editorType || ''); const isEmailEditor = editorType === 'email'; const cardConfig = { @@ -324,99 +386,83 @@ function DemoComposer({editorType, isMultiplayer, setWordCount, setTKCount}) { deprecated: { headerV1: hideDeprecatedCardInMenu(searchParams), emailCta: hideDeprecatedCardInMenu(searchParams) - } + }, + ...(isEmailEditor ? { + image: { + ...((defaultCardConfig as Record).image as Record || {}), + allowedWidths: ['regular'] + }, + visibilitySettings: VISIBILITY_SETTINGS.EMAIL_ONLY + } : {}) }; - const fileUploader = {useFileUpload: useFileUpload({isMultiplayer}), fileTypes}; - - // Sidebar uses useLexicalComposerContext so it must be inside a KoenigComposer. - // The email editor manages its own composer, so the sidebar is only available - // for non-email editor types. - const demoChrome = ( - <> - - {!isEmailEditor && ( -
- - -
- )} - - ); - - const demoLayout = (children) => ( -
- { - !isMultiplayer && !isEmailEditor && contentParam !== 'false' - ? - : null - } - -
-
- {showTitle - ? - : null - } - {children} -
-
-
- ); - - // Email editor includes its own KoenigComposer, so it renders outside the shared one - if (isEmailEditor) { - return ( - <> - {demoLayout( - - - - - - )} - {demoChrome} - - ); - } - return ( - {demoLayout( - - )} - {demoChrome} +
+ { + !isMultiplayer + ? + : null + } + +
+
+ {showTitle + ? + : null + } + {editorType === 'email' ? ( + + void} + setTKCount={setTKCount} + setWordCount={setWordCount} + /> + + ) : ( + void} + setTKCount={setTKCount} + setWordCount={setWordCount} + /> + )} +
+
+
+ +
+ + +
); } const MemoizedDemoComposer = React.memo(DemoComposer); -function DemoApp({editorType, isMultiplayer}) { +interface DemoAppProps { + editorType?: string; + isMultiplayer?: boolean; + introContent?: boolean; +} + +function DemoApp({editorType, isMultiplayer}: DemoAppProps) { const [wordCount, setWordCount] = useState(0); const [tkCount, setTKCount] = useState(0); diff --git a/packages/koenig-lexical/demo/HtmlOutputDemo.tsx b/packages/koenig-lexical/demo/HtmlOutputDemo.tsx index bb65f9e9da..73faa7497e 100644 --- a/packages/koenig-lexical/demo/HtmlOutputDemo.tsx +++ b/packages/koenig-lexical/demo/HtmlOutputDemo.tsx @@ -21,9 +21,14 @@ function HtmlOutputDemo() { const [html, setHtml] = useState('

check ghost.org/changelog/markdown/

'); const [sidebarView, setSidebarView] = useState('json'); const [defaultContent] = useState(undefined); - const [editorAPI, setEditorAPI] = useState(null); - const titleRef = React.useRef(null); - const containerRef = React.useRef(null); + const [editorAPI, setEditorAPI] = useState<{ + editorInstance: unknown; + insertParagraphAtBottom: () => void; + focusEditor: (options: {position: string}) => void; + [key: string]: unknown; + } | null>(null); + const titleRef = React.useRef<{focus: () => void} | null>(null); + const containerRef = React.useRef(null); const {snippets, createSnippet, deleteSnippet} = useSnippets(); function openSidebar(view = 'json') { @@ -38,13 +43,14 @@ function HtmlOutputDemo() { titleRef.current?.focus(); } - function focusEditor(event) { - const clickedOnDecorator = (event.target.closest('[data-lexical-decorator]') !== null) || event.target.hasAttribute('data-lexical-decorator'); - const clickedOnSlashMenu = (event.target.closest('[data-kg-slash-menu]') !== null) || event.target.hasAttribute('data-kg-slash-menu'); + function focusEditor(event: React.MouseEvent) { + const target = event.target as HTMLElement; + const clickedOnDecorator = (target.closest('[data-lexical-decorator]') !== null) || target.hasAttribute('data-lexical-decorator'); + const clickedOnSlashMenu = (target.closest('[data-kg-slash-menu]') !== null) || target.hasAttribute('data-kg-slash-menu'); if (editorAPI && !clickedOnDecorator && !clickedOnSlashMenu) { - let editor = editorAPI.editorInstance; - let {bottom} = editor._rootElement.getBoundingClientRect(); + const editor = editorAPI.editorInstance as {_rootElement: HTMLElement; getEditorState: () => {read: (fn: () => void) => void}}; + const {bottom} = editor._rootElement.getBoundingClientRect(); // if a mousedown and subsequent mouseup occurs below the editor // canvas, focus the editor and put the cursor at the end of the document @@ -73,7 +79,7 @@ function HtmlOutputDemo() { editorAPI.focusEditor({position: 'bottom'}); //scroll to the bottom of the container - containerRef.current.scrollTop = containerRef.current.scrollHeight; + containerRef.current!.scrollTop = containerRef.current!.scrollHeight; } } } @@ -86,7 +92,7 @@ function HtmlOutputDemo() { >
@@ -94,7 +100,7 @@ function HtmlOutputDemo() {
void} > diff --git a/packages/koenig-lexical/demo/RestrictedContentDemo.tsx b/packages/koenig-lexical/demo/RestrictedContentDemo.tsx index 1c4b25cd9b..41701123dd 100644 --- a/packages/koenig-lexical/demo/RestrictedContentDemo.tsx +++ b/packages/koenig-lexical/demo/RestrictedContentDemo.tsx @@ -23,15 +23,20 @@ function useQuery() { return React.useMemo(() => new URLSearchParams(search), [search]); } -function RestrictedContentDemo() { - let query = useQuery(); +function RestrictedContentDemo(_props: {paragraphs?: number}) { + const query = useQuery(); const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [sidebarView, setSidebarView] = useState('json'); const [defaultContent] = useState(undefined); - const [editorAPI, setEditorAPI] = useState(null); - const titleRef = React.useRef(null); - const containerRef = React.useRef(null); - const paragraphs = query.get('paragraphs') || 1; + const [editorAPI, setEditorAPI] = useState<{ + editorInstance: unknown; + insertParagraphAtBottom: () => void; + focusEditor: (options: {position: string}) => void; + [key: string]: unknown; + } | null>(null); + const titleRef = React.useRef<{focus: () => void} | null>(null); + const containerRef = React.useRef(null); + const paragraphs = Number(query.get('paragraphs')) || 1; const {snippets, createSnippet, deleteSnippet} = useSnippets(); function openSidebar(view = 'json') { @@ -46,13 +51,14 @@ function RestrictedContentDemo() { titleRef.current?.focus(); } - function focusEditor(event) { - const clickedOnDecorator = (event.target.closest('[data-lexical-decorator]') !== null) || event.target.hasAttribute('data-lexical-decorator'); - const clickedOnSlashMenu = (event.target.closest('[data-kg-slash-menu]') !== null) || event.target.hasAttribute('data-kg-slash-menu'); + function focusEditor(event: React.MouseEvent) { + const target = event.target as HTMLElement; + const clickedOnDecorator = (target.closest('[data-lexical-decorator]') !== null) || target.hasAttribute('data-lexical-decorator'); + const clickedOnSlashMenu = (target.closest('[data-kg-slash-menu]') !== null) || target.hasAttribute('data-kg-slash-menu'); if (editorAPI && !clickedOnDecorator && !clickedOnSlashMenu) { - let editor = editorAPI.editorInstance; - let {bottom} = editor._rootElement.getBoundingClientRect(); + const editor = editorAPI.editorInstance as {_rootElement: HTMLElement; getEditorState: () => {read: (fn: () => void) => void}}; + const {bottom} = editor._rootElement.getBoundingClientRect(); // if a mousedown and subsequent mouseup occurs below the editor // canvas, focus the editor and put the cursor at the end of the document @@ -81,7 +87,9 @@ function RestrictedContentDemo() { editorAPI.focusEditor({position: 'bottom'}); //scroll to the bottom of the container - containerRef.current.scrollTop = containerRef.current.scrollHeight; + if (containerRef.current) { + containerRef.current.scrollTop = containerRef.current.scrollHeight; + } } } } @@ -92,7 +100,7 @@ function RestrictedContentDemo() { >
@@ -100,7 +108,7 @@ function RestrictedContentDemo() {
void} > diff --git a/packages/koenig-lexical/demo/components/DarkModeToggle.tsx b/packages/koenig-lexical/demo/components/DarkModeToggle.tsx index cb39d8eaba..48833e77c8 100644 --- a/packages/koenig-lexical/demo/components/DarkModeToggle.tsx +++ b/packages/koenig-lexical/demo/components/DarkModeToggle.tsx @@ -1,4 +1,9 @@ -const DarkModeToggle = ({darkMode, toggleDarkMode}) => { +interface DarkModeToggleProps { + darkMode: boolean; + toggleDarkMode: () => void; +} + +const DarkModeToggle = ({darkMode, toggleDarkMode}: DarkModeToggleProps) => { return ( <>
); } else if (IndicatorIcon) { + const Icon = IndicatorIcon as React.ComponentType>; indicatorIcon = (
- @@ -99,21 +116,10 @@ export const CardWrapper = React.forwardRef(({ data-kg-card-selected={isSelected} {...props} > - {children} + {children as React.ReactNode}
); }); CardWrapper.displayName = 'CardWrapper'; - -CardWrapper.propTypes = { - isSelected: PropTypes.bool, - isEditing: PropTypes.bool, - cardWidth: PropTypes.oneOf(['regular', 'wide', 'full']), - icon: PropTypes.string, - indicatorPosition: PropTypes.shape({ - left: PropTypes.string, - top: PropTypes.string - }) -}; diff --git a/packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx b/packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx index c1794512ce..342dfc2405 100644 --- a/packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx +++ b/packages/koenig-lexical/src/components/ui/ColorOptionButtons.tsx @@ -4,9 +4,21 @@ import {Tooltip} from './Tooltip'; import {useClickOutside} from '../../hooks/useClickOutside'; import {usePreviousFocus} from '../../hooks/usePreviousFocus'; -export function ColorOptionButtons({buttons = [], selectedName, onClick}) { +interface ColorOptionButton { + label: string; + name: string; + color?: string; +} + +interface ColorOptionButtonsProps { + buttons?: ColorOptionButton[]; + selectedName?: string; + onClick: (name: string) => void; +} + +export function ColorOptionButtons({buttons = [], selectedName, onClick}: ColorOptionButtonsProps) { const [isOpen, setIsOpen] = useState(false); - const componentRef = React.useRef(null); + const componentRef = React.useRef(null); const selectedButton = buttons.find(button => button.name === selectedName); @@ -49,13 +61,13 @@ export function ColorOptionButtons({buttons = [], selectedName, onClick}) { label={label} name={name} selectedName={selectedName} - onClick={(title) => { + onClick={(title: string) => { onClick(title); setIsOpen(false); }} /> : -
  • onClick(name)}> +
  • onClick(name)}> @@ -69,7 +81,16 @@ export function ColorOptionButtons({buttons = [], selectedName, onClick}) { ); } -export function ColorButton({onClick, label, name, color, selectedName}) { +interface ColorButtonProps { + onClick: (name: string) => void; + label: string; + name: string; + color?: string; + selectedName?: string; + [key: string]: unknown; +} + +export function ColorButton({onClick, label, name, color, selectedName}: ColorButtonProps) { const isActive = name === selectedName; const {handleMousedown, handleClick} = usePreviousFocus(onClick, name); diff --git a/packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx b/packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx index b6bacf0b41..9a748732ef 100644 --- a/packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/ColorPicker.stories.tsx @@ -1,6 +1,7 @@ import {ColorPicker} from './ColorPicker'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Generic/Color picker (New)', component: ColorPicker, parameters: { @@ -9,12 +10,12 @@ const story = { } }, argTypes: { - selectedName: {control: 'select', options: ['grey', 'blue', 'green', 'yellow', 'red', 'pink', 'purple']} + value: {control: 'text'} } }; export default story; -const Template = (args) => { +const Template: StoryFn = (args) => { return (
    @@ -24,9 +25,7 @@ const Template = (args) => { export const Default = Template.bind({}); Default.args = { - swatches: [ - {title: 'Brand color', accent: true}, - {title: 'Black', hex: '#000000'}, - {title: 'Transparent', transparent: true} - ] + value: '#000000', + hasTransparentOption: true, + onChange: () => {} }; diff --git a/packages/koenig-lexical/src/components/ui/ColorPicker.tsx b/packages/koenig-lexical/src/components/ui/ColorPicker.tsx index e10e658f80..1e331aaff6 100644 --- a/packages/koenig-lexical/src/components/ui/ColorPicker.tsx +++ b/packages/koenig-lexical/src/components/ui/ColorPicker.tsx @@ -8,11 +8,19 @@ import {Tooltip} from './Tooltip'; import {getAccentColor} from '../../utils/getAccentColor'; import {useClickOutside} from '../../hooks/useClickOutside'; -export function ColorPicker({value, eyedropper, hasTransparentOption, onChange, children}) { +export interface ColorPickerProps { + value?: string; + eyedropper?: boolean; + hasTransparentOption?: boolean; + onChange: (color: string) => void; + children?: React.ReactNode; +} + +export function ColorPicker({value, eyedropper, hasTransparentOption, onChange, children}: ColorPickerProps) { // HexColorInput doesn't support adding a ref on the input itself - const inputWrapperRef = useRef(null); + const inputWrapperRef = useRef(null); - const stopPropagation = useCallback((e) => { + const stopPropagation = useCallback((e: React.MouseEvent | React.TouchEvent) => { e.stopPropagation(); const inputElement = inputWrapperRef.current?.querySelector('input'); @@ -46,15 +54,15 @@ export function ColorPicker({value, eyedropper, hasTransparentOption, onChange, document.addEventListener('touchend', stopUsingColorPicker); }, [stopUsingColorPicker]); - const openColorPicker = useCallback((e) => { + const openColorPicker = useCallback((e: React.MouseEvent) => { e.preventDefault(); isUsingColorPicker.current = true; document.body.style.setProperty('pointer-events', 'none'); - const eyeDropper = new window.EyeDropper(); + const eyeDropper = new (window as unknown as {EyeDropper: new () => {open: () => Promise<{sRGBHex: string}>}}).EyeDropper(); eyeDropper.open() - .then(result => onChange(result.sRGBHex)) + .then((result: {sRGBHex: string}) => onChange(result.sRGBHex)) .finally(() => { isUsingColorPicker.current = false; document.body.style.removeProperty('pointer-events'); @@ -73,7 +81,7 @@ export function ColorPicker({value, eyedropper, hasTransparentOption, onChange, hexValue = ''; } - const focusHexInputOnClick = useCallback((e) => { + const focusHexInputOnClick = useCallback(() => { inputWrapperRef.current?.querySelector('input')?.focus(); }, []); @@ -84,7 +92,7 @@ export function ColorPicker({value, eyedropper, hasTransparentOption, onChange,
    # - {eyedropper && !!window.EyeDropper && ( + {eyedropper && !!(window as unknown as {EyeDropper?: unknown}).EyeDropper && ( {open && ( - defaultSelected={selectedItem} getItem={getItem} items={menu} diff --git a/packages/koenig-lexical/src/components/ui/DropdownContainer.tsx b/packages/koenig-lexical/src/components/ui/DropdownContainer.tsx index 1e4c80d6ab..91cf110117 100644 --- a/packages/koenig-lexical/src/components/ui/DropdownContainer.tsx +++ b/packages/koenig-lexical/src/components/ui/DropdownContainer.tsx @@ -9,6 +9,16 @@ import debounce from 'lodash/debounce'; * Displays the dropdown above or below the parent element, depending on the space available in the viewport. * The parent should be positioned relative. */ + +interface DropdownContainerProps { + dataTestId?: string; + className?: string; + placementTopClass?: string; + placementBottomClass?: string; + children?: React.ReactNode; + [key: string]: unknown; +} + export function DropdownContainer({ dataTestId, className = 'z-[-1] max-h-[30vh] w-full overflow-y-auto bg-white shadow rounded-lg dark:border-grey-800 dark:bg-grey-900', @@ -16,8 +26,8 @@ export function DropdownContainer({ placementBottomClass = 'mt-0.5', children, ...props -}) { - const divRef = React.useRef(null); +}: DropdownContainerProps) { + const divRef = React.useRef(null); const [placement, setPlacement] = React.useState('bottom'); @@ -27,7 +37,7 @@ export function DropdownContainer({ } // Get the position of divRef on the screen - const box = divRef.current.parentNode.getBoundingClientRect(); + const box = (divRef.current.parentNode as HTMLElement).getBoundingClientRect(); const bottom = box.bottom; const spaceBelow = window.innerHeight - bottom; @@ -53,7 +63,7 @@ export function DropdownContainer({ window.addEventListener('resize', updatePlacementDebounced, {passive: true}); return () => { - window.removeEventListener('resize', updatePlacementDebounced, {passive: true}); + window.removeEventListener('resize', updatePlacementDebounced); }; }, []); diff --git a/packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx b/packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx index 4109e03c53..9c31fd289e 100644 --- a/packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx +++ b/packages/koenig-lexical/src/components/ui/EditorPlaceholder.tsx @@ -1,4 +1,9 @@ -export function EditorPlaceholder({className, text}) { +interface EditorPlaceholderProps { + className?: string; + text?: string; +} + +export function EditorPlaceholder({className, text}: EditorPlaceholderProps) { return (
    void; + [key: string]: unknown; +} + +export default function EmojiPicker({setInstanceRef, ...props}: EmojiPickerProps) { + const ref = useRef(null); + const instance = useRef<{update: (props: Record) => void} | null>(null); - function setInstance(newInstance) { + function setInstance(newInstance: {update: (props: Record) => void} | null) { instance.current = newInstance; setInstanceRef?.(newInstance); } - if (instance.current) { + if (instance.current && typeof instance.current.update === 'function') { instance.current.update(props); } @@ -21,7 +26,7 @@ export default function EmojiPicker({setInstanceRef, ...props}) { // copy's class gets registered with customElements.define(). Instantiating // an unregistered class throws "Illegal constructor". const RegisteredPicker = customElements.get('em-emoji-picker') || Picker; - setInstance(new RegisteredPicker({...props, ref})); + setInstance(new (RegisteredPicker as unknown as new (opts: unknown) => {update: (props: Record) => void})({...props, ref})); return () => { setInstance(null); diff --git a/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx b/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx index abfa7f9c34..9c086138f5 100644 --- a/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx +++ b/packages/koenig-lexical/src/components/ui/EmojiPickerPortal.tsx @@ -1,10 +1,34 @@ import KoenigComposerContext from '../../context/KoenigComposerContext'; import Picker from './EmojiPicker'; import Portal from './Portal'; -import PropTypes from 'prop-types'; import React from 'react'; import defaultData from '@emoji-mart/data'; +interface EmojiPickerPortalProps { + onEmojiClick?: (emoji: {native: string}) => void; + positionRef: React.RefObject; + data?: unknown; + autoFocus?: boolean; + dynamicWidth?: boolean; + emojiButtonRadius?: string; + emojiButtonSize?: number; + emojiSize?: number; + icons?: 'auto' | 'outline' | 'solid'; + locale?: string; + maxFrequentRows?: number; + navPosition?: 'top' | 'bottom' | 'none'; + noCountryFlags?: boolean; + noResultsEmoji?: string; + perLine?: number; + previewEmoji?: string | null; + previewPosition?: 'top' | 'bottom' | 'none'; + searchPosition?: 'sticky' | 'static' | 'none'; + set?: 'native' | 'apple' | 'facebook' | 'google' | 'twitter'; + skin?: 1 | 2 | 3 | 4 | 5 | 6; + skinTonePosition?: 'preview' | 'search' | 'none'; + [key: string]: unknown; +} + const EmojiPickerPortal = ({ onEmojiClick, positionRef, @@ -28,8 +52,8 @@ const EmojiPickerPortal = ({ skin = 1, skinTonePosition = 'preview', ...props -}) => { - const [position, setPosition] = React.useState(null); +}: EmojiPickerPortalProps) => { + const [position, setPosition] = React.useState<{x: number; y: number} | null>(null); const {darkMode} = React.useContext(KoenigComposerContext); const shiftPixels = 35; // how many pixels we want to move it up when it's at the bottom of the screen @@ -64,11 +88,11 @@ const EmojiPickerPortal = ({ } const {x, y} = position; - const handleClick = (e) => { + const handleClick = (e: React.MouseEvent) => { e.stopPropagation(); }; - const style = { + const style: React.CSSProperties = { left: x, top: y, position: 'fixed' @@ -115,31 +139,3 @@ const EmojiPickerPortal = ({ }; export default EmojiPickerPortal; - -EmojiPickerPortal.propTypes = { - onEmojiClick: PropTypes.func.isRequired, - positionRef: PropTypes.object, - data: PropTypes.array, - autoFocus: PropTypes.bool, - dynamicWidth: PropTypes.bool, - emojiButtonColors: PropTypes.arrayOf(PropTypes.string), - emojiButtonRadius: PropTypes.string, - emojiButtonSize: PropTypes.number, - emojiSize: PropTypes.number, - emojiVersion: PropTypes.oneOf([1, 2, 3, 4, 5, 11, 12, 12.1, 13, 13.1, 14]), - exceptEmojis: PropTypes.arrayOf(PropTypes.string), - icons: PropTypes.oneOf(['auto', 'outline', 'solid']), - locale: PropTypes.oneOf(['en','ar','be','cs','de','es','fa','fi','fr','hi','it','ja','kr','nl','pl','pt','ru','sa','tr','uk','vi','zh']), - maxFrequentRows: PropTypes.number, - navPosition: PropTypes.oneOf(['top', 'bottom', 'none']), - noCountryFlags: PropTypes.bool, - noResultsEmoji: PropTypes.string, - perLine: PropTypes.number, - previewEmoji: PropTypes.string, - previewPosition: PropTypes.oneOf(['top', 'bottom', 'none']), - searchPosition: PropTypes.oneOf(['sticky', 'static', 'none']), - set: PropTypes.oneOf(['native', 'apple', 'facebook', 'google', 'twitter']), - setInstanceRef: PropTypes.func, - skin: PropTypes.oneOf([1, 2, 3, 4, 5, 6]), - skinTonePosition: PropTypes.oneOf(['preview', 'search', 'none']) -}; diff --git a/packages/koenig-lexical/src/components/ui/FileUploadForm.tsx b/packages/koenig-lexical/src/components/ui/FileUploadForm.tsx index ad66a083a9..790187c11f 100644 --- a/packages/koenig-lexical/src/components/ui/FileUploadForm.tsx +++ b/packages/koenig-lexical/src/components/ui/FileUploadForm.tsx @@ -1,11 +1,20 @@ -export function FileUploadForm({onFileChange, fileInputRef}) { +import React from 'react'; + +interface FileUploadFormProps { + onFileChange: (e: React.ChangeEvent) => void; + fileInputRef: React.Ref; + setFileInputRef?: (ref: React.RefObject) => void; +} + +export function FileUploadForm({onFileChange, fileInputRef}: FileUploadFormProps) { return ( -
    +
    ); diff --git a/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx b/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx index 8588e81efd..f77cc48442 100644 --- a/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx +++ b/packages/koenig-lexical/src/components/ui/FloatingFormatToolbar.tsx @@ -1,13 +1,14 @@ import FloatingToolbar from '../../components/ui/FloatingToolbar'; import FormatToolbar from './FormatToolbar'; -import KoenigComposerContext from '../../context/KoenigComposerContext.jsx'; +import KoenigComposerContext from '../../context/KoenigComposerContext'; import React from 'react'; import debounce from 'lodash/debounce'; import {$getSelection, $isRangeSelection, COMMAND_PRIORITY_LOW, DELETE_CHARACTER_COMMAND} from 'lexical'; -import {LinkActionToolbar} from './LinkActionToolbar.jsx'; -import {LinkActionToolbarWithSearch} from './LinkActionToolbarWithSearch.jsx'; +import {LinkActionToolbar} from './LinkActionToolbar'; +import {LinkActionToolbarWithSearch} from './LinkActionToolbarWithSearch'; import {SnippetActionToolbar} from './SnippetActionToolbar'; import {mergeRegister} from '@lexical/utils'; +import type {LexicalEditor} from 'lexical'; // don't show the toolbar until the mouse has moved a certain distance, // avoids accidental toolbar display when clicking buttons that select content @@ -19,6 +20,16 @@ export const toolbarItemTypes = { text: 'text' }; +interface FloatingFormatToolbarProps { + editor: LexicalEditor; + anchorElem?: HTMLElement; + href?: string; + isSnippetsEnabled?: boolean; + toolbarItemType?: string | null; + setToolbarItemType: (type: string | null) => void; + hiddenFormats?: string[]; +} + export function FloatingFormatToolbar({ editor, anchorElem, @@ -27,34 +38,35 @@ export function FloatingFormatToolbar({ toolbarItemType, setToolbarItemType, hiddenFormats = [] -}) { +}: FloatingFormatToolbarProps) { const {cardConfig} = React.useContext(KoenigComposerContext); const isLinkSearchEnabled = typeof cardConfig?.searchLinks === 'function' || false; - const toolbarRef = React.useRef(null); + const toolbarRef = React.useRef(null); const isLinkSearchToolbarVisible = toolbarItemType === toolbarItemTypes.link && isLinkSearchEnabled; // toolbar opacity is 0 by default // shouldn't display until selection via mouse is complete to avoid toolbar re-positioning while dragging - const showToolbarIfHidden = React.useCallback((e) => { + const showToolbarIfHidden = React.useCallback(() => { if (toolbarItemType && toolbarRef.current?.style.opacity === '0') { toolbarRef.current.style.opacity = '1'; } }, [toolbarItemType]); React.useEffect(() => { - const toggle = (e) => { + const toggle = (e: MouseEvent | TouchEvent) => { editor.getEditorState().read(() => { const selection = $getSelection(); - if ($isRangeSelection(selection)) { + const target = e.target; + if ($isRangeSelection(selection) && target instanceof Node) { const selectedNodeMatchesTarget = selection.getNodes().find((node) => { const element = editor.getElementByKey(node.getKey()); - return element && (element.contains(e.target) || e.target.contains(element)); + return element && (element.contains(target) || target.contains(element)); }); if (selectedNodeMatchesTarget) { - showToolbarIfHidden(e); + showToolbarIfHidden(); } } }); @@ -84,9 +96,9 @@ export function FloatingFormatToolbar({ }, [editor, setToolbarItemType]); React.useEffect(() => { - let initialPosition = null; + let initialPosition: {x: number; y: number} | null = null; - const onMouseMove = (e) => { + const onMouseMove = (e: MouseEvent) => { // ignore drag events if (e?.buttons > 0) { return; @@ -147,12 +159,10 @@ export function FloatingFormatToolbar({ <> {isSnippetToolbar && ( diff --git a/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx b/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx index b5fe08c1f3..b1e07fd543 100644 --- a/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx +++ b/packages/koenig-lexical/src/components/ui/FloatingLinkToolbar.tsx @@ -6,13 +6,20 @@ import {$isLinkNode} from '@lexical/link'; import {LinkToolbar} from './LinkToolbar'; import {TOGGLE_LINK_COMMAND} from '@lexical/link'; import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; +import type {LinkNode} from '@lexical/link'; -export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}) { +interface FloatingLinkToolbarProps { + anchorElem?: HTMLElement; + onEditLink: (opts: {href: string}) => void; + disabled?: boolean; +} + +export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}: FloatingLinkToolbarProps) { const [editor] = useLexicalComposerContext(); - const [linkNode, setLinkNode] = React.useState(null); + const [linkNode, setLinkNode] = React.useState(null); const [href, setHref] = React.useState(''); - const toolbarRef = React.useRef(null); - const [targetElem, setTargetElem] = React.useState(null); + const toolbarRef = React.useRef(null); + const [targetElem, setTargetElem] = React.useState(null); React.useEffect(() => { if (disabled) { @@ -23,14 +30,14 @@ export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}) { return; } - const onMouseEnter = (event) => { - if (toolbarRef.current?.contains(event.target)) { + const onMouseEnter = (event: MouseEvent) => { + if (toolbarRef.current?.contains(event.target as Node)) { return; } editor.update(() => { - const node = $getNearestNodeFromDOMNode(event.target); - setTargetElem(event.target); + const node = $getNearestNodeFromDOMNode(event.target as Node); + setTargetElem(event.target as HTMLElement); const isLink = $isLinkNode(node) || $isLinkNode(node?.getParent()); if (!isLink) { @@ -40,7 +47,7 @@ export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}) { return; } - let link = $isLinkNode(node) ? node : node.getParent(); + const link = ($isLinkNode(node) ? node : node?.getParent()) as LinkNode; setLinkNode(link); setHref(link.getURL()); @@ -59,14 +66,20 @@ export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}) { const onEdit = () => { editor.update(() => { + if (!linkNode) { + return; + } const selection = $createRangeSelection(); - // select all children because createRectsFromDOMRange method from lexical is not working properly for link node - selection.setTextNodeRange( - linkNode.getFirstChild(), - 0, - linkNode.getLastChild(), - linkNode.getLastChild().getTextContentSize() - ); + const firstChild = linkNode.getFirstChild(); + const lastChild = linkNode.getLastChild(); + if (firstChild && lastChild) { + selection.setTextNodeRange( + firstChild, + 0, + lastChild, + lastChild.getTextContentSize() + ); + } $setSelection(selection); onEditLink({href}); }); @@ -74,6 +87,9 @@ export function FloatingLinkToolbar({anchorElem, onEditLink, disabled}) { const onRemove = () => { editor.update(() => { + if (!linkNode) { + return; + } linkNode.select(); editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); setLinkNode(null); diff --git a/packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx b/packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx index bb3a13edc8..1733a101d1 100644 --- a/packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx +++ b/packages/koenig-lexical/src/components/ui/FloatingToolbar.tsx @@ -4,6 +4,19 @@ import {$getSelection} from 'lexical'; import {$getSelectionRangeRect} from '../../utils/$getSelectionRangeRect'; import {getScrollParent} from '../../utils/getScrollParent'; import {setFloatingElemPosition} from '../../utils/setFloatingElemPosition'; +import type {LexicalEditor} from 'lexical'; + +interface FloatingToolbarProps { + anchorElem?: HTMLElement; + children?: React.ReactNode; + editor: LexicalEditor; + isVisible?: boolean; + toolbarRef: React.RefObject; + targetElem?: HTMLElement | null; + onReposition?: () => void; + shouldReposition?: boolean; + controlOpacity?: boolean; +} export default function FloatingToolbar({ anchorElem, @@ -15,7 +28,7 @@ export default function FloatingToolbar({ onReposition, shouldReposition = true, controlOpacity -}) { +}: FloatingToolbarProps) { const updateToolbarPosition = React.useCallback((reposition = true) => { editor.update(() => { const toolbarElement = toolbarRef?.current; @@ -43,7 +56,7 @@ export default function FloatingToolbar({ return; } - setFloatingElemPosition(rangeRect, toolbarElement, anchorElem, {controlOpacity}); + setFloatingElemPosition(rangeRect, toolbarElement, anchorElem!, {controlOpacity}); }); }, [anchorElem, controlOpacity, editor, targetElem, toolbarRef]); @@ -58,17 +71,20 @@ export default function FloatingToolbar({ }, [isVisible, onReposition, shouldReposition, updateToolbarPosition]); React.useEffect(() => { - const scrollElement = getScrollParent(anchorElem); + const scrollElement = getScrollParent(anchorElem ?? null); + + const handleResize = () => updateToolbarPosition(); + const handleScroll = () => updateToolbarPosition(); - window.addEventListener('resize', updateToolbarPosition); + window.addEventListener('resize', handleResize); if (scrollElement) { - scrollElement.addEventListener('scroll', updateToolbarPosition); + scrollElement.addEventListener('scroll', handleScroll); } return () => { - window.removeEventListener('resize', updateToolbarPosition); + window.removeEventListener('resize', handleResize); if (scrollElement) { - scrollElement.removeEventListener('scroll', updateToolbarPosition); + scrollElement.removeEventListener('scroll', handleScroll); } }; }, [anchorElem, updateToolbarPosition]); @@ -79,7 +95,7 @@ export default function FloatingToolbar({ return ( -
    +
    } className="not-kg-prose fixed z-[10000]" style={{opacity: 0, transition: 'opacity 100ms ease'}} data-kg-floating-toolbar> {children}
    diff --git a/packages/koenig-lexical/src/components/ui/FormatToolbar.tsx b/packages/koenig-lexical/src/components/ui/FormatToolbar.tsx index 86bb1f4d76..87fd7f1ca4 100644 --- a/packages/koenig-lexical/src/components/ui/FormatToolbar.tsx +++ b/packages/koenig-lexical/src/components/ui/FormatToolbar.tsx @@ -23,8 +23,10 @@ import { } from './ToolbarMenu'; import {altOrOption, ctrlOrCmdSymbol, ctrlOrSymbol} from '../../utils/shortcutSymbols'; import {getSelectedNode} from '../../utils/getSelectedNode'; +import type {HeadingTagType} from '@lexical/rich-text'; +import type {LexicalEditor} from 'lexical'; -const blockTypeToBlockName = { +const blockTypeToBlockName: Record = { bullet: 'Bulleted List', check: 'Check List', code: 'Code Block', @@ -51,6 +53,15 @@ function quoteIcon(blockType = '') { } } +interface FormatToolbarProps { + editor: LexicalEditor; + isSnippetsEnabled?: boolean; + isLinkSelected?: boolean; + onLinkClick?: () => void; + onSnippetClick?: () => void; + hiddenFormats?: string[]; +} + export default function FormatToolbar({ editor, isSnippetsEnabled, @@ -58,7 +69,7 @@ export default function FormatToolbar({ onLinkClick, onSnippetClick, hiddenFormats = [] -}) { +}: FormatToolbarProps) { const [isBold, setIsBold] = React.useState(false); const [isItalic, setIsItalic] = React.useState(false); const [blockType, setBlockType] = React.useState('paragraph'); @@ -73,7 +84,7 @@ export default function FormatToolbar({ if (!editor.hasNodes([QuoteNode])){ hideQuotes = true; } - + let hideSnippets = !isSnippetsEnabled || !createSnippet; // don't show snippet toolbar if we can't create them if (editor._parentEditor) { hideSnippets = true; @@ -146,7 +157,7 @@ export default function FormatToolbar({ } }; - const formatHeading = (headingSize) => { + const formatHeading = (headingSize: HeadingTagType) => { if (blockType !== headingSize) { editor.update(() => { const selection = $getSelection(); diff --git a/packages/koenig-lexical/src/components/ui/GifPlugin.tsx b/packages/koenig-lexical/src/components/ui/GifPlugin.tsx index 0763ff3f27..20215beb7e 100644 --- a/packages/koenig-lexical/src/components/ui/GifPlugin.tsx +++ b/packages/koenig-lexical/src/components/ui/GifPlugin.tsx @@ -1,19 +1,25 @@ -import GifSelector from './GifSelector'; -import KoenigComposerContext from '../../context/KoenigComposerContext.jsx'; +import GifSelector, {type GifSelectorProps} from './GifSelector'; +import KoenigComposerContext from '../../context/KoenigComposerContext'; import React from 'react'; -import {DELETE_CARD_COMMAND} from '../../plugins/KoenigBehaviourPlugin.jsx'; -import {INSERT_FROM_GIF_COMMAND} from '../../plugins/KoenigSelectorPlugin.jsx'; -import {getGifProviderConfig, useGif} from '../../utils/services/gif.js'; +import {DELETE_CARD_COMMAND} from '../../plugins/KoenigBehaviourPlugin'; +import {INSERT_FROM_GIF_COMMAND} from '../../plugins/KoenigSelectorPlugin'; +import {getGifProviderConfig, useGif} from '../../utils/services/gif'; import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; -const GifPlugin = ({nodeKey}) => { - const {cardConfig} = React.useContext(KoenigComposerContext); - const providerConfig = getGifProviderConfig(cardConfig); +interface GifPluginProps { + nodeKey: string; +} + +interface GifSelectorPluginProps extends GifPluginProps { + providerConfig: NonNullable>; +} + +const GifSelectorPlugin = ({nodeKey, providerConfig}: GifSelectorPluginProps) => { const gifHook = useGif({config: providerConfig}); const [editor] = useLexicalComposerContext(); React.useEffect(() => { - const handleKeyDown = (e) => { + const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { editor.dispatchCommand(DELETE_CARD_COMMAND, {cardKey: nodeKey}); } @@ -33,7 +39,7 @@ const GifPlugin = ({nodeKey}) => { editor.dispatchCommand(DELETE_CARD_COMMAND, {cardKey: nodeKey}); }; - const insertImageToNode = async (image) => { + const insertImageToNode = async (image: unknown) => { editor.dispatchCommand(INSERT_FROM_GIF_COMMAND, image); }; @@ -41,10 +47,21 @@ const GifPlugin = ({nodeKey}) => { } /> ); }; +const GifPlugin = ({nodeKey}: GifPluginProps) => { + const {cardConfig} = React.useContext(KoenigComposerContext); + const providerConfig = getGifProviderConfig(cardConfig); + + if (!providerConfig) { + return null; + } + + return ; +}; + export default GifPlugin; diff --git a/packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx b/packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx index d122d4a61b..86856ffc4b 100644 --- a/packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/GifSelector.stories.tsx @@ -1,8 +1,9 @@ import GifSelector from './GifSelector'; -import {getGifProviderConfig, useGif} from '../../utils/services/gif.js'; +import {getGifProviderConfig, useGif} from '../../utils/services/gif'; import {tenorConfig} from '../../../demo/utils/gifConfig'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'File Selectors/Gif', component: GifSelector, parameters: { @@ -13,8 +14,8 @@ const story = { }; export default story; -const Template = (args) => { - const gifHook = useGif({config: getGifProviderConfig({tenor: tenorConfig})}); +const Template: StoryFn = (args) => { + const gifHook = useGif({config: getGifProviderConfig({tenor: tenorConfig})!}); return ( @@ -22,20 +23,16 @@ const Template = (args) => { }; export const Base = Template.bind({}); -Base.args = { - config: tenorConfig -}; +Base.args = {}; export const Loading = Template.bind({}); Loading.args = { - config: tenorConfig, isLoading: true, isLazyLoading: false }; export const LazyLoading = Template.bind({}); LazyLoading.args = { - config: tenorConfig, isLoading: true, isLazyLoading: true, loadNextPage: () => {} @@ -43,18 +40,15 @@ LazyLoading.args = { export const ErrorCommon = Template.bind({}); ErrorCommon.args = { - config: tenorConfig, error: 'common' }; export const ErrorInvalidKey = Template.bind({}); ErrorInvalidKey.args = { - config: tenorConfig, error: 'invalid_key' }; export const ErrorSpecific = Template.bind({}); ErrorSpecific.args = { - config: tenorConfig, error: 'Something went wrong' }; diff --git a/packages/koenig-lexical/src/components/ui/GifSelector.tsx b/packages/koenig-lexical/src/components/ui/GifSelector.tsx index ca24c08d11..21ff8c54c0 100644 --- a/packages/koenig-lexical/src/components/ui/GifSelector.tsx +++ b/packages/koenig-lexical/src/components/ui/GifSelector.tsx @@ -1,17 +1,51 @@ -import React, {useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; import SearchIcon from '../../assets/icons/kg-search.svg?react'; import {Error} from './file-selectors/Gif/Error'; -import {Gif} from './file-selectors/Gif/Gif'; +import {Gif, type GifData, type GifMediaFormat} from './file-selectors/Gif/Gif'; import {Loader} from './file-selectors/Gif/Loader'; // number of columns based on selector container width const TWO_COLUMN_WIDTH = 540; const THREE_COLUMN_WIDTH = 940; -const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoading, isLazyLoading, error, changeColumnCount, loadNextPage, gifs, provider}) => { - const selectorRef = useRef(null); - const searchRef = useRef(null); - const [highlightedGif, setHighlightedGif] = useState(undefined); +interface GifItem extends GifData { + columnIndex: number; + columnRowIndex: number; + media_formats: {gif: GifMediaFormat; tinygif: GifMediaFormat; [key: string]: GifMediaFormat}; +} + +export interface GifSelectorProps { + onGifInsert: (data: {src: string; width: number; height: number}) => void; + onClickOutside: () => void; + updateSearch: (term?: string) => void; + columns: GifItem[][]; + isLoading?: boolean; + isLazyLoading?: boolean; + error?: unknown; + changeColumnCount: (count: number) => void; + loadNextPage: () => void; + gifs: GifItem[]; + provider?: string; +} + +const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoading, isLazyLoading, error, changeColumnCount, loadNextPage, gifs, provider}: GifSelectorProps) => { + const selectorRef = useRef(null); + const searchRef = useRef(null); + const columnKeys = useRef(new WeakMap()); + const nextColumnKey = useRef(0); + const [highlightedGif, setHighlightedGif] = useState(undefined); + + const getColumnKey = useCallback((column: GifItem[]) => { + const existingKey = columnKeys.current.get(column); + if (existingKey) { + return existingKey; + } + + const key = `gif-column-${nextColumnKey.current}`; + nextColumnKey.current += 1; + columnKeys.current.set(column, key); + return key; + }, []); useEffect(() => { updateSearch(); @@ -51,17 +85,9 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - document.addEventListener('keydown', handleGifHighlight); - - return () => { - document.removeEventListener('keydown', handleGifHighlight); - }; - }, [handleGifHighlight]); - React.useEffect(() => { - const handleClickOutside = (event) => { - if (selectorRef.current && !selectorRef.current.contains(event.target)) { + const handleClickOutside = (event: MouseEvent) => { + if (selectorRef.current && !selectorRef.current.contains(event.target as Node)) { onClickOutside(); } }; @@ -71,7 +97,7 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad }; }, [onClickOutside]); - function handleGifSelect(selectedGif) { + const handleGifSelect = useCallback((selectedGif: GifItem) => { const gif = selectedGif.media_formats.gif; const data = { src: gif.url, @@ -79,55 +105,55 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad height: gif.dims[1] }; onGifInsert(data); - } + }, [onGifInsert]); - const handleSearch = (e) => { + const handleSearch = (e: React.ChangeEvent) => { updateSearch(e.target.value); }; - const handleScroll = (e) => { - const container = e.target; + const handleScroll = (e: React.UIEvent) => { + const container = e.target as HTMLDivElement; if (container.scrollTop + container.clientHeight >= container.scrollHeight - 1000) { loadNextPage(); } }; - function focusSearch() { + const focusSearch = useCallback(() => { searchRef.current?.focus(); - } + }, []); - function highlightFirst() { + const highlightFirst = useCallback(() => { setHighlightedGif(gifs[0]); - } + }, [gifs]); - function highlightNext() { + const highlightNext = useCallback(() => { if (highlightedGif === gifs[gifs.length - 1]) { // reached the end, do nothing return; } - setHighlightedGif(gifs[highlightedGif.index + 1]); - } + setHighlightedGif(gifs[highlightedGif!.index + 1]); + }, [gifs, highlightedGif]); - function highlightPrev() { - if (highlightedGif.index === 0) { + const highlightPrev = useCallback(() => { + if (highlightedGif!.index === 0) { // reached the beginning, focus the search bar focusSearch(); } - setHighlightedGif(gifs[highlightedGif.index - 1]); - } + setHighlightedGif(gifs[highlightedGif!.index - 1]); + }, [focusSearch, gifs, highlightedGif]); - function moveHighlightDown() { - const nextGif = columns[highlightedGif.columnIndex][highlightedGif.columnRowIndex + 1]; + const moveHighlightDown = useCallback(() => { + const nextGif = columns[highlightedGif!.columnIndex][highlightedGif!.columnRowIndex + 1]; if (nextGif) { setHighlightedGif(nextGif); } - } + }, [columns, highlightedGif]); - function moveHighlightUp() { - const nextGif = columns[highlightedGif.columnIndex][highlightedGif.columnRowIndex - 1]; + const moveHighlightUp = useCallback(() => { + const nextGif = columns[highlightedGif!.columnIndex][highlightedGif!.columnRowIndex - 1]; if (nextGif) { setHighlightedGif(nextGif); @@ -135,10 +161,13 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad // already at top, focus the search bar focusSearch(); } - } + }, [columns, focusSearch, highlightedGif]); - function moveToNextHorizontalGif(direction) { - const highlightedElem = document.querySelector(`[data-gif-index="${highlightedGif.index}"]`); + const moveToNextHorizontalGif = useCallback((direction: 'left' | 'right') => { + const highlightedElem = document.querySelector(`[data-gif-index="${highlightedGif!.index}"]`); + if (!highlightedElem) { + return; + } const highlightedElemRect = highlightedElem.getBoundingClientRect(); let x; @@ -155,9 +184,9 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad // we might hit spacing between gifs, keep moving up 5 px until we get a match while (!foundGifElem) { - let possibleMatch = document.elementFromPoint(x, y)?.closest('[data-gif-index]'); + const possibleMatch = document.elementFromPoint(x, y)?.closest('[data-gif-index]') as HTMLElement | null; - if (possibleMatch?.dataset.gifIndex !== undefined) { + if (possibleMatch?.dataset?.gifIndex !== undefined) { foundGifElem = possibleMatch; break; } @@ -172,65 +201,48 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad } if (foundGifElem) { - setHighlightedGif(gifs[foundGifElem.dataset.gifIndex]); + setHighlightedGif(gifs[Number(foundGifElem.dataset.gifIndex)]); } - } + }, [gifs, highlightedGif]); - function moveHighlightRight() { - if (highlightedGif.columnIndex === columns.length - 1) { + const moveHighlightRight = useCallback(() => { + if (highlightedGif!.columnIndex === columns.length - 1) { // we don't wrap and we're on the last column, do nothing return; } moveToNextHorizontalGif('right'); - } + }, [columns.length, highlightedGif, moveToNextHorizontalGif]); - function moveHighlightLeft() { - if (highlightedGif.index === 0) { + const moveHighlightLeft = useCallback(() => { + if (highlightedGif!.index === 0) { // on the first Gif, focus the search bar return focusSearch(); } - if (highlightedGif.columnIndex === 0) { + if (highlightedGif!.columnIndex === 0) { // we don't wrap and we're on the first column, do nothing return; } moveToNextHorizontalGif('left'); - } + }, [focusSearch, highlightedGif, moveToNextHorizontalGif]); - function handleGifHighlight(event) { - switch (event.key) { - case 'Tab': - return handleTab(event); - case 'ArrowLeft': - return handleLeft(event); - case 'ArrowRight': - return handleRight(event); - case 'ArrowUp': - return handleUp(event); - case 'ArrowDown': - return handleDown(event); - case 'Enter': - return handleEnter(event); - default: - return null; - } - } - - function handleTab(event) { + const handleTab = useCallback((event: KeyboardEvent) => { // event.stopPropagation(); // event.preventDefault(); + const target = event.target as HTMLElement | null; + if (event.shiftKey) { if (highlightedGif) { event.preventDefault(); return highlightPrev(); } } else { - if (event?.target.tagName === 'INPUT') { + if (target?.tagName === 'INPUT') { event.preventDefault(); - event.target.blur(); + (target as HTMLInputElement).blur(); return highlightFirst(); } @@ -239,33 +251,34 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad return highlightNext(); } } - } + }, [highlightedGif, highlightFirst, highlightNext, highlightPrev]); - function handleLeft(event) { + const handleLeft = useCallback((event: KeyboardEvent) => { if (highlightedGif) { event.preventDefault(); moveHighlightLeft(); } - } + }, [highlightedGif, moveHighlightLeft]); - function handleRight(event) { + const handleRight = useCallback((event: KeyboardEvent) => { if (highlightedGif) { event.preventDefault(); moveHighlightRight(); } - } + }, [highlightedGif, moveHighlightRight]); - function handleUp(event) { + const handleUp = useCallback((event: KeyboardEvent) => { if (highlightedGif) { event.preventDefault(); moveHighlightUp(); } - } + }, [highlightedGif, moveHighlightUp]); - function handleDown(event) { - if (event.target.tagName === 'INPUT') { + const handleDown = useCallback((event: KeyboardEvent) => { + const target = event.target as HTMLElement | null; + if (target?.tagName === 'INPUT') { event.preventDefault(); - event.target.blur(); + (target as HTMLInputElement).blur(); return highlightFirst(); } @@ -273,20 +286,48 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad event.preventDefault(); moveHighlightDown(); } - } + }, [highlightedGif, highlightFirst, moveHighlightDown]); - function handleEnter(event) { + const handleEnter = useCallback((event: KeyboardEvent) => { event.preventDefault(); - if (event.target.tagName === 'INPUT') { - event.target.blur(); + const target = event.target as HTMLElement | null; + if (target?.tagName === 'INPUT') { + (target as HTMLInputElement).blur(); return highlightFirst(); } if (highlightedGif) { return handleGifSelect(highlightedGif); } - } + }, [handleGifSelect, highlightedGif, highlightFirst]); + + const handleGifHighlight = useCallback((event: KeyboardEvent) => { + switch (event.key) { + case 'Tab': + return handleTab(event); + case 'ArrowLeft': + return handleLeft(event); + case 'ArrowRight': + return handleRight(event); + case 'ArrowUp': + return handleUp(event); + case 'ArrowDown': + return handleDown(event); + case 'Enter': + return handleEnter(event); + default: + return null; + } + }, [handleDown, handleEnter, handleLeft, handleRight, handleTab, handleUp]); + + useEffect(() => { + document.addEventListener('keydown', handleGifHighlight); + + return () => { + document.removeEventListener('keydown', handleGifHighlight); + }; + }, [handleGifHighlight]); const isSearchInProgress = isLoading && !isLazyLoading; @@ -316,9 +357,8 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad { !error && !isSearchInProgress && (
    - {columns.map((column, i) => ( - // eslint-disable-next-line react/no-array-index-key -
    + {columns.map(column => ( +
    {column.map(gif => ( ))} @@ -330,7 +370,7 @@ const GifSelector = ({onGifInsert, onClickOutside, updateSearch, columns, isLoad {!!isLoading && !error && } - {!!error &&
    } + {!!error &&
    }
    diff --git a/packages/koenig-lexical/src/components/ui/HighlightedString.tsx b/packages/koenig-lexical/src/components/ui/HighlightedString.tsx index cb33dd558a..4ac6b7b9b1 100644 --- a/packages/koenig-lexical/src/components/ui/HighlightedString.tsx +++ b/packages/koenig-lexical/src/components/ui/HighlightedString.tsx @@ -1,18 +1,29 @@ import escapeRegExp from 'lodash/escapeRegExp'; -export function HighlightedString({string, highlightString, shouldHighlight = true}) { +interface HighlightedStringProps { + string: string; + highlightString?: string; + shouldHighlight?: boolean; +} + +export function HighlightedString({string, highlightString, shouldHighlight = true}: HighlightedStringProps) { if (!highlightString || shouldHighlight === false) { return string; } const parts = string.split(new RegExp(`(${escapeRegExp(highlightString)})`, 'gi')); + // track each part's starting character offset to use as a stable, unique key + let offset = 0; + return ( <> - {parts.map((part, index) => { + {parts.map((part) => { + const partOffset = offset; + offset += part.length; + if (part.toLowerCase() === highlightString.toLowerCase()) { - // eslint-disable-next-line react/no-array-index-key - return {part}; + return {part}; } return part; diff --git a/packages/koenig-lexical/src/components/ui/IconButton.stories.tsx b/packages/koenig-lexical/src/components/ui/IconButton.stories.tsx index d1a3f877d1..c04dddac45 100644 --- a/packages/koenig-lexical/src/components/ui/IconButton.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/IconButton.stories.tsx @@ -1,7 +1,8 @@ import DeleteIcon from '../../assets/icons/kg-trash.svg?react'; import {IconButton} from './IconButton'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Generic/Icon button', component: IconButton, parameters: { @@ -12,7 +13,7 @@ const story = { }; export default story; -const Template = (args) => { +const Template: StoryFn = (args) => { return ( ); diff --git a/packages/koenig-lexical/src/components/ui/IconButton.tsx b/packages/koenig-lexical/src/components/ui/IconButton.tsx index b891bc6651..1c38c519a2 100644 --- a/packages/koenig-lexical/src/components/ui/IconButton.tsx +++ b/packages/koenig-lexical/src/components/ui/IconButton.tsx @@ -1,7 +1,15 @@ import clsx from 'clsx'; import {Tooltip} from './Tooltip'; -export function IconButton({className, onClick, label, dataTestId, Icon}) { +export interface IconButtonProps { + className?: string; + onClick?: (e: React.MouseEvent) => void; + label?: string; + dataTestId?: string; + Icon: React.ComponentType>; +} + +export function IconButton({className, onClick, label, dataTestId, Icon}: IconButtonProps) { return ( @@ -85,7 +90,3 @@ export function LinkInput({href, update, cancel}) {
    ); } - -LinkInput.propTypes = { - href: PropTypes.string -}; diff --git a/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx b/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx index d8157223f5..23009fe068 100644 --- a/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx +++ b/packages/koenig-lexical/src/components/ui/LinkInputSearchItem.tsx @@ -1,7 +1,27 @@ import {HighlightedString} from './HighlightedString'; import {InputListItem} from './InputList'; -export function LinkInputSearchItem({dataTestId, item, highlightString, selected, onMouseOver, scrollIntoView, onClick}) { +interface LinkInputSearchItemProps { + dataTestId?: string; + item: { + value?: string | null; + type?: string; + Icon?: React.ComponentType>; + label: string; + highlight?: boolean; + metaText?: string; + MetaIcon?: React.ComponentType>; + metaIconTitle?: string; + [key: string]: unknown; + }; + highlightString?: string; + selected?: boolean; + onMouseOver?: () => void; + scrollIntoView?: boolean; + onClick?: (item: {value?: string | null; type?: string}) => void; +} + +export function LinkInputSearchItem({dataTestId, item, highlightString, selected, onMouseOver, scrollIntoView, onClick}: LinkInputSearchItemProps) { return ( = { title: 'Toolbar/LinkInputWithSearch', component: LinkInputWithSearch, parameters: { @@ -11,7 +12,7 @@ const story = { }; export default story; -const Template = (args) => { +const Template: StoryFn = (args) => { return (
    diff --git a/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx b/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx index 6d5475b2b2..9e9c8d408c 100644 --- a/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx +++ b/packages/koenig-lexical/src/components/ui/LinkInputWithSearch.tsx @@ -1,22 +1,27 @@ import KoenigComposerContext from '../../context/KoenigComposerContext'; -import PropTypes from 'prop-types'; import React from 'react'; import trackEvent from '../../utils/analytics'; import {Input} from './Input'; import {InputListGroup, InputListLoadingItem} from './InputList'; -import {KeyboardSelectionWithGroups} from './KeyboardSelectionWithGroups'; +import {KeyboardSelectionWithGroups, type GroupData} from './KeyboardSelectionWithGroups'; import {LinkInputSearchItem} from './LinkInputSearchItem'; import {useSearchLinks} from '../../hooks/useSearchLinks'; -export function LinkInputWithSearch({href, update, cancel}) { +export interface LinkInputWithSearchProps { + href?: string; + update: (href: string, type?: string) => void; + cancel: () => void; +} + +export function LinkInputWithSearch({href, update, cancel}: LinkInputWithSearchProps) { const {cardConfig: {searchLinks}} = React.useContext(KoenigComposerContext); // store the href/query in state so we can update it without affecting the saved editor value const [_href, setHref] = React.useState(href); - const {isSearching, listOptions} = useSearchLinks(_href, searchLinks); + const {isSearching, listOptions} = useSearchLinks(_href || '', searchLinks as (term?: string) => Promise); // add refs for input and container - const containerRef = React.useRef(null); + const containerRef = React.useRef(null); const testId = 'link-input'; @@ -32,13 +37,13 @@ export function LinkInputWithSearch({href, update, cancel}) { // close link input when clicking outside or pressing escape React.useEffect(() => { - const closeOnClickOutside = (event) => { - if (containerRef.current && !containerRef.current.contains(event.target)) { + const closeOnClickOutside = (event: MouseEvent) => { + if (containerRef.current && !containerRef.current.contains(event.target as Node)) { cancel(); } }; - const onEscape = (event) => { + const onEscape = (event: KeyboardEvent) => { if (event.key === 'Escape') { cancel(); } @@ -53,11 +58,14 @@ export function LinkInputWithSearch({href, update, cancel}) { }; }, [cancel]); - const onItemSelected = (item) => { + const onItemSelected = (item: {value?: string | null; type?: string}) => { + if (!item.value) { + return; + } update(item.value, item.type); }; - const getItem = (item, selected, onMouseOver, scrollIntoView) => { + const getItem = (item: {value: string | null; label: string; [key: string]: unknown}, selected: boolean, onMouseOver: () => void, scrollIntoView: boolean) => { return ( onItemSelected(selectedItem)} onMouseOver={onMouseOver} /> ); }; - const getGroup = (group, {showSpinner} = {}) => { + const getGroup = (group: GroupData, {showSpinner}: {showSpinner?: boolean} = {}) => { return ( ); @@ -90,16 +98,16 @@ export function LinkInputWithSearch({href, update, cancel}) { placeholder="Search or enter URL to link" value={_href} data-kg-link-input - onChange={(e) => { + onChange={(e: React.ChangeEvent) => { // update local value to allow searching setHref(e.target.value); }} - onKeyDown={(e) => { + onKeyDown={(e: React.KeyboardEvent) => { if (e.key === 'Enter') { // prevent Enter from triggering in the editor and removing text // update the link value in the editor e.preventDefault(); - update(_href); + update(_href || ''); return; } }} @@ -121,7 +129,3 @@ export function LinkInputWithSearch({href, update, cancel}) {
    ); } - -LinkInputWithSearch.propTypes = { - href: PropTypes.string -}; diff --git a/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx b/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx index b6e779ac62..1111f8b72b 100644 --- a/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/LinkToolbar.stories.tsx @@ -1,6 +1,7 @@ import {LinkToolbar} from './LinkToolbar'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Toolbar/LinkToolbar', component: LinkToolbar, parameters: { @@ -11,7 +12,7 @@ const story = { }; export default story; -const Template = (args) => { +const Template: StoryFn = (args) => { return (
    diff --git a/packages/koenig-lexical/src/components/ui/LinkToolbar.tsx b/packages/koenig-lexical/src/components/ui/LinkToolbar.tsx index e3aa8c4fe0..a0f59bb959 100644 --- a/packages/koenig-lexical/src/components/ui/LinkToolbar.tsx +++ b/packages/koenig-lexical/src/components/ui/LinkToolbar.tsx @@ -1,6 +1,12 @@ import {ToolbarMenuItem} from './ToolbarMenu'; -export function LinkToolbar({href, onEdit, onRemove}) { +export interface LinkToolbarProps { + href?: string; + onEdit?: () => void; + onRemove?: () => void; +} + +export function LinkToolbar({href, onEdit, onRemove}: LinkToolbarProps) { return (
    {href} diff --git a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx index a14acc19bd..feb751f9e5 100644 --- a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.stories.tsx @@ -1,6 +1,7 @@ import {MediaPlaceholder} from './MediaPlaceholder'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Generic/Media placeholder (beta)', component: MediaPlaceholder, argTypes: { @@ -25,7 +26,7 @@ const story = { }; export default story; -const Template = args => ( +const Template: StoryFn = args => (
    diff --git a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx index f347e7a689..33425ea067 100644 --- a/packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx +++ b/packages/koenig-lexical/src/components/ui/MediaPlaceholder.tsx @@ -3,11 +3,11 @@ import FilePlaceholderIcon from '../../assets/icons/kg-file-placeholder.svg?reac import GalleryPlaceholderIcon from '../../assets/icons/kg-gallery-placeholder.svg?react'; import ImgPlaceholderIcon from '../../assets/icons/kg-img-placeholder.svg?react'; import ProductPlaceholderIcon from '../../assets/icons/kg-product-placeholder.svg?react'; -import PropTypes from 'prop-types'; +import React from 'react'; import VideoPlaceholderIcon from '../../assets/icons/kg-video-placeholder.svg?react'; import clsx from 'clsx'; -export const PLACEHOLDER_ICONS = { +export const PLACEHOLDER_ICONS: Record>> = { image: ImgPlaceholderIcon, gallery: GalleryPlaceholderIcon, video: VideoPlaceholderIcon, @@ -16,7 +16,7 @@ export const PLACEHOLDER_ICONS = { product: ProductPlaceholderIcon }; -export const CardText = ({text, type}) => ( +export const CardText = ({text, type}: {text: string; type?: string}) => ( ( ); -const ButtonContents = ({desc, hasErrors}) => { +const ButtonContents = ({desc, hasErrors}: {desc?: string; hasErrors: boolean}) => { if (hasErrors) { return null; } return

    {desc}

    ; }; -const StandardContents = ({desc, hasErrors, icon, size}) => { +const StandardContents = ({desc, hasErrors, icon, size}: {desc?: string; hasErrors: boolean; icon?: string; size?: string}) => { if (size === 'xsmall' && hasErrors) { return null; } - const Icon = PLACEHOLDER_ICONS[icon]; + const Icon = icon ? PLACEHOLDER_ICONS[icon] : null; const iconClasses = clsx( 'shrink-0 opacity-80 transition-all ease-linear hover:scale-105 group-hover:opacity-100', size === 'large' && 'size-20 text-grey', size === 'small' && 'size-14 text-grey', size === 'xsmall' && 'size-5 text-grey-700', - !['large', 'small', 'xsmall'].includes(size) && 'size-16 text-grey', + !['large', 'small', 'xsmall'].includes(size || '') && 'size-16 text-grey', (size === 'xsmall' && desc) && 'mr-3' ); @@ -58,11 +58,27 @@ const StandardContents = ({desc, hasErrors, icon, size}) => { ); return <> - + {Icon && }

    {desc}

    ; }; +export interface MediaPlaceholderProps { + desc?: string; + icon?: 'image' | 'gallery' | 'video' | 'audio' | 'file' | 'product'; + filePicker?: () => void; + size?: 'xsmall' | 'small' | 'medium' | 'large'; + type?: 'image' | 'button'; + borderStyle?: 'squared' | 'rounded'; + isDraggedOver?: boolean; + errors?: {message: string}[]; + placeholderRef?: React.Ref; + dataTestId?: string; + errorDataTestId?: string; + multiple?: boolean; + [key: string]: unknown; +} + export function MediaPlaceholder({ desc, icon, @@ -77,7 +93,7 @@ export function MediaPlaceholder({ errorDataTestId = 'media-placeholder-errors', multiple = false, ...props -}) { +}: MediaPlaceholderProps) { const containerClasses = clsx( 'relative flex h-full items-center justify-center', type === 'button' ? 'rounded-lg bg-grey-100' : 'border bg-grey-50', @@ -137,11 +153,3 @@ export function MediaPlaceholder({
    ); } - -MediaPlaceholder.propTypes = { - icon: PropTypes.oneOf(['image', 'gallery', 'video', 'audio', 'file', 'product']), - desc: PropTypes.string, - size: PropTypes.oneOf(['xsmall', 'small', 'medium', 'large']), - type: PropTypes.oneOf(['image', 'button']), - borderStyle: PropTypes.oneOf(['squared', 'rounded']) -}; diff --git a/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx b/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx index 293041424d..12dec2d346 100644 --- a/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/MediaPlayer.stories.tsx @@ -1,6 +1,7 @@ import {MediaPlayer} from './MediaPlayer'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Generic/Media player', component: MediaPlayer, parameters: { @@ -11,7 +12,7 @@ const story = { }; export default story; -const Template = args => ( +const Template: StoryFn = args => ( ); diff --git a/packages/koenig-lexical/src/components/ui/MediaPlayer.tsx b/packages/koenig-lexical/src/components/ui/MediaPlayer.tsx index d2f90890af..84e0dce3a6 100644 --- a/packages/koenig-lexical/src/components/ui/MediaPlayer.tsx +++ b/packages/koenig-lexical/src/components/ui/MediaPlayer.tsx @@ -1,8 +1,14 @@ import PlayIcon from '../../assets/icons/kg-play.svg?react'; -import PropTypes from 'prop-types'; import UnmuteIcon from '../../assets/icons/kg-unmute.svg?react'; -export function MediaPlayer({type, duration, theme, ...args}) { +export interface MediaPlayerProps { + type?: string; + duration?: string; + theme?: 'light' | 'dark'; + [key: string]: unknown; +} + +export function MediaPlayer({type: _type, duration, theme, ...args}: MediaPlayerProps) { return (
    @@ -25,7 +31,3 @@ export function MediaPlayer({type, duration, theme, ...args}) {
    ); } - -MediaPlayer.propTypes = { - theme: PropTypes.oneOf(['light', 'dark']) -}; diff --git a/packages/koenig-lexical/src/components/ui/MediaUploader.tsx b/packages/koenig-lexical/src/components/ui/MediaUploader.tsx index 6d98fd1ad1..7cbc9342f8 100644 --- a/packages/koenig-lexical/src/components/ui/MediaUploader.tsx +++ b/packages/koenig-lexical/src/components/ui/MediaUploader.tsx @@ -1,13 +1,40 @@ import DeleteIcon from '../../assets/icons/kg-trash.svg?react'; import ImageUploadForm from './ImageUploadForm'; -import PropTypes from 'prop-types'; +import React from 'react'; import WandIcon from '../../assets/icons/kg-wand.svg?react'; import clsx from 'clsx'; import {IconButton} from './IconButton'; import {MediaPlaceholder} from './MediaPlaceholder'; import {ProgressBar} from './ProgressBar'; +import {createFileInputChangeEventFromBlob} from '../../utils/createFileInputChangeEvent'; import {openFileSelection} from '../../utils/openFileSelection'; import {useRef} from 'react'; +import type {OpenImageEditor} from '../../hooks/usePinturaEditor'; + +interface MediaUploaderProps { + className?: string; + imgClassName?: string; + src?: string; + alt?: string; + desc?: string; + icon?: string; + size?: string; + type?: 'image' | 'button'; + borderStyle?: 'squared' | 'rounded'; + backgroundSize?: 'cover' | 'contain'; + mimeTypes?: string[]; + onFileChange: (e: React.ChangeEvent) => void; + dragHandler?: {isDraggedOver?: boolean; setRef?: React.Ref}; + isEditing?: boolean; + isLoading?: boolean; + isPinturaEnabled?: boolean; + openImageEditor?: OpenImageEditor; + progress?: number; + errors?: {message: string}[]; + onRemoveMedia?: () => void; + additionalActions?: React.ReactNode; + setFileInputRef?: (el: HTMLInputElement | null) => void; +} export function MediaUploader({ className, @@ -32,19 +59,19 @@ export function MediaUploader({ onRemoveMedia = () => {}, additionalActions, setFileInputRef -}) { - const fileInputRef = useRef(null); +}: MediaUploaderProps) { + const fileInputRef = useRef(null); - const onFileInputRef = (element) => { + const onFileInputRef = (element: HTMLInputElement | null) => { fileInputRef.current = element; setFileInputRef?.(element); }; const progressStyle = { - width: `${progress?.toFixed(0)}%` + width: `${(progress ?? 0).toFixed(0)}%` }; - const onRemove = (e) => { + const onRemove = (e: React.MouseEvent) => { e.stopPropagation(); // prevents card from losing selected state onRemoveMedia(); }; @@ -61,15 +88,14 @@ export function MediaUploader({ errorDataTestId="media-upload-errors" errors={errors} filePicker={() => openFileSelection({fileInputRef})} - icon={icon} + icon={icon as 'image' | 'gallery' | 'video' | 'audio' | 'file' | 'product'} isDraggedOver={dragHandler?.isDraggedOver} placeholderRef={dragHandler?.setRef} - size={size} + size={size as 'xsmall' | 'small' | 'medium' | 'large'} type={type} /> openFileSelection({fileInputRef})} mimeTypes={mimeTypes} onFileChange={onFileChange} /> @@ -79,9 +105,9 @@ export function MediaUploader({ return (
    {src && ( @@ -94,14 +120,10 @@ export function MediaUploader({ {!isLoading && (
    {additionalActions} - { isPinturaEnabled && openImageEditor({ - image: src, - handleSave: (editedImage) => { - onFileChange({ - target: { - files: [editedImage] - } - }); + { isPinturaEnabled && openImageEditor?.({ + image: src || '', + handleSave: (editedImage: Blob) => { + onFileChange(createFileInputChangeEventFromBlob(editedImage)); } })} /> } @@ -119,28 +141,3 @@ export function MediaUploader({
    ); } - -MediaUploader.propTypes = { - additionalActions: PropTypes.node, - alt: PropTypes.string, - backgroundSize: PropTypes.oneOf(['cover', 'contain']), - borderStyle: PropTypes.oneOf(['squared', 'rounded']), - className: PropTypes.string, - desc: PropTypes.string, - dragHandler: PropTypes.shape({isDraggedOver: PropTypes.bool, setRef: PropTypes.func}), - errors: PropTypes.arrayOf(PropTypes.shape({message: PropTypes.string})), - icon: PropTypes.string, - imgClassName: PropTypes.string, - isEditing: PropTypes.bool, - isLoading: PropTypes.bool, - isPinturaEnabled: PropTypes.bool, - mimeTypes: PropTypes.arrayOf(PropTypes.string), - onFileChange: PropTypes.func, - onRemoveMedia: PropTypes.func, - openImageEditor: PropTypes.func, - progress: PropTypes.number, - setFileInputRef: PropTypes.func, - size: PropTypes.string, - src: PropTypes.string, - type: PropTypes.oneOf(['image', 'button']) -}; diff --git a/packages/koenig-lexical/src/components/ui/Modal.stories.tsx b/packages/koenig-lexical/src/components/ui/Modal.stories.tsx index 12ca012997..164dcd665e 100644 --- a/packages/koenig-lexical/src/components/ui/Modal.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/Modal.stories.tsx @@ -1,7 +1,8 @@ import {Modal} from './Modal'; import {useState} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; -const story = { +const story: Meta = { title: 'Generic/Modal', component: Modal, parameters: { @@ -12,7 +13,7 @@ const story = { }; export default story; -const Template = (args) => { +const Template: StoryFn = (_args) => { const [isOpen, setOpen] = useState(false); const openModal = () => setOpen(true); diff --git a/packages/koenig-lexical/src/components/ui/Modal.tsx b/packages/koenig-lexical/src/components/ui/Modal.tsx index b131f6b373..049efff58a 100644 --- a/packages/koenig-lexical/src/components/ui/Modal.tsx +++ b/packages/koenig-lexical/src/components/ui/Modal.tsx @@ -1,9 +1,15 @@ import CloseIcon from '../../assets/icons/kg-close.svg?react'; import Portal from './Portal'; -import PropTypes from 'prop-types'; +import React from 'react'; -export function Modal({isOpen, onClose, children}) { - const controlByKeys = (event) => { +export interface ModalProps { + isOpen?: boolean; + onClose: () => void; + children?: React.ReactNode; +} + +export function Modal({isOpen, onClose, children}: ModalProps) { + const controlByKeys = (event: React.KeyboardEvent) => { event.stopPropagation(); event.preventDefault(); @@ -35,9 +41,3 @@ export function Modal({isOpen, onClose, children}) { ); } - -Modal.propTypes = { - isOpen: PropTypes.bool, - onClose: PropTypes.func, - children: PropTypes.node -}; diff --git a/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx b/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx index ab5ea1524a..baab3685db 100644 --- a/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx +++ b/packages/koenig-lexical/src/components/ui/MultiSelectDropdown.tsx @@ -4,7 +4,12 @@ import React from 'react'; import {DropdownContainer} from './DropdownContainer'; import {KeyboardSelection} from './KeyboardSelection'; -function Item({item, selected, onChange}) { +interface DropdownItem { + name: string; + label: React.ReactNode; +} + +function Item({item, selected, onChange}: {item: DropdownItem; selected: boolean; onChange: (item: DropdownItem) => void}) { let selectionClass = ''; if (selected) { @@ -13,7 +18,7 @@ function Item({item, selected, onChange}) { // We use the capture phase of the mouse down event, otherwise the list option will be removed when blurring the input // before calling the click event - const handleOptionMouseDown = (event) => { + const handleOptionMouseDown = (event: React.MouseEvent) => { // Prevent losing focus when clicking an option event.preventDefault(); onChange(item); @@ -33,18 +38,27 @@ function Item({item, selected, onChange}) { ); } -export function MultiSelectDropdown({placeholder = '', items = [], availableItems = [], onChange, dataTestId, allowAdd = true}) { +interface MultiSelectDropdownProps { + placeholder?: string; + items?: string[]; + availableItems?: string[]; + onChange: (items: string[]) => void; + dataTestId?: string; + allowAdd?: boolean; +} + +export function MultiSelectDropdown({placeholder = '', items = [], availableItems = [], onChange, dataTestId, allowAdd = true}: MultiSelectDropdownProps) { const [open, setOpen] = React.useState(false); const [filter, setFilter] = React.useState(''); const [isFocused, setIsFocused] = React.useState(false); - const inputRef = React.useRef(null); + const inputRef = React.useRef(null); - const handleOpen = (event) => { + const handleOpen = (event?: React.MouseEvent) => { setOpen(!open); // For Safari, we need to manually focus the button (doesn't happen by default) - if (!open) { - event.target.focus(); + if (!open && event) { + (event.target as HTMLElement).focus(); } }; @@ -59,7 +73,7 @@ export function MultiSelectDropdown({placeholder = '', items = [], availableItem handleOpen(); }; - const handleSelect = (item) => { + const handleSelect = (item: DropdownItem) => { if (!item.name || items?.includes(item.name)) { return; } @@ -68,7 +82,7 @@ export function MultiSelectDropdown({placeholder = '', items = [], availableItem setFilter(''); }; - const handleDeselect = (event, selectedItem) => { + const handleDeselect = (event: React.MouseEvent, selectedItem: DropdownItem) => { // Prevent losing focus when clicking an option event.preventDefault(); event.stopPropagation(); @@ -76,25 +90,25 @@ export function MultiSelectDropdown({placeholder = '', items = [], availableItem onChange(items.filter(selection => selection !== selectedItem.name)); }; - const handleBackspace = (event) => { + const handleBackspace = (event: React.KeyboardEvent) => { if (event.key === 'Backspace' && !filter) { onChange(items.slice(0, -1)); } }; - const getItem = (item, selected) => { + const getItem = (item: DropdownItem, selected: boolean) => { return ( ); }; const selectedItems = items.map(item => ({name: item, label: item})); - const nonSelectedItems = availableItems.map(item => ({name: item, label: item})).filter( + const nonSelectedItems = availableItems.map(item => ({name: item, label: item as React.ReactNode})).filter( ai => !selectedItems.some(ii => ii.name === ai.name) ); - const filteredItems = nonSelectedItems.filter(item => item.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase())); - let prefixItem = ''; + const filteredItems: DropdownItem[] = nonSelectedItems.filter(item => item.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase())); + const prefixItem = ''; const defaultSelected = filteredItems[0]; if (filter && allowAdd) { @@ -109,8 +123,7 @@ export function MultiSelectDropdown({placeholder = '', items = [], availableItem
    inputRef.current.focus()} + onClick={() => inputRef.current?.focus()} > {selectedItems.map(item => ( - +
    - +
    ); } } +interface PopulatedAudioCardProps { + isEditing?: boolean; + title?: string; + placeholder?: string; + thumbnailUploader: FileUploader; + thumbnailMimeTypes?: string[]; + duration?: number; + updateTitle?: (value: string) => void; + thumbnailSrc?: string; + setFileInputRef: (ref: React.RefObject) => void; + onFileChange?: (e: React.ChangeEvent) => void; + removeThumbnail?: () => void; + thumbnailDragHandler?: DragHandler; +} + function PopulatedAudioCard({ isEditing, title, @@ -163,9 +209,9 @@ function PopulatedAudioCard({ onFileChange, removeThumbnail, thumbnailDragHandler = {} -}) { +}: PopulatedAudioCardProps) { const {isLoading: isUploading, progress, errors} = thumbnailUploader; - const formatDuration = (rawDuration) => { + const formatDuration = (rawDuration: number) => { const minutes = Math.floor(rawDuration / 60); const seconds = Math.floor(rawDuration - (minutes * 60)); const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`; @@ -173,14 +219,14 @@ function PopulatedAudioCard({ return formattedDuration; }; - const handleChange = (event) => { - updateTitle(event.target.value); + const handleChange = (event: React.ChangeEvent) => { + updateTitle?.(event.target.value); }; return ( <>
    } className="flex rounded-md border border-grey/30 p-2" data-testid="audio-card-populated" > @@ -208,7 +254,7 @@ function PopulatedAudioCard({ onChange={handleChange} /> )} - +
    {!isEditing && } @@ -216,6 +262,26 @@ function PopulatedAudioCard({ ); } +interface AudioCardProps { + src?: string; + thumbnailSrc?: string; + title?: string; + isEditing?: boolean; + updateTitle?: (value: string) => void; + duration?: number; + audioUploader: FileUploader; + audioMimeTypes?: string[]; + thumbnailUploader: FileUploader; + thumbnailMimeTypes?: string[]; + audioFileInputRef?: React.MutableRefObject; + thumbnailFileInputRef?: React.MutableRefObject; + onAudioFileChange?: (e: React.ChangeEvent) => void; + onThumbnailFileChange?: (e: React.ChangeEvent) => void; + audioDragHandler?: DragHandler; + removeThumbnail?: () => void; + thumbnailDragHandler?: DragHandler; +} + export function AudioCard({ src, thumbnailSrc, @@ -234,14 +300,14 @@ export function AudioCard({ audioDragHandler, removeThumbnail, thumbnailDragHandler -}) { - const setAudioFileInputRef = (ref) => { +}: AudioCardProps) { + const setAudioFileInputRef = (ref: React.RefObject) => { if (audioFileInputRef) { audioFileInputRef.current = ref.current; } }; - const setThumbnailFileInputRef = (ref) => { + const setThumbnailFileInputRef = (ref: React.RefObject) => { if (thumbnailFileInputRef) { thumbnailFileInputRef.current = ref.current; } @@ -256,7 +322,6 @@ export function AudioCard({ placeholder='Add a title...' removeThumbnail={removeThumbnail} setFileInputRef={setThumbnailFileInputRef} - setTitle={updateTitle} thumbnailDragHandler={thumbnailDragHandler} thumbnailMimeTypes={thumbnailMimeTypes} thumbnailSrc={thumbnailSrc} @@ -281,64 +346,3 @@ export function AudioCard({ ); } } - -AudioCard.propTypes = { - src: PropTypes.string, - title: PropTypes.string, - isEditing: PropTypes.bool, - updateTitle: PropTypes.func, - duration: PropTypes.number, - thumbnailSrc: PropTypes.string, - audioUploader: PropTypes.object, - audioMimeTypes: PropTypes.array, - thumbnailUploader: PropTypes.object, - thumbnailMimeTypes: PropTypes.array, - audioFileInputRef: PropTypes.object, - thumbnailFileInputRef: PropTypes.object, - onAudioFileChange: PropTypes.func, - onThumbnailFileChange: PropTypes.func, - audioDragHandler: PropTypes.object, - removeThumbnail: PropTypes.func, - thumbnailDragHandler: PropTypes.object -}; - -AudioUploading.propTypes = { - progress: PropTypes.number -}; - -AudioThumbnail.propTypes = { - errors: PropTypes.array, - isDraggedOver: PropTypes.bool, - isEditing: PropTypes.bool, - isUploading: PropTypes.bool, - mimeTypes: PropTypes.array, - progress: PropTypes.number, - removeThumbnail: PropTypes.func, - setFileInputRef: PropTypes.func, - src: PropTypes.string, - onFileChange: PropTypes.func -}; - -PopulatedAudioCard.propTypes = { - duration: PropTypes.number, - errors: PropTypes.array, - isEditing: PropTypes.bool, - placeholder: PropTypes.string, - removeThumbnail: PropTypes.func, - setFileInputRef: PropTypes.func, - thumbnailDragHandler: PropTypes.object, - thumbnailMimeTypes: PropTypes.array, - thumbnailSrc: PropTypes.string, - thumbnailUploader: PropTypes.object, - title: PropTypes.string, - updateTitle: PropTypes.func, - onFileChange: PropTypes.func -}; - -EmptyAudioCard.propTypes = { - audioDragHandler: PropTypes.object, - audioMimeTypes: PropTypes.array, - audioUploader: PropTypes.object, - setFileInputRef: PropTypes.func, - onFileChange: PropTypes.func -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx index d7563f46b7..aba5f6013d 100644 --- a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.stories.tsx @@ -1,22 +1,25 @@ import populateEditor from '../../../utils/storybook/populate-storybook-editor'; import {BookmarkCard} from './BookmarkCard'; import {CardWrapper} from './../CardWrapper'; -import {MINIMAL_NODES} from '../../../index.js'; +import {MINIMAL_NODES} from '../../../index'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, Selected: {isSelected: true, isEditing: false} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; caption?: string}; + +const story: Meta = { title: 'Primary cards/Bookmark card', component: BookmarkCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -35,20 +38,20 @@ const story = { }; export default story; -const Template = ({display, caption, ...args}) => { +const Template: StoryFn = ({display, caption, ...args}) => { const captionEditor = createEditor({nodes: MINIMAL_NODES}); populateEditor({editor: captionEditor, initialHtml: `${caption}`}); return (
    - - + +
    - - + +
    diff --git a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx index 6cbd765df8..96cef80417 100644 --- a/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/BookmarkCard.tsx @@ -1,8 +1,31 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {CardCaptionEditor} from '../CardCaptionEditor'; import {UrlInput} from '../UrlInput'; import {UrlSearchInput} from '../UrlSearchInput'; +import type {LexicalEditor} from 'lexical'; + +interface BookmarkCardProps { + author?: string; + handleClose?: () => void; + handlePasteAsLink?: (value?: string) => void; + handleRetry?: () => void; + handleUrlChange?: ((e: React.ChangeEvent) => void) | ((value: string) => void); + handleUrlSubmit?: ((e: KeyboardEvent | React.KeyboardEvent) => void) | ((url: string, type?: string) => void); + url?: string; + urlInputValue?: string; + urlPlaceholder?: string; + thumbnail?: string; + title?: string; + description?: string; + icon?: string; + publisher?: string; + captionEditor?: LexicalEditor; + captionEditorInitialState?: string; + isSelected?: boolean; + isLoading?: boolean; + urlError?: boolean; + searchLinks?: (term?: string) => Promise; +} export function BookmarkCard({ author, @@ -25,7 +48,7 @@ export function BookmarkCard({ isLoading, urlError, searchLinks -}) { +}: BookmarkCardProps) { // State to manage thumbnail visibility const [thumbnailVisible, setThumbnailVisible] = React.useState(true); @@ -53,13 +76,15 @@ export function BookmarkCard({ }
    - + {captionEditor && ( + + )}
  • ); } @@ -71,8 +96,8 @@ export function BookmarkCard({ handleClose={handleClose} handlePasteAsLink={handlePasteAsLink} handleRetry={handleRetry} - handleUrlChange={handleUrlChange} - handleUrlSubmit={handleUrlSubmit} + handleUrlChange={handleUrlChange as (value: string) => void} + handleUrlSubmit={handleUrlSubmit as (url: string, type?: string) => void} hasError={urlError} isLoading={isLoading} placeholder={urlPlaceholder} @@ -87,8 +112,8 @@ export function BookmarkCard({ handleClose={handleClose} handlePasteAsLink={handlePasteAsLink} handleRetry={handleRetry} - handleUrlChange={handleUrlChange} - handleUrlSubmit={handleUrlSubmit} + handleUrlChange={handleUrlChange as (e: React.ChangeEvent) => void} + handleUrlSubmit={handleUrlSubmit as (e: KeyboardEvent | React.KeyboardEvent) => void} hasError={urlError} isLoading={isLoading} placeholder={urlPlaceholder} @@ -98,35 +123,12 @@ export function BookmarkCard({ } } -export function BookmarkIcon({src}) { +interface BookmarkIconProps { + src: string; +} + +export function BookmarkIcon({src}: BookmarkIconProps) { return ( ); } - -BookmarkCard.propTypes = { - author: PropTypes.string, - handleClose: PropTypes.func, - handlePasteAsLink: PropTypes.func, - handleRetry: PropTypes.func, - handleUrlChange: PropTypes.func, - handleUrlSubmit: PropTypes.func, - url: PropTypes.string, - urlInputValue: PropTypes.string, - urlPlaceholder: PropTypes.string, - thumbnail: PropTypes.string, - title: PropTypes.string, - description: PropTypes.string, - icon: PropTypes.string, - publisher: PropTypes.string, - captionEditor: PropTypes.object, - captionEditorInitialState: PropTypes.object, - isSelected: PropTypes.bool, - isLoading: PropTypes.bool, - urlError: PropTypes.bool, - searchLinks: PropTypes.func -}; - -BookmarkIcon.propTypes = { - src: PropTypes.string -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx index 6844c2e3c5..777b5ef038 100644 --- a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.stories.tsx @@ -1,5 +1,7 @@ import {ButtonCard} from './ButtonCard'; import {CardWrapper} from './../CardWrapper'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -7,14 +9,15 @@ const displayOptions = { Editing: {isSelected: true, isEditing: true} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions}; + +const story: Meta = { title: 'Primary cards/Button card', component: ButtonCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -38,11 +41,11 @@ const story = { }; export default story; -const Template = ({display, ...args}) => ( +const Template: StoryFn = ({display, ...args}) => (
    - - + +
    diff --git a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx index 1c85754136..063fdaaeb1 100644 --- a/packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/ButtonCard.tsx @@ -1,10 +1,21 @@ import CenterAlignIcon from '../../../assets/icons/kg-align-center.svg?react'; import LeftAlignIcon from '../../../assets/icons/kg-align-left.svg?react'; -import PropTypes from 'prop-types'; +import React from 'react'; import {Button} from '../Button'; import {ButtonGroupSetting, InputSetting, InputUrlSetting, SettingsPanel} from '../SettingsPanel'; import {ReadOnlyOverlay} from '../ReadOnlyOverlay'; +interface ButtonCardProps { + alignment?: string; + buttonText?: string; + buttonPlaceholder?: string; + buttonUrl?: string; + handleAlignmentChange: (name: string) => void; + handleButtonTextChange?: (e: React.ChangeEvent) => void; + handleButtonUrlChange: (value: string) => void; + isEditing?: boolean; +} + export function ButtonCard({ alignment, buttonText, @@ -14,7 +25,7 @@ export function ButtonCard({ handleButtonTextChange, handleButtonUrlChange, isEditing -}) { +}: ButtonCardProps) { const buttonGroupChildren = [ { label: 'Left', @@ -43,7 +54,7 @@ export function ButtonCard({ @@ -64,18 +75,3 @@ export function ButtonCard({ ); } - -ButtonCard.propTypes = { - alignment: PropTypes.string, - buttonText: PropTypes.string, - buttonPlaceholder: PropTypes.string, - buttonUrl: PropTypes.string, - handleAlignmentChange: PropTypes.func, - handleButtonTextChange: PropTypes.func, - handleButtonUrlChange: PropTypes.func, - handleButtonUrlFocus: PropTypes.func, - handleOptionClick: PropTypes.func, - isEditing: PropTypes.bool, - suggestedUrls: PropTypes.array, - suggestedUrlVisibility: PropTypes.bool -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx index 5eb02393bc..f249e06a78 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.stories.tsx @@ -1,9 +1,11 @@ import VisibilityIndicatorIcon from '../../../assets/icons/kg-indicator-visibility.svg?react'; -import populateEditor from '../../../utils/storybook/populate-storybook-editor.js'; -import {BASIC_NODES} from '../../../index.js'; +import populateEditor from '../../../utils/storybook/populate-storybook-editor'; +import {BASIC_NODES} from '../../../index'; import {CallToActionCard} from './CallToActionCard'; import {CardWrapper} from '../CardWrapper'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -16,14 +18,15 @@ const layoutOptions = { Immersive: 'immersive' }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; value?: string}; + +const story: Meta = { title: 'Primary cards/Call to Action card', component: CallToActionCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -54,18 +57,16 @@ const story = { }; export default story; -const Template = ({display, value, ...args}) => { +const Template: StoryFn = ({display, value, ...args}) => { // Main editor setup const htmlEditor = createEditor({nodes: BASIC_NODES}); populateEditor({editor: htmlEditor, initialHtml: `${value}`}); // Sponsor label editor setup - let sponsorLabelHtmlEditor = null; - let sponsorLabelHtmlEditorInitialState = null; + const sponsorLabelHtmlEditor = createEditor({nodes: BASIC_NODES}); if (args.hasSponsorLabel) { - sponsorLabelHtmlEditor = createEditor({nodes: BASIC_NODES}); - sponsorLabelHtmlEditorInitialState = populateEditor({ + populateEditor({ editor: sponsorLabelHtmlEditor, initialHtml: 'Sponsored' }); @@ -79,15 +80,14 @@ const Template = ({display, value, ...args}) => { indicatorPosition={{ top: '1.2rem' }} - {...(args.color === '' && {wrapperStyle: 'wide'})} - {...display} + {...(args.color === 'none' && {wrapperStyle: 'wide'})} + {...displayOptions[display]} {...args}>
    @@ -106,8 +106,7 @@ Empty.args = { buttonColor: '#2e398a', layout: 'immersive', buttonText: '', - buttonUrl: '', - suggestedUrls: [] + buttonUrl: '' }; export const Populated = Template.bind({}); @@ -121,7 +120,6 @@ Populated.args = { buttonColor: '#2e398a', layout: 'immersive', buttonText: 'Grab 20% discount', - buttonUrl: 'https://ghost.org/', - suggestedUrls: [{label: 'Homepage', value: 'https://localhost.org/'}] + buttonUrl: 'https://ghost.org/' }; diff --git a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx index 6a765ecf6c..a828ad6c2e 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CallToActionCard.tsx @@ -1,21 +1,21 @@ import CenterAlignIcon from '../../../assets/icons/kg-align-center.svg?react'; import ImmersiveLayoutIcon from '../../../assets/icons/kg-layout-immersive.svg?react'; -import KoenigNestedEditor from '../../KoenigNestedEditor.jsx'; +import KoenigNestedEditor from '../../KoenigNestedEditor'; import LeftAlignIcon from '../../../assets/icons/kg-align-left.svg?react'; import MinimalLayoutIcon from '../../../assets/icons/kg-layout-minimal.svg?react'; -import PropTypes from 'prop-types'; -import ReplacementStringsPlugin from '../../../plugins/ReplacementStringsPlugin.jsx'; +import React, {useState} from 'react'; +import ReplacementStringsPlugin from '../../../plugins/ReplacementStringsPlugin'; import clsx from 'clsx'; -import defaultTheme from '../../../themes/default.js'; -import {Button} from '../Button.jsx'; -import {ButtonGroupSetting, ColorOptionSetting, ColorPickerSetting, InputSetting, InputUrlSetting, MediaUploadSetting, SettingsPanel, ToggleSetting} from '../SettingsPanel.jsx'; -import {CALLTOACTION_COLORS} from '../../../utils/callToActionColors.js'; -import {ReadOnlyOverlay} from '../ReadOnlyOverlay.jsx'; -import {RestrictContentPlugin} from '../../../index.js'; -import {VisibilitySettings} from '../VisibilitySettings.jsx'; -import {getAccentColor} from '../../../utils/getAccentColor.js'; +import defaultTheme from '../../../themes/default'; +import {Button} from '../Button'; +import {ButtonGroupSetting, ColorOptionSetting, ColorPickerSetting, InputSetting, InputUrlSetting, MediaUploadSetting, SettingsPanel, ToggleSetting} from '../SettingsPanel'; +import {CALLTOACTION_COLORS} from '../../../utils/callToActionColors'; +import {ReadOnlyOverlay} from '../ReadOnlyOverlay'; +import {RestrictContentPlugin} from '../../../index'; +import {VisibilitySettings} from '../VisibilitySettings'; +import {getAccentColor} from '../../../utils/getAccentColor'; import {textColorForBackgroundColor} from '@tryghost/color-utils'; -import {useState} from 'react'; +import type {LexicalEditor} from 'lexical'; const getTheme = () => ({ ...defaultTheme, @@ -83,6 +83,46 @@ export const callToActionLinkColorPicker = [ } ]; +type CtaColor = 'none' | 'grey' | 'white' | 'blue' | 'green' | 'yellow' | 'red' | 'pink' | 'purple'; + +interface CallToActionCardProps { + alignment?: 'left' | 'center'; + buttonColor?: string; + buttonText?: string; + buttonTextColor?: string; + buttonUrl?: string; + color?: CtaColor; + hasSponsorLabel?: boolean; + htmlEditor: LexicalEditor; + htmlEditorInitialState?: string; + sponsorLabelHtmlEditor: LexicalEditor; + sponsorLabelHtmlEditorInitialState?: string; + imageSrc?: string; + isEditing?: boolean; + layout?: 'minimal' | 'immersive'; + showButton?: boolean; + showDividers?: boolean; + visibilityOptions?: import('../VisibilitySettings').VisibilityGroup[]; + handleButtonColor?: (bgColor: string, textColor: string) => void; + handleColorChange?: (name: string) => void; + handleLinkColorChange?: (name: string) => void; + onFileChange?: (e: React.ChangeEvent) => void; + onRemoveMedia?: () => void; + setFileInputRef?: (el: HTMLInputElement | null) => void; + updateAlignment?: (name: string) => void; + updateButtonText?: (e: React.ChangeEvent) => void; + updateButtonUrl?: (value: string) => void; + updateHasSponsorLabel?: (event: React.ChangeEvent) => void; + updateLayout?: (name: string) => void; + updateShowButton?: (event: React.ChangeEvent) => void; + updateShowDividers?: (event: React.ChangeEvent) => void; + toggleVisibility?: (groupKey: string, toggleKey: string, value: boolean) => void; + imageDragHandler?: {isDraggedOver?: boolean; setRef?: React.Ref}; + imageUploader?: {isLoading?: boolean; progress?: number}; + linkColor?: 'text' | 'accent'; + showVisibilitySettings?: boolean; +} + export function CallToActionCard({ alignment = 'left', buttonColor = '', @@ -100,7 +140,7 @@ export function CallToActionCard({ layout = 'immersive', showButton = false, showDividers = true, - visibilityOptions = {}, + visibilityOptions = [], handleButtonColor = () => {}, handleColorChange = () => {}, handleLinkColorChange = () => {}, @@ -116,10 +156,10 @@ export function CallToActionCard({ updateShowDividers = () => {}, toggleVisibility = () => {}, imageDragHandler = {}, - imageUploader = () => {}, + imageUploader = {}, linkColor = 'text', showVisibilitySettings = false -}) { +}: CallToActionCardProps) { const [buttonColorPickerExpanded, setButtonColorPickerExpanded] = useState(false); const {isLoading, progress} = imageUploader || {}; @@ -164,7 +204,7 @@ export function CallToActionCard({ } ]; - const matchingTextColor = (bgColor) => { + const matchingTextColor = (bgColor: string) => { return bgColor === 'transparent' ? '' : textColorForBackgroundColor(bgColor === 'accent' ? getAccentColor() : bgColor).hex(); }; @@ -281,12 +321,12 @@ export function CallToActionCard({ {title: 'Brand color', accent: true} ]} value={buttonColor} - onPickerChange={bgColor => handleButtonColor(bgColor, matchingTextColor(bgColor))} - onSwatchChange={(bgColor) => { + onPickerChange={(bgColor: string) => handleButtonColor(bgColor, matchingTextColor(bgColor))} + onSwatchChange={(bgColor: string) => { handleButtonColor(bgColor, matchingTextColor(bgColor)); setButtonColorPickerExpanded(false); }} - onTogglePicker={(isExpanded) => { + onTogglePicker={(isExpanded: boolean) => { setButtonColorPickerExpanded(isExpanded); }} /> @@ -318,7 +358,7 @@ export function CallToActionCard({ '--cta-link-color': linkColor === 'accent' ? getAccentColor() : 'var(--cta-link-color-text)' - }} + } as React.CSSProperties} > {/* Sponsor label */} @@ -423,7 +463,6 @@ export function CallToActionCard({ e.preventDefault()} > {{ content: contentSettings, @@ -435,42 +474,3 @@ export function CallToActionCard({ ); } - -CallToActionCard.propTypes = { - alignment: PropTypes.oneOf(['left', 'center']), - buttonText: PropTypes.string, - buttonUrl: PropTypes.string, - buttonColor: PropTypes.string, - buttonTextColor: PropTypes.string, - color: PropTypes.oneOf(['none', 'grey', 'white', 'blue', 'green', 'yellow', 'red', 'pink', 'purple']), - hasSponsorLabel: PropTypes.bool, - imageSrc: PropTypes.string, - isEditing: PropTypes.bool, - layout: PropTypes.oneOf(['minimal', 'immersive']), - showButton: PropTypes.bool, - showDividers: PropTypes.bool, - htmlEditor: PropTypes.object, - htmlEditorInitialState: PropTypes.object, - updateAlignment: PropTypes.func, - updateButtonText: PropTypes.func, - updateButtonUrl: PropTypes.func, - updateHasSponsorLabel: PropTypes.func, - updateShowButton: PropTypes.func, - updateShowDividers: PropTypes.func, - updateLayout: PropTypes.func, - handleColorChange: PropTypes.func, - handleButtonColor: PropTypes.func, - onFileChange: PropTypes.func, - setFileInputRef: PropTypes.func, - onRemoveMedia: PropTypes.func, - sponsorLabelHtmlEditor: PropTypes.object, - sponsorLabelHtmlEditorInitialState: PropTypes.object, - visibilityOptions: PropTypes.array, - toggleVisibility: PropTypes.func, - imageUploadHandler: PropTypes.func, - imageDragHandler: PropTypes.object, - linkColor: PropTypes.oneOf(['text', 'accent']), - handleLinkColorChange: PropTypes.func, - imageUploader: PropTypes.object, - showVisibilitySettings: PropTypes.bool -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx index 6e6e45c7b5..0860e6035d 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.stories.tsx @@ -1,7 +1,9 @@ -import populateEditor from '../../../utils/storybook/populate-storybook-editor.js'; +import populateEditor from '../../../utils/storybook/populate-storybook-editor'; import {CalloutCard} from './CalloutCard'; import {CardWrapper} from './../CardWrapper'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -9,14 +11,15 @@ const displayOptions = { Editing: {isSelected: true, isEditing: true} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; value?: string}; + +const story: Meta = { title: 'Primary cards/Callout card', component: CalloutCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -36,15 +39,15 @@ const story = { }; export default story; -const Template = ({display, value, ...args}) => { +const Template: StoryFn = ({display, value, ...args}) => { const textEditor = createEditor(); populateEditor({editor: textEditor, initialHtml: `${value}`}); return (
    - - + +
    @@ -55,8 +58,7 @@ export const Empty = Template.bind({}); Empty.args = { display: 'Editing', value: '', - placeholder: 'Callout text...', - emoji: true, + hasEmoji: true, color: 'grey', setShowEmojiPicker: () => {} }; @@ -65,8 +67,7 @@ export const Populated = Template.bind({}); Populated.args = { display: 'Editing', value: 'Something to pay attention to.', - placeholder: 'Callout text...', - emoji: true, + hasEmoji: true, color: 'grey', setShowEmojiPicker: () => {} }; diff --git a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx index e00576b1ce..a560b159c5 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CalloutCard.tsx @@ -1,12 +1,14 @@ import EmojiPickerPortal from '../EmojiPickerPortal'; -import KoenigComposerContext from '../../../context/KoenigComposerContext.jsx'; +import KoenigComposerContext from '../../../context/KoenigComposerContext'; import KoenigNestedEditor from '../../KoenigNestedEditor'; -import PropTypes from 'prop-types'; import React from 'react'; import {ColorOptionSetting, SettingsPanel, ToggleSetting} from '../SettingsPanel'; import {ReadOnlyOverlay} from '../ReadOnlyOverlay'; +import type {LexicalEditor} from 'lexical'; -export const CALLOUT_COLORS = { +export type CalloutColor = 'white' | 'grey' | 'blue' | 'green' | 'yellow' | 'red' | 'pink' | 'purple' | 'accent'; + +export const CALLOUT_COLORS: Record = { white: 'bg-transparent border-grey/30', grey: 'bg-grey/10 border-transparent', blue: 'bg-blue/10 border-transparent', @@ -21,7 +23,7 @@ export const CALLOUT_COLORS = { const TEXT_BLACK = 'text-black dark:text-grey-300 caret-black dark:caret-grey-300'; const TEXT_WHITE = 'text-white caret-white'; -export const CALLOUT_TEXT_COLORS = { +export const CALLOUT_TEXT_COLORS: Record = { white: TEXT_BLACK, grey: TEXT_BLACK, blue: TEXT_BLACK, @@ -82,6 +84,22 @@ export const calloutColorPicker = [ } ]; +interface CalloutCardProps { + color?: CalloutColor; + isEditing?: boolean; + setShowEmojiPicker: (show: boolean) => void; + toggleEmoji?: (event: React.ChangeEvent) => void; + hasEmoji?: boolean; + handleColorChange: (name: string) => void; + changeEmoji?: (emoji: {native: string}) => void; + calloutEmoji?: string; + textEditor: LexicalEditor; + textEditorInitialState?: string; + nodeKey?: string; + toggleEmojiPicker?: () => void; + showEmojiPicker?: boolean; +} + export function CalloutCard({ color = 'green', isEditing, @@ -90,14 +108,14 @@ export function CalloutCard({ hasEmoji = true, handleColorChange, changeEmoji, - calloutEmoji = '💡', + calloutEmoji = '\u{1F4A1}', textEditor, textEditorInitialState, - nodeKey, + nodeKey: _nodeKey, toggleEmojiPicker, showEmojiPicker -}) { - const emojiButtonRef = React.useRef(null); +}: CalloutCardProps) { + const emojiButtonRef = React.useRef(null); const {darkMode} = React.useContext(KoenigComposerContext); React.useEffect(() => { @@ -169,22 +187,3 @@ export function CalloutCard({ ); } - -CalloutCard.propTypes = { - color: PropTypes.oneOf(['white', 'grey', 'blue', 'green', 'yellow', 'red', 'pink', 'purple', 'accent']), - text: PropTypes.string, - hasEmoji: PropTypes.bool, - placeholder: PropTypes.string, - isEditing: PropTypes.bool, - updateText: PropTypes.func, - calloutEmoji: PropTypes.string, - setShowEmojiPicker: PropTypes.func, - toggleEmoji: PropTypes.func, - handleColorChange: PropTypes.func, - changeEmoji: PropTypes.func, - textEditor: PropTypes.object, - textEditorInitialState: PropTypes.object, - nodeKey: PropTypes.string, - toggleEmojiPicker: PropTypes.func, - showEmojiPicker: PropTypes.bool -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx index 950815eda5..0a09cd5510 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.stories.tsx @@ -1,8 +1,10 @@ import populateEditor from '../../../utils/storybook/populate-storybook-editor'; import {CardWrapper} from './../CardWrapper'; import {CodeBlockCard} from './CodeBlockCard'; -import {MINIMAL_NODES} from '../../../index.js'; +import {MINIMAL_NODES} from '../../../index'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -10,14 +12,15 @@ const displayOptions = { Editing: {isSelected: true, isEditing: true} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; caption?: string}; + +const story: Meta = { title: 'Primary cards/Code card', component: CodeBlockCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -37,15 +40,15 @@ const story = { }; export default story; -const Template = ({display, caption, ...args}) => { +const Template: StoryFn = ({display, caption, ...args}) => { const captionEditor = createEditor({nodes: MINIMAL_NODES}); populateEditor({editor: captionEditor, initialHtml: `${caption}`}); return (
    - - {}} {...display} {...args} /> + + {}} {...displayOptions[display]} {...args} />
    diff --git a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx index 832f2a1b85..7ce4ea8831 100644 --- a/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/CodeBlockCard.tsx @@ -1,21 +1,26 @@ import CodeMirror from '@uiw/react-codemirror'; import KoenigComposerContext from '../../../context/KoenigComposerContext'; -import PropTypes from 'prop-types'; import React from 'react'; import {CardCaptionEditor} from '../CardCaptionEditor'; +import {EditorView, keymap, lineNumbers} from '@codemirror/view'; +import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'; import {css} from '@codemirror/lang-css'; -import {darkBaseExtensions, lightBaseExtensions} from '../../../utils/codemirror-config'; +import {history, standardKeymap} from '@codemirror/commands'; import {html} from '@codemirror/lang-html'; import {javascript} from '@codemirror/lang-javascript'; +import {minimalSetup} from '@uiw/codemirror-extensions-basic-setup'; +import {tags as t} from '@lezer/highlight'; +import type {LexicalEditor} from 'lexical'; -const languageMap = new Map([ - ['javascript', javascript], - ['js', javascript], - ['html', html], - ['css', css] -]); +interface CodeEditorProps { + code?: string; + language?: string; + updateCode?: (value: string) => void; + updateLanguage?: (value: string) => void; + darkMode?: boolean; +} -export function CodeEditor({code, language, updateCode, updateLanguage}) { +export function CodeEditor({code, language, updateCode, updateLanguage}: CodeEditorProps) { const [showLanguage, setShowLanguage] = React.useState(true); const {darkMode} = React.useContext(KoenigComposerContext); @@ -32,26 +37,167 @@ export function CodeEditor({code, language, updateCode, updateLanguage}) { }; }, []); - const onChange = React.useCallback((value) => { + const onChange = React.useCallback((value: string) => { setShowLanguage(false); // hide language input whenever the user types in the editor - updateCode(value); + updateCode?.(value); }, [updateCode]); - const onLanguageChange = React.useCallback((event) => { - updateLanguage(event.target.value); + const onLanguageChange = React.useCallback((event: React.ChangeEvent) => { + updateLanguage?.(event.target.value); }, [updateLanguage]); - const extensions = React.useMemo(() => { - const base = darkMode ? darkBaseExtensions : lightBaseExtensions; - const highlighter = languageMap.get(language?.toLowerCase().trim()); - return highlighter ? [...base, highlighter()] : base; - }, [darkMode, language]); + const editorLightCSS = EditorView.theme({ + '&.cm-editor': { + background: 'transparent' + }, + '&.cm-focused': { + outline: '0' + }, + '&.cm-editor .cm-content': { + padding: '7px 0' + }, + '&.cm-editor .cm-scroller': { + overflow: 'auto' + }, + '&.cm-editor .cm-gutters': { + background: 'none', + border: 'none', + fontFamily: 'Consolas,Liberation Mono,Menlo,Courier,monospace;', + color: '#CED4D9', + lineHeight: '2.25rem' + }, + '&.cm-editor .cm-gutter': { + minHeight: '170px' + }, + '&.cm-editor .cm-lineNumbers': { + padding: '0' + }, + '&.cm-editor .cm-foldGutter': { + width: '0' + }, + '&.cm-editor .cm-line': { + padding: '0 .8rem', + color: '#394047', + fontFamily: 'Consolas,Liberation Mono,Menlo,Courier,monospace;', + fontSize: '1.6rem', + lineHeight: '2.25rem' + }, + '&.cm-editor .cm-activeLine, &.cm-editor .cm-activeLineGutter': { + background: 'none' + }, + '&.cm-editor .cm-cursor, &.cm-editor .cm-dropCursor': { + borderLeft: '1.2px solid black' + } + }); + + const editorDarkCSS = EditorView.theme({ + '&.cm-editor': { + background: 'transparent' + }, + '&.cm-focused': { + outline: '0' + }, + '&.cm-editor .cm-content': { + padding: '7px 0' + }, + '&.cm-editor .cm-scroller': { + overflow: 'auto' + }, + '&.cm-editor .cm-gutters': { + background: 'none', + border: 'none', + fontFamily: 'Consolas,Liberation Mono,Menlo,Courier,monospace;', + color: 'rgb(108, 118, 127);', + lineHeight: '2.25rem' + }, + '&.cm-editor .cm-gutter': { + minHeight: '170px' + }, + '&.cm-editor .cm-lineNumbers': { + padding: '0' + }, + '&.cm-editor .cm-foldGutter': { + width: '0' + }, + '&.cm-editor .cm-line': { + padding: '0 .8rem', + color: 'rgb(210, 215, 218)', + fontFamily: 'Consolas,Liberation Mono,Menlo,Courier,monospace;', + fontSize: '1.6rem', + lineHeight: '2.25rem' + }, + '&.cm-editor .cm-activeLine, &.cm-editor .cm-activeLineGutter': { + background: 'none' + }, + '&.cm-editor .cm-cursor, &.cm-editor .cm-dropCursor': { + borderLeft: '1.2px solid white' + } + + }); + + const editorLightHighlightStyle = HighlightStyle.define([ + {tag: t.keyword, color: '#5A5CAD'}, + {tag: t.atom, color: '#6C8CD5'}, + {tag: t.number, color: '#116644'}, + {tag: t.definition(t.variableName), textDecoration: 'underline'}, + {tag: t.variableName, color: 'black'}, + {tag: t.comment, color: '#0080FF', fontStyle: 'italic', background: 'rgba(0,0,0,.05)'}, + {tag: [t.string, t.special(t.brace)], color: '#183691'}, + {tag: t.meta, color: 'yellow'}, + {tag: t.bracket, color: '#63a35c'}, + {tag: t.tagName, color: '#63a35c'}, + {tag: t.attributeName, color: '#795da3'} + ]); + + const editorDarkHighlightStyle = HighlightStyle.define([ + {tag: t.keyword, color: '#795da3'}, + {tag: t.atom, color: '#6C8CD5'}, + {tag: t.number, color: '#63a35c'}, + {tag: t.definition(t.variableName), textDecoration: 'underline'}, + {tag: t.variableName, color: 'white'}, + {tag: t.comment, color: '#0080FF', fontStyle: 'italic', background: 'rgba(0,0,0,.05)'}, + {tag: [t.string, t.special(t.brace)], color: 'rgb(72, 110, 225)'}, + {tag: t.meta, color: 'yellow'}, + {tag: t.bracket, color: '#63a35c'}, + {tag: t.tagName, color: '#63a35c'}, + {tag: t.attributeName, color: '#795da3'}, + {tag: [t.className, t.propertyName], color: 'rgb(72, 110, 225)'} + ]); + + const editorCSS = darkMode ? editorDarkCSS : editorLightCSS; + const editorHighlightStyle = darkMode ? editorDarkHighlightStyle : editorLightHighlightStyle; + + // Base extensions for the CodeMirror editor + const extensions = [ + EditorView.lineWrapping, // wraps lines that exceed the viewport width + syntaxHighlighting(editorHighlightStyle), // customizes syntax highlighting rules + editorCSS, // customizes general editor appearance (does not include syntax highlighting) + lineNumbers(), // adds line numbers to the gutter + minimalSetup({defaultKeymap: false, history: false}), // disable defaultKeymap to prevent Mod+Enter from inserting new line + keymap.of(standardKeymap), // add back in standardKeymap, which doesn't include Mod+Enter + // adds undo/redo functionality with custom behaviour to make tests faster + history({ + joinToEvent: process.env.NODE_ENV === 'test' ? () => false : undefined + }) + ]; + + // If provided language is supported, add the corresponding extension + const languageMap: Record = { + javascript: javascript, + js: javascript, + html: html, + css: css + }; + const highlighter = languageMap[language?.toLowerCase().trim() || ''] || null; + if (highlighter) { + extensions.push(highlighter()); + } return (
    -                
    +                
                         {code}
                     
                 
    @@ -87,7 +239,19 @@ export function CodeBlock({code, darkMode, language}) { ); } -export function CodeBlockCard({captionEditor, captionEditorInitialState, code, darkMode, isEditing, isSelected, language, updateCode, updateLanguage}) { +interface CodeBlockCardProps { + captionEditor?: LexicalEditor; + captionEditorInitialState?: string; + code?: string; + darkMode?: boolean; + isEditing?: boolean; + isSelected?: boolean; + language?: string; + updateCode?: (value: string) => void; + updateLanguage?: (value: string) => void; +} + +export function CodeBlockCard({captionEditor, captionEditorInitialState, code, darkMode, isEditing, isSelected, language, updateCode, updateLanguage}: CodeBlockCardProps) { if (isEditing) { return ( - + {captionEditor && ( + + )} ); } } - -CodeEditor.propTypes = { - code: PropTypes.string, - language: PropTypes.string, - updateCode: PropTypes.func, - updateLanguage: PropTypes.func -}; - -CodeBlock.propTypes = { - code: PropTypes.string, - darkMode: PropTypes.bool, - language: PropTypes.string -}; - -CodeBlockCard.propTypes = { - code: PropTypes.string, - darkMode: PropTypes.bool, - language: PropTypes.string, - captionEditor: PropTypes.object, - captionEditorInitialState: PropTypes.object, - isEditing: PropTypes.bool, - isSelected: PropTypes.bool, - updateCode: PropTypes.func, - updateLanguage: PropTypes.func -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx index 4a0a4df174..e033a42d94 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmailCard.stories.tsx @@ -1,9 +1,11 @@ import EmailIndicatorIcon from '../../../assets/icons/kg-indicator-email.svg?react'; import populateEditor from '../../../utils/storybook/populate-storybook-editor'; -import {BASIC_NODES} from '../../../index.js'; +import {BASIC_NODES} from '../../../index'; import {CardWrapper} from '../CardWrapper'; import {EmailCard} from './EmailCard'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -11,14 +13,15 @@ const displayOptions = { Editing: {isSelected: true, isEditing: true} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; html?: string}; + +const story: Meta = { title: 'Primary cards/Email content card', component: EmailCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -38,15 +41,15 @@ const story = { }; export default story; -const Template = ({display, html, ...args}) => { +const Template: StoryFn = ({display, html, ...args}) => { const editor = createEditor({nodes: BASIC_NODES}); populateEditor({editor, initialHtml: `${html}`}); return (
    - - + +
    diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx b/packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx index ca6485b2a8..5d83e53699 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmailCard.tsx @@ -1,14 +1,20 @@ import KoenigNestedEditor from '../../KoenigNestedEditor'; -import PropTypes from 'prop-types'; import ReplacementStringsPlugin from '../../../plugins/ReplacementStringsPlugin'; -import {CardVisibilityMessage} from '../CardVisibilityMessage.jsx'; +import {CardVisibilityMessage} from '../CardVisibilityMessage'; import {ReadOnlyOverlay} from '../ReadOnlyOverlay'; +import type {LexicalEditor} from 'lexical'; + +interface EmailCardProps { + htmlEditor: LexicalEditor; + htmlEditorInitialState?: string; + isEditing?: boolean; +} export function EmailCard({ htmlEditor, htmlEditorInitialState, isEditing = false -}) { +}: EmailCardProps) { return ( <> @@ -28,9 +34,3 @@ export function EmailCard({ ); } - -EmailCard.propTypes = { - htmlEditor: PropTypes.object, - isEditing: PropTypes.bool, - htmlEditorInitialState: PropTypes.object -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx index 38e1881026..68d791240a 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.stories.tsx @@ -1,9 +1,11 @@ import EmailIndicatorIcon from '../../../assets/icons/kg-indicator-email.svg?react'; -import populateEditor from '../../../utils/storybook/populate-storybook-editor.js'; -import {BASIC_NODES} from '../../../index.js'; +import populateEditor from '../../../utils/storybook/populate-storybook-editor'; +import {BASIC_NODES} from '../../../index'; import {CardWrapper} from './../CardWrapper'; import {EmailCtaCard} from './EmailCtaCard'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, @@ -11,14 +13,15 @@ const displayOptions = { Editing: {isSelected: true, isEditing: true} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; value?: string}; + +const story: Meta = { title: 'Primary cards/Email CTA card', component: EmailCtaCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -38,22 +41,22 @@ const story = { }; export default story; -const Template = ({display, value, ...args}) => { +const Template: StoryFn = ({display, value, ...args}) => { const htmlEditor = createEditor({nodes: BASIC_NODES}); populateEditor({editor: htmlEditor, initialHtml: `${value}`}); return (
    - - + +
    - - + +
    @@ -68,11 +71,9 @@ Empty.args = { alignment: 'left', showDividers: true, value: '', - placeholder: 'Email only text... (optional)', showButton: true, buttonText: '', - buttonUrl: '', - suggestedUrls: [] + buttonUrl: '' }; export const Populated = Template.bind({}); @@ -81,11 +82,9 @@ Populated.args = { segment: 'status:free', alignment: 'center', value: 'Want to get access to premium content?', - placeholder: 'Email only text... (optional)', showButton: false, showDividers: true, buttonText: 'Upgrade', - buttonUrl: 'https://ghost.org/', - suggestedUrls: [{label: 'Homepage', value: 'https://localhost.org/'}] + buttonUrl: 'https://ghost.org/' }; diff --git a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx index e8a28f7acd..fefc3a0d86 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmailCtaCard.tsx @@ -1,12 +1,31 @@ import CenterAlignIcon from '../../../assets/icons/kg-align-center.svg?react'; import KoenigNestedEditor from '../../KoenigNestedEditor'; import LeftAlignIcon from '../../../assets/icons/kg-align-left.svg?react'; -import PropTypes from 'prop-types'; +import React from 'react'; import ReplacementStringsPlugin from '../../../plugins/ReplacementStringsPlugin'; import {Button} from '../Button'; import {ButtonGroupSetting, DropdownSetting, InputSetting, InputUrlSetting, SettingsPanel, ToggleSetting} from '../SettingsPanel'; -import {CardVisibilityMessage} from '../CardVisibilityMessage.jsx'; +import {CardVisibilityMessage} from '../CardVisibilityMessage'; import {ReadOnlyOverlay} from '../ReadOnlyOverlay'; +import type {LexicalEditor} from 'lexical'; + +interface EmailCtaCardProps { + alignment?: 'left' | 'center'; + buttonText?: string; + buttonUrl?: string; + handleSegmentChange?: (value: string) => void; + htmlEditor?: LexicalEditor; + htmlEditorInitialState?: string; + isEditing?: boolean; + segment?: 'status:free' | 'status:-free'; + showDividers?: boolean; + showButton?: boolean; + toggleDividers?: (event: React.ChangeEvent) => void; + updateAlignment?: (name: string) => void; + updateShowButton?: (event: React.ChangeEvent) => void; + updateButtonText?: (e: React.ChangeEvent) => void; + updateButtonUrl?: (value: string) => void; +} export function EmailCtaCard({ alignment = 'left', @@ -24,7 +43,7 @@ export function EmailCtaCard({ updateShowButton, updateButtonText, updateButtonUrl -}) { +}: EmailCtaCardProps) { const alignmentOpts = [ { label: 'Left', @@ -48,7 +67,7 @@ export function EmailCtaCard({ name: 'status:-free' }]; - const getVisibilityMessage = (segmentType) => { + const getVisibilityMessage = (segmentType: string) => { switch (segmentType) { case 'status:free': return 'Hidden on website and paid newsletter'; @@ -74,7 +93,7 @@ export function EmailCtaCard({ {/* Alignment settings */} @@ -114,7 +133,7 @@ export function EmailCtaCard({ buttons={alignmentOpts} label='Content alignment' selectedName={alignment} - onClick={updateAlignment} + onClick={updateAlignment!} /> {/* Dividers settings */} @@ -145,7 +164,7 @@ export function EmailCtaCard({ dataTestId="button-url" label='Button URL' value={buttonUrl} - onChange={updateButtonUrl} + onChange={updateButtonUrl!} /> )} @@ -154,22 +173,3 @@ export function EmailCtaCard({ ); } - -EmailCtaCard.propTypes = { - alignment: PropTypes.oneOf(['left', 'center']), - buttonText: PropTypes.string, - buttonUrl: PropTypes.string, - isEditing: PropTypes.bool, - segment: PropTypes.oneOf(['status:free', 'status:-free']), - showButton: PropTypes.bool, - showDividers: PropTypes.bool, - updateAlignment: PropTypes.func, - updateButtonText: PropTypes.func, - updateButtonUrl: PropTypes.func, - updateShowButton: PropTypes.func, - toggleDividers: PropTypes.func, - suggestedUrls: PropTypes.array, - handleSegmentChange: PropTypes.func, - htmlEditor: PropTypes.object, - htmlEditorInitialState: PropTypes.object -}; diff --git a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx index 0403798509..5fae537b6d 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.stories.tsx @@ -1,22 +1,25 @@ import populateEditor from '../../../utils/storybook/populate-storybook-editor'; import {CardWrapper} from './../CardWrapper'; import {EmbedCard} from './EmbedCard'; -import {MINIMAL_NODES} from '../../../index.js'; +import {MINIMAL_NODES} from '../../../index'; import {createEditor} from 'lexical'; +import type {ComponentProps} from 'react'; +import type {Meta, StoryFn} from '@storybook/react-vite'; const displayOptions = { Default: {isSelected: false, isEditing: false}, Selected: {isSelected: true, isEditing: false} }; -const story = { +type StoryArgs = ComponentProps & {display: keyof typeof displayOptions; caption?: string}; + +const story: Meta = { title: 'Primary cards/Embed card', component: EmbedCard, - subcomponent: {CardWrapper}, + subcomponents: {CardWrapper}, argTypes: { display: { options: Object.keys(displayOptions), - mapping: displayOptions, control: { type: 'radio', labels: { @@ -35,20 +38,20 @@ const story = { }; export default story; -const Template = ({display, caption, ...args}) => { +const Template: StoryFn = ({display, caption, ...args}) => { const captionEditor = createEditor({nodes: MINIMAL_NODES}); populateEditor({editor: captionEditor, initialHtml: `${caption}`}); return (
    - - + +
    - - + +
    @@ -58,53 +61,19 @@ const Template = ({display, caption, ...args}) => { export const Empty = Template.bind({}); Empty.args = { display: 'Selected', - url: '', + urlInputValue: '', urlPlaceholder: 'Paste URL to add embedded content...' }; export const Populated = Template.bind({}); Populated.args = { display: 'Selected', - url: 'https://ghost.org/', - embedType: 'video', - html: '', - metadata: { - html: '', - thumbnail_width: 480, - width: 480, - author_url: 'https://www.youtube.com/user/gorillaz', - height: 270, - thumbnail_height: 360, - provider_name: 'YouTube', - title: 'Gorillaz - Humility (Official Video)', - provider_url: 'https://www.youtube.com/', - author_name: 'Gorillaz', - version: '1.0', - thumbnail_url: 'https://i.ytimg.com/vi/E5yFcdPAGv0/hqdefault.jpg', - type: 'video' - } + html: '' }; export const WithCaption = Template.bind({}); WithCaption.args = { display: 'Selected', - url: 'https://ghost.org/', caption: 'This is a caption', - embedType: 'video', - html: '', - metadata: { - html: '', - thumbnail_width: 480, - width: 480, - author_url: 'https://www.youtube.com/user/gorillaz', - height: 270, - thumbnail_height: 360, - provider_name: 'YouTube', - title: 'Gorillaz - Humility (Official Video)', - provider_url: 'https://www.youtube.com/', - author_name: 'Gorillaz', - version: '1.0', - thumbnail_url: 'https://i.ytimg.com/vi/E5yFcdPAGv0/hqdefault.jpg', - type: 'video' - } + html: '' }; diff --git a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx index ce3b12b5dd..f35f71bb7c 100644 --- a/packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx +++ b/packages/koenig-lexical/src/components/ui/cards/EmbedCard.tsx @@ -1,10 +1,26 @@ import '@tryghost/kg-simplemde/dist/simplemde.min.css'; -import PropTypes from 'prop-types'; import React from 'react'; import {CardCaptionEditor} from '../CardCaptionEditor'; import {UrlInput} from '../UrlInput'; +import type {LexicalEditor} from 'lexical'; + +interface EmbedCardProps { + captionEditor?: LexicalEditor; + captionEditorInitialState?: string; + html?: string; + isSelected?: boolean; + urlInputValue?: string; + urlPlaceholder?: string; + urlError?: boolean; + isLoading?: boolean; + handleUrlChange?: (e: React.ChangeEvent) => void; + handleUrlSubmit: (e: KeyboardEvent | React.KeyboardEvent) => void; + handleRetry?: () => void; + handlePasteAsLink?: (value?: string) => void; + handleClose?: () => void; +} -export function EmbedCard({captionEditor, captionEditorInitialState, html, isSelected, urlInputValue, urlPlaceholder, urlError, isLoading, handleUrlChange, handleUrlSubmit, handleRetry, handlePasteAsLink, handleClose}) { +export function EmbedCard({captionEditor, captionEditorInitialState, html, isSelected, urlInputValue, urlPlaceholder, urlError, isLoading, handleUrlChange, handleUrlSubmit, handleRetry, handlePasteAsLink, handleClose}: EmbedCardProps) { if (html) { return (
    @@ -12,13 +28,15 @@ export function EmbedCard({captionEditor, captionEditorInitialState, html, isSel
    - + {captionEditor && ( + + )}
    ); } @@ -38,12 +56,17 @@ export function EmbedCard({captionEditor, captionEditorInitialState, html, isSel ); } -function EmbedIframe({dataTestId, html}) { - const iframeRef = React.useRef(null); +interface EmbedIframeProps { + dataTestId?: string; + html: string; +} + +function EmbedIframe({dataTestId, html}: EmbedIframeProps) { + const iframeRef = React.useRef(null); const handleResize = () => { // get ratio from nested iframe if present (eg, Vimeo) - const firstElement = iframeRef.current?.contentDocument?.body?.firstChild; + const firstElement = iframeRef.current?.contentDocument?.body?.firstChild as HTMLElement | null; // won't have an iframe if the embed is invalid or fetching if (!firstElement) { @@ -51,20 +74,21 @@ function EmbedIframe({dataTestId, html}) { } if (firstElement.tagName === 'IFRAME') { - const widthAttr = firstElement.getAttribute('width'); - const heightAttr = firstElement.getAttribute('height'); + const iframeElement = firstElement as HTMLIFrameElement; + const widthAttr = iframeElement.getAttribute('width'); + const heightAttr = iframeElement.getAttribute('height'); if (widthAttr && heightAttr && widthAttr.indexOf('%') === -1 && heightAttr.indexOf('%') === -1) { const ratio = parseInt(widthAttr) / parseInt(heightAttr); - const newHeight = iframeRef.current.offsetWidth / ratio; - firstElement.style.height = `${newHeight}px`; - iframeRef.current.style.height = `${newHeight}px`; - firstElement.style.width = '100%'; + const newHeight = iframeRef.current!.offsetWidth / ratio; + iframeElement.style.height = `${newHeight}px`; + iframeRef.current!.style.height = `${newHeight}px`; + iframeElement.style.width = '100%'; return; } if (heightAttr && heightAttr.indexOf('%') === -1) { - iframeRef.current.style.height = `${heightAttr}px`; + iframeRef.current!.style.height = `${heightAttr}px`; return; } } @@ -76,11 +100,11 @@ function EmbedIframe({dataTestId, html}) { return; } - iframeRef.current.style.height = `${scrollHeight}px`; + iframeRef.current!.style.height = `${scrollHeight}px`; }; // register mutation observer to handle changes to iframe content (e.g. twitter embeds loading richer content) - const config = { + const config: MutationObserverInit = { attributes: true, attributeOldValue: false, characterData: true, @@ -91,7 +115,7 @@ function EmbedIframe({dataTestId, html}) { const mutationObserver = new MutationObserver(handleResize); const handleLoad = () => { - const iframeBody = iframeRef.current.contentDocument.body; + const iframeBody = iframeRef.current!.contentDocument!.body; // apply styles iframeBody.style.display = 'flex'; iframeBody.style.margin = '0'; @@ -99,20 +123,20 @@ function EmbedIframe({dataTestId, html}) { // resize first load handleResize(); // start listening to mutations when the iframe content is loaded - mutationObserver.observe(iframeRef.current.contentWindow.document, config); + mutationObserver.observe(iframeRef.current!.contentWindow!.document, config); }; // register listener for window resize events React.useEffect(() => { const resizeObserver = new ResizeObserver(handleResize); - resizeObserver.observe(iframeRef.current); + resizeObserver.observe(iframeRef.current!); // cleanup listener when component unmounts return function cleanup() { resizeObserver.disconnect(); mutationObserver.disconnect(); }; - }, []); + }, []); // eslint-disable-line react-hooks/exhaustive-deps return ( '); + expect(sanitizedHtml).toEqual('Hey
    Embedded iFrame
    '); + }); + it('can render html', function () { const sanitizedHtml = sanitizeHtml('bold'); expect(sanitizedHtml).toEqual('bold'); diff --git a/packages/koenig-lexical/test/unit/utils/visibility.test.ts b/packages/koenig-lexical/test/unit/utils/visibility.test.ts index e89a083454..8ce2a06253 100644 --- a/packages/koenig-lexical/test/unit/utils/visibility.test.ts +++ b/packages/koenig-lexical/test/unit/utils/visibility.test.ts @@ -87,7 +87,7 @@ describe('parseVisibilityToToggles', function () { describe('getVisibilityOptions', function () { it('has correct default options', function () { - const options = getVisibilityOptions(); + const options = getVisibilityOptions(undefined); expect(options).toEqual([ { @@ -239,17 +239,17 @@ describe('serializeOptionsToVisibility', function () { key: 'web', label: 'Web', toggles: [ - {key: 'nonMembers', checked: true}, - {key: 'freeMembers', checked: true}, - {key: 'paidMembers', checked: false} + {key: 'nonMembers', label: 'Public visitors', checked: true}, + {key: 'freeMembers', label: 'Free members', checked: true}, + {key: 'paidMembers', label: 'Paid members', checked: false} ] }, { key: 'email', label: 'Email', toggles: [ - {key: 'freeMembers', checked: false}, - {key: 'paidMembers', checked: true} + {key: 'freeMembers', label: 'Free members', checked: false}, + {key: 'paidMembers', label: 'Paid members', checked: true} ] } ]); diff --git a/packages/koenig-lexical/test/utils/color-select-helper.ts b/packages/koenig-lexical/test/utils/color-select-helper.ts index 1fbe56b294..7cefcc951d 100644 --- a/packages/koenig-lexical/test/utils/color-select-helper.ts +++ b/packages/koenig-lexical/test/utils/color-select-helper.ts @@ -1,4 +1,6 @@ -export async function selectNamedColor(page, colorName, testId) { +import type {Page} from '@playwright/test'; + +export async function selectNamedColor(page: Page, colorName: string, testId?: string) { if (testId) { const color = page.locator(`[data-testid="${testId}"]`); await color.click(); @@ -7,7 +9,7 @@ export async function selectNamedColor(page, colorName, testId) { await colorPicker.click(); } -export async function selectCustomColor(page, color, pickerTestId) { +export async function selectCustomColor(page: Page, color: string, pickerTestId?: string) { if (pickerTestId) { const customColor = page.locator(`[data-testid="${pickerTestId}"]`); await customColor.click(); @@ -16,7 +18,7 @@ export async function selectCustomColor(page, color, pickerTestId) { await customColorInput.fill(color); } -export async function selectTitledColor(page, colorName, testId) { +export async function selectTitledColor(page: Page, colorName: string, testId?: string) { if (testId) { const color = page.locator(`[data-testid="${testId}"]`); await color.click(); diff --git a/packages/koenig-lexical/test/utils/e2e.ts b/packages/koenig-lexical/test/utils/e2e.ts index 00e2987d11..958ffc7a78 100644 --- a/packages/koenig-lexical/test/utils/e2e.ts +++ b/packages/koenig-lexical/test/utils/e2e.ts @@ -4,15 +4,63 @@ import prettier from '@prettier/sync'; import startCase from 'lodash/startCase.js'; import {E2E_PORT} from '../../playwright.config'; import {expect} from '@playwright/test'; +import type {Page} from '@playwright/test'; const {JSDOM} = jsdom; const browserCtrlOrCmdMap = new WeakMap(); -export async function initialize({page, uri = '/#/?content=false'}) { +interface AssertHTMLOptions { + selector?: string; + ignoreClasses?: boolean; + ignoreInlineStyles?: boolean; + ignoreInnerSVG?: boolean; + getBase64FileFormat?: boolean; + ignoreCardContents?: boolean; + ignoreCardSettings?: boolean; + ignoreCardToolbarContents?: boolean; + ignoreDragDropAttrs?: boolean; + ignoreDataTestId?: boolean; + ignoreCardCaptionContents?: boolean; +} + +interface PrettifyHTMLOptions { + ignoreClasses?: boolean; + ignoreInlineStyles?: boolean; + ignoreInnerSVG?: boolean; + getBase64FileFormat?: boolean; + ignoreCardContents?: boolean; + ignoreCardSettings?: boolean; + ignoreCardToolbarContents?: boolean; + ignoreDragDropAttrs?: boolean; + ignoreDataTestId?: boolean; + ignoreCardCaptionContents?: boolean; +} + +interface FileData { + filePath: string; + fileName: string; + fileType: string; +} + +interface SelectionExpectation { + anchorPath: number[]; + anchorOffset: number | [number, number]; + focusPath: number[]; + focusOffset: number | [number, number]; +} + +export interface BoundingBox { + x: number; + y: number; + width: number; + height: number; +} + +export async function initialize({page, uri = '/#/?content=false', force: _force = false}: {page: Page; uri?: string; force?: boolean}) { const url = `http://localhost:${E2E_PORT}${uri}`; const currentViewportSize = page.viewportSize(); - if (currentViewportSize.width !== 1000 || currentViewportSize.height !== 1000) { + if (currentViewportSize!.width !== 1000 || currentViewportSize!.height !== 1000) { await page.setViewportSize({width: 1000, height: 1000}); } @@ -26,24 +74,25 @@ export async function initialize({page, uri = '/#/?content=false'}) { await exposeLexicalEditor(page); } else { // Subsequent pages navigated to using react router - await page.evaluate(async ([navigateTo, force]) => { - window.lexicalEditor.blur(); - window.lexicalEditor.setEditorState(window.originalEditorState); + await page.evaluate(async ([navigateTo, force]: [string, boolean]) => { + const w = window; + w.lexicalEditor.blur(); + w.lexicalEditor.setEditorState(w.originalEditorState); if (force) { // Purposefully navigate away from the current page to ensure component is reloaded - window.navigate('/404'); - await new Promise((res) => { + w.navigate('/404'); + await new Promise((res) => { setTimeout(() => { // Navigate in a task to ensure React Router cannot optimise out our first navigation - window.navigate(navigateTo); + w.navigate(navigateTo); res(); }, 10); }); } else { - await window.navigate(navigateTo); + await w.navigate(navigateTo); } - }, [uri.slice(2), currentUrl === url]); + }, [uri.slice(2), currentUrl === url] as [string, boolean]); await exposeLexicalEditor(page); } @@ -52,22 +101,23 @@ export async function initialize({page, uri = '/#/?content=false'}) { })); } -async function exposeLexicalEditor(page) { +async function exposeLexicalEditor(page: Page) { await page.waitForSelector('[data-lexical-editor]'); await page.evaluate(() => { - window.lexicalEditor = document.querySelector('[data-lexical-editor]').__lexicalEditor; + const el = document.querySelector('[data-lexical-editor]') as HTMLElement & {__lexicalEditor: unknown}; + window.lexicalEditor = el.__lexicalEditor as KoenigTestEditor; window.originalEditorState = window.lexicalEditor.getEditorState(); }); } -export async function focusEditor(page, parentSelector = '.koenig-lexical') { +export async function focusEditor(page: Page, parentSelector = '.koenig-lexical') { const selector = `${parentSelector} div[contenteditable="true"]`; await page.focus(selector); } export async function assertHTML( - page, - expectedHtml, + page: Page, + expectedHtml: string, { selector = 'div[contenteditable="true"]', ignoreClasses = true, @@ -80,7 +130,7 @@ export async function assertHTML( ignoreDragDropAttrs = true, ignoreDataTestId = true, ignoreCardCaptionContents = false - } = {} + }: AssertHTMLOptions = {} ) { const actualHtml = await page.$eval(selector, e => e.innerHTML); const actual = prettifyHTML(actualHtml.replace(/\n/gm, ''), { @@ -110,7 +160,7 @@ export async function assertHTML( expect(actual).toEqual(expected); } -export function prettifyHTML(string, options = {}) { +export function prettifyHTML(string: string, options: PrettifyHTMLOptions = {}) { let output = string; if (options.ignoreInnerSVG) { @@ -132,7 +182,7 @@ export function prettifyHTML(string, options = {}) { if (options.ignoreCardContents || options.ignoreCardToolbarContents || options.ignoreCardCaptionContents || options.ignoreCardSettings) { const {document} = (new JSDOM(output)).window; - const querySelectors = []; + const querySelectors: string[] = []; if (options.ignoreCardContents) { querySelectors.push('[data-kg-card]'); } @@ -146,7 +196,7 @@ export function prettifyHTML(string, options = {}) { querySelectors.push('[data-testid="settings-panel"]'); } - document.querySelectorAll(querySelectors.join(', ')).forEach((element) => { + document.querySelectorAll(querySelectors.join(', ')).forEach((element: Element) => { element.innerHTML = ''; }); output = document.body.innerHTML; @@ -176,7 +226,7 @@ export function prettifyHTML(string, options = {}) { .trim(); } -export function prettifyJSON(string) { +export function prettifyJSON(string: string) { let output = string; // replace urls inside markdown links @@ -191,7 +241,7 @@ export function prettifyJSON(string) { // This function does not suppose to do anything, it's only used as a trigger // for prettier auto-formatting (https://prettier.io/blog/2020/08/24/2.1.0.html#api) -export function html(partials, ...params) { +export function html(partials: TemplateStringsArray, ...params: unknown[]) { let output = ''; for (let i = 0; i < partials.length; i++) { output += partials[i]; @@ -202,13 +252,13 @@ export function html(partials, ...params) { return output; } -export async function assertSelection(page, expected) { +export async function assertSelection(page: Page, expected: SelectionExpectation) { // Assert the selection of the editor matches the snapshot const selection = await page.evaluate(() => { const rootElement = document.querySelector('div[contenteditable="true"]'); - const getPathFromNode = (node) => { - const path = []; + const getPathFromNode = (node: Node | null): number[] => { + const path: number[] = []; if (node === rootElement) { return []; } @@ -217,13 +267,13 @@ export async function assertSelection(page, expected) { if (parent === null || node === rootElement) { break; } - path.push(Array.from(parent.childNodes).indexOf(node)); + path.push(Array.from(parent.childNodes).indexOf(node as ChildNode)); node = parent; } return path.reverse(); }; - const {anchorNode, anchorOffset, focusNode, focusOffset} = window.getSelection(); + const {anchorNode, anchorOffset, focusNode, focusOffset} = window.getSelection()!; return { anchorOffset, @@ -231,7 +281,7 @@ export async function assertSelection(page, expected) { focusOffset, focusPath: getPathFromNode(focusNode) }; - }, expected); + }); expect(selection.anchorPath).toEqual(expected.anchorPath); @@ -254,21 +304,21 @@ export async function assertSelection(page, expected) { } } -export async function assertPosition(page, selector, expectedBox, {threshold = 0} = {}) { +export async function assertPosition(page: Page, selector: string, expectedBox: Partial, {threshold = 0} = {}) { const assertedElem = await page.$(selector); - const assertedBox = await assertedElem.boundingBox(); + const assertedBox = await assertedElem!.boundingBox(); - ['x', 'y'].forEach((boxProperty) => { + (['x', 'y'] as const).forEach((boxProperty) => { if (Object.prototype.hasOwnProperty.call(expectedBox, boxProperty)) { - expect(assertedBox[boxProperty], boxProperty).toBeGreaterThanOrEqual(expectedBox[boxProperty] - threshold); - expect(assertedBox[boxProperty], boxProperty).toBeLessThanOrEqual(expectedBox[boxProperty] + threshold); + expect(assertedBox![boxProperty], boxProperty).toBeGreaterThanOrEqual(expectedBox[boxProperty]! - threshold); + expect(assertedBox![boxProperty], boxProperty).toBeLessThanOrEqual(expectedBox[boxProperty]! + threshold); } }); } -export async function getEditorStateJSON(page) { +export async function getEditorStateJSON(page: Page) { const json = await page.evaluate(() => { - const rootElement = document.querySelector('div[contenteditable="true"]'); + const rootElement = document.querySelector('div[contenteditable="true"]') as HTMLElement & {__lexicalEditor: {getEditorState: () => {toJSON: () => unknown}}}; const editor = rootElement.__lexicalEditor; return JSON.stringify(editor.getEditorState().toJSON()); }); @@ -276,7 +326,7 @@ export async function getEditorStateJSON(page) { return json; } -export async function assertRootChildren(page, expectedState) { +export async function assertRootChildren(page: Page, expectedState: string) { const state = await getEditorStateJSON(page); const actualState = JSON.stringify(JSON.parse(state).root.children); @@ -286,7 +336,7 @@ export async function assertRootChildren(page, expectedState) { expect(actual).toEqual(expected); } -export async function paste(page, data) { +export async function paste(page: Page, data: Record) { const setDataCommands = Object.keys(data).map((mimeType) => { return ` dataTransfer.setData('${mimeType}', ${JSON.stringify(data[mimeType])}); @@ -310,60 +360,63 @@ export async function paste(page, data) { await page.evaluate(pasteCommand); } -export async function pasteText(page, content) { +export async function pasteText(page: Page, content: string) { await paste(page, {'text/plain': content}); } -export async function pasteHtml(page, content) { +export async function pasteHtml(page: Page, content: string) { await paste(page, {'text/html': content}); } -export async function pasteLexical(page, content) { +export async function pasteLexical(page: Page, content: string) { await paste(page, {'application/x-lexical-editor': content}); } -export async function pasteFiles(page, files) { +export async function pasteFiles(page: Page, files: FileData[]) { const dataTransfer = await createDataTransfer(page, files); await page.evaluate(async (clipboardData) => { - document.activeElement.dispatchEvent(new ClipboardEvent('paste', { - clipboardData: clipboardData, + document.activeElement!.dispatchEvent(new ClipboardEvent('paste', { + clipboardData: clipboardData as unknown as DataTransfer, bubbles: true, cancelable: true })); - clipboardData.clearData(); + (clipboardData as unknown as DataTransfer).clearData(); }, dataTransfer); } -export async function pasteFilesWithText(page, files, text = {}) { +export async function pasteFilesWithText(page: Page, files: FileData[], text: Record = {}) { const dataTransfer = await createDataTransfer(page, files); await page.evaluate(async ({clipboardData, textData}) => { Object.keys(textData).forEach((mimeType) => { - clipboardData.setData(mimeType, textData[mimeType]); + (clipboardData as unknown as DataTransfer).setData(mimeType, textData[mimeType]); }); - document.activeElement.dispatchEvent(new ClipboardEvent('paste', { - clipboardData: clipboardData, + document.activeElement!.dispatchEvent(new ClipboardEvent('paste', { + clipboardData: clipboardData as unknown as DataTransfer, bubbles: true, cancelable: true })); - clipboardData.clearData(); + (clipboardData as unknown as DataTransfer).clearData(); }, {clipboardData: dataTransfer, textData: text}); } export async function dragMouse( - page, - fromBoundingBox, - toBoundingBox, + page: Page, + fromBoundingBox: BoundingBox | null, + toBoundingBox: BoundingBox | null, positionStart = 'middle', positionEnd = 'middle', mouseUp = true, hover = 0, steps = 1 ) { + if (!fromBoundingBox || !toBoundingBox) { + throw new Error('dragMouse: bounding box not found'); + } let fromX = fromBoundingBox.x; let fromY = fromBoundingBox.y; if (positionStart === 'middle') { @@ -402,7 +455,7 @@ export function isMac() { return process.platform === 'darwin'; } -export function ctrlOrCmd(page) { +export function ctrlOrCmd(page?: Page) { if (!page) { return isMac() ? 'Meta' : 'Control'; } @@ -417,8 +470,8 @@ export function ctrlOrCmd(page) { } // note: we always use lowercase for the cardName but we use start case for the menu item attribute -export async function insertCard(page, {cardName, nth = 0}) { - let card = startCase(cardName); +export async function insertCard(page: Page, {cardName, nth = 0}: {cardName: string; nth?: number}) { + const card = startCase(cardName); await page.keyboard.type(`/${cardName}`); await expect(page.locator(`[data-kg-card-menu-item="${card}" i][data-kg-cardmenu-selected="true"]`)).toBeVisible(); await page.keyboard.press('Enter'); @@ -432,7 +485,7 @@ export async function insertCard(page, {cardName, nth = 0}) { } } -export async function createSnippet(page) { +export async function createSnippet(page: Page) { await page.waitForSelector('[data-testid="create-snippet"]'); // Small wait for toolbar to stabilize after card state transitions // (React re-renders can detach and re-mount toolbar elements) @@ -442,13 +495,13 @@ export async function createSnippet(page) { await page.keyboard.press('Enter'); } -export async function getScrollPosition(page) { +export async function getScrollPosition(page: Page) { return await page.evaluate(() => { - return document.querySelector('.h-full.overflow-auto').scrollTop; + return document.querySelector('.h-full.overflow-auto')!.scrollTop; }); } -export async function enterUntilScrolled(page) { +export async function enterUntilScrolled(page: Page) { let scrollPosition = 0; while (scrollPosition === 0) { @@ -460,15 +513,15 @@ export async function enterUntilScrolled(page) { } } -export async function expectUnchangedScrollPosition(page, wrapper) { +export async function expectUnchangedScrollPosition(page: Page, wrapper: () => Promise) { const start = await getScrollPosition(page); await wrapper(); const end = await getScrollPosition(page); expect(start).toEqual(end); } -export async function createDataTransfer(page, data = []) { - const filesData = []; +export async function createDataTransfer(page: Page, data: FileData[] = []) { + const filesData: {buffer: number[]; name: string; type: string}[] = []; data.forEach((file) => { const buffer = fs.readFileSync(file.filePath); @@ -480,10 +533,10 @@ export async function createDataTransfer(page, data = []) { }); }); - return await page.evaluateHandle((dataset = []) => { + return await page.evaluateHandle((dataset) => { const dt = new DataTransfer(); - dataset.forEach((fileData) => { + dataset.forEach((fileData: {buffer: number[]; name: string; type: string}) => { const file = new File([new Uint8Array(fileData.buffer)], fileData.name, {type: fileData.type}); dt.items.add(file); }); @@ -492,9 +545,9 @@ export async function createDataTransfer(page, data = []) { }, filesData); } -export async function getEditorState(page) { +export async function getEditorState(page: Page): Promise<{root: {children: Array>}}> { return await page.evaluate(() => { - return window.lexicalEditor.getEditorState().toJSON(); + return window.lexicalEditor.getEditorState().toJSON() as {root: {children: Array>}}; }); } @@ -503,7 +556,7 @@ export async function getEditorState(page) { * Uses keyboard Shift+ArrowLeft with a short wait to ensure Chrome for Testing * registers the selection correctly before subsequent keyboard actions. */ -export async function selectBackwards(page, charCount) { +export async function selectBackwards(page: Page, charCount: number) { await page.keyboard.down('Shift'); for (let i = 0; i < charCount; i++) { await page.keyboard.press('ArrowLeft'); @@ -518,7 +571,7 @@ export async function selectBackwards(page, charCount) { * Uses keyboard Shift+ArrowRight with a short wait to ensure Chrome for Testing * registers the selection correctly before subsequent keyboard actions. */ -export async function selectForward(page, charCount) { +export async function selectForward(page: Page, charCount: number) { await page.keyboard.down('Shift'); for (let i = 0; i < charCount; i++) { await page.keyboard.press('ArrowRight'); diff --git a/packages/koenig-lexical/tsconfig.json b/packages/koenig-lexical/tsconfig.json new file mode 100644 index 0000000000..bcbef41b44 --- /dev/null +++ b/packages/koenig-lexical/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "jsx": "react-jsx", + "strict": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "include": ["src/**/*", "demo/**/*"] +} diff --git a/packages/koenig-lexical/tsconfig.test.json b/packages/koenig-lexical/tsconfig.test.json new file mode 100644 index 0000000000..f7dc98afe2 --- /dev/null +++ b/packages/koenig-lexical/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["vitest/globals"] + }, + "include": ["src/**/*", "test/**/*"] +} diff --git a/packages/koenig-lexical/tsconfig.types.json b/packages/koenig-lexical/tsconfig.types.json new file mode 100644 index 0000000000..3af936e8c0 --- /dev/null +++ b/packages/koenig-lexical/tsconfig.types.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "noEmit": false, + "outDir": "./dist/types", + "rootDir": "./src" + }, + "include": ["src/**/*"], + "exclude": ["src/**/*.stories.tsx"] +} diff --git a/packages/koenig-lexical/vite.config.demo.ts b/packages/koenig-lexical/vite.config.demo.ts index df8818cd35..2348e23ab6 100644 --- a/packages/koenig-lexical/vite.config.demo.ts +++ b/packages/koenig-lexical/vite.config.demo.ts @@ -1,7 +1,10 @@ import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; import {defineConfig} from 'vite'; -import {resolve} from 'path'; +import {resolve, dirname} from 'path'; +import {fileURLToPath} from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); // https://vitejs.dev/config/ export default (function viteDemoConfig() { @@ -41,7 +44,7 @@ export default (function viteDemoConfig() { test: { globals: true, // required for @testing-library/jest-dom extensions environment: 'jsdom', - setupFiles: './test/test-setup.js', + setupFiles: './test/test-setup.ts', include: ['./test/unit/*'], testTimeout: 10000, ...(process.env.CI && { // https://github.com/vitest-dev/vitest/issues/1674 diff --git a/packages/koenig-lexical/vite.config.ts b/packages/koenig-lexical/vite.config.ts index 1cd11a6586..0408b6bd06 100644 --- a/packages/koenig-lexical/vite.config.ts +++ b/packages/koenig-lexical/vite.config.ts @@ -3,14 +3,17 @@ import mdx from '@mdx-js/rollup'; import pkg from './package.json'; import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; -import {defineConfig, esmExternalRequirePlugin, loadEnv} from 'vite'; -import {resolve} from 'path'; +import {defineConfig, esmExternalRequirePlugin, loadEnv, type ConfigEnv} from 'vite'; +import {resolve, dirname} from 'path'; +import {fileURLToPath} from 'url'; import {sentryVitePlugin} from '@sentry/vite-plugin'; +const __dirname = dirname(fileURLToPath(import.meta.url)); + const outputFileName = pkg.name[0] === '@' ? pkg.name.slice(pkg.name.indexOf('/') + 1) : pkg.name; // https://vitejs.dev/config/ -export default (function viteConfig({mode}) { +export default (function viteConfig({mode}: ConfigEnv) { const env = loadEnv(mode, process.cwd()); process.env = {...process.env, ...env}; @@ -87,7 +90,7 @@ export default (function viteConfig({mode}) { sourcemap: true, cssCodeSplit: true, lib: { - entry: resolve(__dirname, 'src/index.js'), + entry: resolve(__dirname, 'src/index.ts'), name: pkg.name, fileName(format) { if (format === 'umd') { @@ -120,7 +123,7 @@ export default (function viteConfig({mode}) { test: { globals: true, // required for @testing-library/jest-dom extensions environment: 'jsdom', - setupFiles: './test/test-setup.js', + setupFiles: './test/test-setup.ts', include: ['./test/unit/**/*.test.{js,jsx,ts,tsx}'], testTimeout: process.env.TIMEOUT ? parseInt(process.env.TIMEOUT) : 10000, ...(process.env.CI && { // https://github.com/vitest-dev/vitest/issues/1674 diff --git a/yarn.lock b/yarn.lock index 8b8edede38..743acaf2dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,7 +66,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.7.tgz#6f0237f0f36d2e51c0570a636faed9d2d0efe629" integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg== -"@babel/core@7.29.7", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.28.0": +"@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.28.0": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.7.tgz#80c10b17248082968b57a857b91640971f2070f7" integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA== @@ -107,13 +107,6 @@ "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz#c70fe3c6ecbdc3fd2dd1b0f498428b88b82ce47f" - integrity sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw== - dependencies: - "@babel/types" "^7.29.7" - "@babel/helper-compilation-targets@^7.29.7": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz#7a1def704302401c47f64fa85589e974ae217042" @@ -125,32 +118,11 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.21.0": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz#6eddf286f2ec418f740c91d60a83347c55838ddd" - integrity sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.29.7" - "@babel/helper-member-expression-to-functions" "^7.29.7" - "@babel/helper-optimise-call-expression" "^7.29.7" - "@babel/helper-replace-supers" "^7.29.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.29.7" - "@babel/traverse" "^7.29.7" - semver "^6.3.1" - "@babel/helper-globals@^7.29.7": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz#f04a96fbd8473241b1079243f5b3f03a3010ab7b" integrity sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA== -"@babel/helper-member-expression-to-functions@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz#8dbdb3ce0b5c487e1aec10e13c9a43a500814df8" - integrity sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg== - dependencies: - "@babel/traverse" "^7.29.7" - "@babel/types" "^7.29.7" - "@babel/helper-module-imports@^7.29.7": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz#ef25048a518e828d7393fac5882ddd73921d7396" @@ -168,35 +140,6 @@ "@babel/helper-validator-identifier" "^7.29.7" "@babel/traverse" "^7.29.7" -"@babel/helper-optimise-call-expression@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz#77b0b5b94f1997fa9d6e3125f445227b1faf9d85" - integrity sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong== - dependencies: - "@babel/types" "^7.29.7" - -"@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.20.2": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz#c0a0766f1a13617d8a17407d7ab8f9d486225ea4" - integrity sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw== - -"@babel/helper-replace-supers@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz#bc3c3964329043c79112e513c1b198f16589ac21" - integrity sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.29.7" - "@babel/helper-optimise-call-expression" "^7.29.7" - "@babel/traverse" "^7.29.7" - -"@babel/helper-skip-transparent-expression-wrappers@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz#50c95c7e4c4f54936cfa0116428edc559862d551" - integrity sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ== - dependencies: - "@babel/traverse" "^7.29.7" - "@babel/types" "^7.29.7" - "@babel/helper-string-parser@^7.29.7": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f" @@ -227,23 +170,6 @@ dependencies: "@babel/types" "^7.29.7" -"@babel/plugin-proposal-private-property-in-object@7.21.11": - version "7.21.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" - integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.21.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768" @@ -386,9 +312,9 @@ style-mod "^4.0.0" "@codemirror/lint@^6.0.0": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.9.7.tgz#841fc733674389d91fe49a1c34027ad3babdf105" - integrity sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg== + version "6.9.6" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.9.6.tgz#eae25d5dfac28595521a2b38ebad223f14b7b6d1" + integrity sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A== dependencies: "@codemirror/state" "^6.0.0" "@codemirror/view" "^6.42.0" @@ -421,9 +347,9 @@ "@lezer/highlight" "^1.0.0" "@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.37.0", "@codemirror/view@^6.42.0": - version "6.43.1" - resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.43.1.tgz#bfe3ea568e38812631749c1b6c9c7869784143a5" - integrity sha512-+BIjw/AG3tDQ4pJgTLPYdAW25eDE66YsvM4LKyVPgGzVgZ4a9Wj1SRX8kPVKgBDdPt8oHtZ15F0qx7p0oOHdHw== + version "6.43.0" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.43.0.tgz#a577da65f1d5d8f7cbf08e14849284c12f38365a" + integrity sha512-V7ZCLQO3Jus9hzh2jVCCPW3mO4IBMr43O37PqSUYautJSnnJF41YlgLw21x0fLJTYvJ+Vkm6Gp+qKGH9pltgXA== dependencies: "@codemirror/state" "^6.6.0" crelt "^1.0.6" @@ -441,9 +367,9 @@ integrity sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg== "@csstools/css-color-parser@^4.1.0": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-4.1.7.tgz#ca32fc74a3cdec7c288651fe01241fcd59f95a0e" - integrity sha512-CmjJFQTFQx/U/xNJhSjCQ0ilpesPmNQ8+eOUeM/+kDOVW33qsIjeOXc27vrQDdWVkf83ZSWwtg7kXSUvKDJ8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-4.1.1.tgz#70c322112e2aafb0b09f34b51ce3482db6aab2ac" + integrity sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g== dependencies: "@csstools/color-helpers" "^6.0.2" "@csstools/css-calc" "^3.2.1" @@ -508,9 +434,9 @@ tslib "^2.4.0" "@emnapi/core@^1.1.0": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.11.1.tgz#b9e1064f3a6b1631e241e638eb48d736bfd372a6" - integrity sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ== + version "1.11.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.11.0.tgz#8a655042dbbb10d0266670c9903c34a7001c705b" + integrity sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q== dependencies: "@emnapi/wasi-threads" "1.2.2" tslib "^2.4.0" @@ -537,9 +463,9 @@ tslib "^2.4.0" "@emnapi/runtime@^1.1.0": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.11.1.tgz#58f1f3d5d81a9b12f793ab688c96371901027c24" - integrity sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw== + version "1.11.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.11.0.tgz#ce16b3674ff7266bbf50f9668bde8a04f3014d4e" + integrity sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg== dependencies: tslib "^2.4.0" @@ -579,269 +505,269 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz#82b74f92aa78d720b714162939fb248c90addf53" integrity sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg== -"@esbuild/aix-ppc64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz#7a01a8d2ec2fbb2dac78adad09b0fa781e4082be" - integrity sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ== +"@esbuild/aix-ppc64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz#7a289c158e29cbf59ea0afc83cc80f06d1c89402" + integrity sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA== "@esbuild/android-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz#f78cb8a3121fc205a53285adb24972db385d185d" integrity sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ== -"@esbuild/android-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz#b540a27d14e4afd058496a4dbec4d3f414db110a" - integrity sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg== +"@esbuild/android-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz#b8828d9edfa3a92660644eb8de6e4f3c203d7b17" + integrity sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw== "@esbuild/android-arm@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.7.tgz#593e10a1450bbfcac6cb321f61f468453bac209d" integrity sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ== -"@esbuild/android-arm@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz#704bd297de6d762de54eabbeafbf55f6756abe2f" - integrity sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ== +"@esbuild/android-arm@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz#5ec1847605e05b5dbe5df90db9ff7e3e4c58dca7" + integrity sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ== "@esbuild/android-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.7.tgz#453143d073326033d2d22caf9e48de4bae274b07" integrity sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg== -"@esbuild/android-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz#d1cb166d34b0fbf0fe8ab460a5594f24a378701e" - integrity sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng== +"@esbuild/android-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.0.tgz#390642175b88ef82bad4cce03f8ab13fe9b1912e" + integrity sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA== "@esbuild/darwin-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz#6f23000fb9b40b7e04b7d0606c0693bd0632f322" integrity sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw== -"@esbuild/darwin-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz#1034b26457fc886368fe61bbd09f653f6afa8e54" - integrity sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q== +"@esbuild/darwin-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz#ae45325960d5950cd6951e4f97396f4e1ff7d8d3" + integrity sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q== "@esbuild/darwin-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz#27393dd18bb1263c663979c5f1576e00c2d024be" integrity sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ== -"@esbuild/darwin-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz#65556a432a1e4d72032d8218c1932fcca1a49772" - integrity sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ== +"@esbuild/darwin-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz#c079247d589b6b99449659d94f06951b84bff2e4" + integrity sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ== "@esbuild/freebsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz#22e4638fa502d1c0027077324c97640e3adf3a62" integrity sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w== -"@esbuild/freebsd-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz#2e61e0592f9030d7e3dae18ee25ebc535918aef6" - integrity sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw== +"@esbuild/freebsd-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz#45c456215a486593c94900297202dc11c880a37a" + integrity sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q== "@esbuild/freebsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz#9224b8e4fea924ce2194e3efc3e9aebf822192d6" integrity sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ== -"@esbuild/freebsd-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz#c95ec289959ef8079c4dca817a1e2c4be66b9bd3" - integrity sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ== +"@esbuild/freebsd-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz#0399494c1c85e4388e9b7040bd60d48f2a5b0d2c" + integrity sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw== "@esbuild/linux-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz#4f5d1c27527d817b35684ae21419e57c2bda0966" integrity sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A== -"@esbuild/linux-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz#40b22175dda06182f3ee8141186c5ff304c4a717" - integrity sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g== +"@esbuild/linux-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz#d6d9f09ef0de54116bf459a4d53cac7e0952fe39" + integrity sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A== "@esbuild/linux-arm@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz#b9e9d070c8c1c0449cf12b20eac37d70a4595921" integrity sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA== -"@esbuild/linux-arm@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz#c09a0f67917592ac0de892a9be4d3814debd2a6c" - integrity sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ== +"@esbuild/linux-arm@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz#7b42ffa84c288ae94fdc431c1b28a89e3c3b9278" + integrity sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw== "@esbuild/linux-ia32@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz#3f80fb696aa96051a94047f35c85b08b21c36f9e" integrity sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg== -"@esbuild/linux-ia32@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz#a580f9c676797833891e519fc7a1337c8afd8db3" - integrity sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w== +"@esbuild/linux-ia32@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz#deb15d112ed8dd605346b6b953d23a21ff81253f" + integrity sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ== "@esbuild/linux-loong64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz#9be1f2c28210b13ebb4156221bba356fe1675205" integrity sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q== -"@esbuild/linux-loong64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz#46452cf321dc7f9e91c2fa780a56bb56e79cd68b" - integrity sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg== +"@esbuild/linux-loong64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz#81fb89d07eecc79b157dea61033757726fce0ca4" + integrity sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg== "@esbuild/linux-mips64el@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz#4ab5ee67a3dfcbcb5e8fd7883dae6e735b1163b8" integrity sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw== -"@esbuild/linux-mips64el@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz#4211b3184dd6608f53dcb22e39f5d34ee08852c8" - integrity sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ== +"@esbuild/linux-mips64el@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz#d0e42691b3ff7af9fb2217b70fc01f343bdb62bb" + integrity sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w== "@esbuild/linux-ppc64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz#dac78c689f6499459c4321e5c15032c12307e7ea" integrity sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ== -"@esbuild/linux-ppc64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz#697857c2a61cb9b0b6bb6652e40c1dc5e1ca8e5d" - integrity sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ== +"@esbuild/linux-ppc64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz#389f3e5e98f17d477c467cc87136e1a076eead87" + integrity sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg== "@esbuild/linux-riscv64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz#050f7d3b355c3a98308e935bc4d6325da91b0027" integrity sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ== -"@esbuild/linux-riscv64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz#d192943eb146a40ac4c6497d0cf7be35b986bf08" - integrity sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ== +"@esbuild/linux-riscv64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz#763bd60d59b242be12da1e67d5729f3024c605fa" + integrity sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ== "@esbuild/linux-s390x@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz#d61f715ce61d43fe5844ad0d8f463f88cbe4fef6" integrity sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw== -"@esbuild/linux-s390x@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz#acea0356da0e0ebc08f97cf7b9c2e401e1e648dc" - integrity sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag== +"@esbuild/linux-s390x@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz#aac6061634872e4677de693bce8030d73b1fd055" + integrity sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q== "@esbuild/linux-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz#ca8e1aa478fc8209257bf3ac8f79c4dc2982f32a" integrity sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA== -"@esbuild/linux-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz#6f0c3ce0cb64c534b70c4c45ecb2c16d34e35dfd" - integrity sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA== +"@esbuild/linux-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz#4f2917747188fe77632bcec65b2d84b422419779" + integrity sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ== "@esbuild/netbsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz#1650f2c1b948deeb3ef948f2fc30614723c09690" integrity sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w== -"@esbuild/netbsd-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz#8bcd77077a0dce3378b574fedb26d2a253b73d36" - integrity sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw== +"@esbuild/netbsd-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz#814df0ae57a0c386814491b8397eeba82094a947" + integrity sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw== "@esbuild/netbsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz#65772ab342c4b3319bf0705a211050aac1b6e320" integrity sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw== -"@esbuild/netbsd-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz#e7fb2a01e99c830c94e6623cd9fefb4c8fb58347" - integrity sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg== +"@esbuild/netbsd-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz#e01bdf7e60fa1a08e46d46d960b0d9bb8ac210af" + integrity sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw== "@esbuild/openbsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz#37ed7cfa66549d7955852fce37d0c3de4e715ea1" integrity sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A== -"@esbuild/openbsd-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz#c52909372db8b86e2c55e05a8940033b5660a3b2" - integrity sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q== +"@esbuild/openbsd-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz#4a15c36aacca68d2d5a4c90b710c06759f4c1ffa" + integrity sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g== "@esbuild/openbsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz#01bf3d385855ef50cb33db7c4b52f957c34cd179" integrity sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg== -"@esbuild/openbsd-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz#c427b9be5a64c262ff9a7eb70b5fbbaadf446c6c" - integrity sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw== +"@esbuild/openbsd-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz#475e6101498a8ecce3008d7c388111d7a27c17bd" + integrity sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA== "@esbuild/openharmony-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz#6c1f94b34086599aabda4eac8f638294b9877410" integrity sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw== -"@esbuild/openharmony-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz#dc9b147baca2e6c4b3c85571741ef4860a489097" - integrity sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg== +"@esbuild/openharmony-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz#cfdc3957f0b7a69f1bde129aad17fcc2f6fa033e" + integrity sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w== "@esbuild/sunos-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz#4b0dd17ae0a6941d2d0fd35a906392517071a90d" integrity sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA== -"@esbuild/sunos-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz#ce866d12df13c15e4c99f073a3d466f6e0649b3a" - integrity sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ== +"@esbuild/sunos-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz#a013c856fecacd1c3aec985c8afe1d1cb017497d" + integrity sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw== "@esbuild/win32-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz#34193ab5565d6ff68ca928ac04be75102ccb2e77" integrity sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA== -"@esbuild/win32-arm64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz#7468e3692d01d629d5941e5d83817bb80f9e39b4" - integrity sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA== +"@esbuild/win32-arm64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz#eae05e0f35271cad3898b43168d3e9a3bbaf47e5" + integrity sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA== "@esbuild/win32-ia32@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz#eb67f0e4482515d8c1894ede631c327a4da9fc4d" integrity sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw== -"@esbuild/win32-ia32@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz#a5bc0063fb2bcab6d0ed63f2a1537958bc269ec6" - integrity sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg== +"@esbuild/win32-ia32@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz#06161ebc5bf75c08d69feb3c6b22560515913998" + integrity sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA== "@esbuild/win32-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz#8fe30b3088b89b4873c3a6cc87597ae3920c0a8b" integrity sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg== -"@esbuild/win32-x64@0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz#10064ee44f4347b90c9a02b446bbf80a91632b12" - integrity sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A== +"@esbuild/win32-x64@0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz#04d90d5752b4ce65d2b6ac25eba08ff7624fe07c" + integrity sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw== -"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": version "4.9.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2": version "4.12.2" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== @@ -1549,11 +1475,11 @@ "@tybys/wasm-util" "^0.9.0" "@napi-rs/wasm-runtime@^1.1.4": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz#cccd6ebc40b991dea6936f9126b1b8155b6c4c95" - integrity sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q== + version "1.1.4" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz#a46bbfedc29751b7170c5d23bc1d8ee8c7e3c1e1" + integrity sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow== dependencies: - "@tybys/wasm-util" "^0.10.2" + "@tybys/wasm-util" "^0.10.1" "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" @@ -2972,7 +2898,7 @@ dependencies: tslib "^2.4.0" -"@tybys/wasm-util@^0.10.2": +"@tybys/wasm-util@^0.10.1": version "0.10.2" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.2.tgz#12b3a1b33db1f9cad4ddff1f604ab7dd00bf464e" integrity sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg== @@ -3161,9 +3087,9 @@ integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/node@*": - version "25.9.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.3.tgz#11dfe7a33e68fa5c560f0aa76cc5595621ef26b9" - integrity sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg== + version "25.9.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.2.tgz#fc8958e757994b71fee516f9634bdb03d1b19e9f" + integrity sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw== dependencies: undici-types ">=7.24.0 <7.24.7" @@ -3259,6 +3185,20 @@ "@types/expect" "^1.20.4" "@types/node" "*" +"@typescript-eslint/eslint-plugin@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.49.0.tgz#8ed8736b8415a9193989220eadb6031dbcd2260a" + integrity sha512-JXij0vzIaTtCwu6SxTh8qBc66kmf1xs7pI4UOiMDFVct6q86G0Zs7KRcEoJgY3Cav3x5Tq0MF5jwgpgLqgKG3A== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.49.0" + "@typescript-eslint/type-utils" "8.49.0" + "@typescript-eslint/utils" "8.49.0" + "@typescript-eslint/visitor-keys" "8.49.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + "@typescript-eslint/eslint-plugin@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz#b1ce606d87221daec571e293009675992f0aae76" @@ -3287,6 +3227,17 @@ natural-compare "^1.4.0" ts-api-utils "^2.5.0" +"@typescript-eslint/parser@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.49.0.tgz#0ede412d59e99239b770f0f08c76c42fba717fa2" + integrity sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA== + dependencies: + "@typescript-eslint/scope-manager" "8.49.0" + "@typescript-eslint/types" "8.49.0" + "@typescript-eslint/typescript-estree" "8.49.0" + "@typescript-eslint/visitor-keys" "8.49.0" + debug "^4.3.4" + "@typescript-eslint/parser@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.56.1.tgz#21d13b3d456ffb08614c1d68bb9a4f8d9237cdc7" @@ -3309,6 +3260,15 @@ "@typescript-eslint/visitor-keys" "8.61.0" debug "^4.4.3" +"@typescript-eslint/project-service@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.49.0.tgz#ce220525c88cb2d23792b391c07e14cb9697651a" + integrity sha512-/wJN0/DKkmRUMXjZUXYZpD1NEQzQAAn9QWfGwo+Ai8gnzqH7tvqS7oNVdTjKqOcPyVIdZdyCMoqN66Ia789e7g== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.49.0" + "@typescript-eslint/types" "^8.49.0" + debug "^4.3.4" + "@typescript-eslint/project-service@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.56.1.tgz#65c8d645f028b927bfc4928593b54e2ecd809244" @@ -3327,6 +3287,14 @@ "@typescript-eslint/types" "^8.61.0" debug "^4.4.3" +"@typescript-eslint/scope-manager@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.49.0.tgz#a3496765b57fb48035d671174552e462e5bffa63" + integrity sha512-npgS3zi+/30KSOkXNs0LQXtsg9ekZ8OISAOLGWA/ZOEn0ZH74Ginfl7foziV8DT+D98WfQ5Kopwqb/PZOaIJGg== + dependencies: + "@typescript-eslint/types" "8.49.0" + "@typescript-eslint/visitor-keys" "8.49.0" + "@typescript-eslint/scope-manager@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz#254df93b5789a871351335dd23e20bc164060f24" @@ -3343,16 +3311,32 @@ "@typescript-eslint/types" "8.61.0" "@typescript-eslint/visitor-keys" "8.61.0" +"@typescript-eslint/tsconfig-utils@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.49.0.tgz#857777c8e35dd1e564505833d8043f544442fbf4" + integrity sha512-8prixNi1/6nawsRYxet4YOhnbW+W9FK/bQPxsGB1D3ZrDzbJ5FXw5XmzxZv82X3B+ZccuSxo/X8q9nQ+mFecWA== + "@typescript-eslint/tsconfig-utils@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz#1afa830b0fada5865ddcabdc993b790114a879b7" integrity sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ== -"@typescript-eslint/tsconfig-utils@8.61.0", "@typescript-eslint/tsconfig-utils@^8.38.0", "@typescript-eslint/tsconfig-utils@^8.56.1", "@typescript-eslint/tsconfig-utils@^8.61.0": +"@typescript-eslint/tsconfig-utils@8.61.0", "@typescript-eslint/tsconfig-utils@^8.38.0", "@typescript-eslint/tsconfig-utils@^8.49.0", "@typescript-eslint/tsconfig-utils@^8.56.1", "@typescript-eslint/tsconfig-utils@^8.61.0": version "8.61.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz#05d6e3ff20001674ebcd22d03dac29ee448043ba" integrity sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ== +"@typescript-eslint/type-utils@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.49.0.tgz#d8118a0c1896a78a22f01d3c176e9945409b085b" + integrity sha512-KTExJfQ+svY8I10P4HdxKzWsvtVnsuCifU5MvXrRwoP2KOlNZ9ADNEWWsQTJgMxLzS5VLQKDjkCT/YzgsnqmZg== + dependencies: + "@typescript-eslint/types" "8.49.0" + "@typescript-eslint/typescript-estree" "8.49.0" + "@typescript-eslint/utils" "8.49.0" + debug "^4.3.4" + ts-api-utils "^2.1.0" + "@typescript-eslint/type-utils@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz#7a6c4fabf225d674644931e004302cbbdd2f2e24" @@ -3375,16 +3359,36 @@ debug "^4.4.3" ts-api-utils "^2.5.0" +"@typescript-eslint/types@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.49.0.tgz#c1bd3ebf956d9e5216396349ca23c58d74f06aee" + integrity sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ== + "@typescript-eslint/types@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.56.1.tgz#975e5942bf54895291337c91b9191f6eb0632ab9" integrity sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw== -"@typescript-eslint/types@8.61.0", "@typescript-eslint/types@^8.56.1", "@typescript-eslint/types@^8.61.0": +"@typescript-eslint/types@8.61.0", "@typescript-eslint/types@^8.49.0", "@typescript-eslint/types@^8.56.1", "@typescript-eslint/types@^8.61.0": version "8.61.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.61.0.tgz#0ddb46e012a4288292950bdd253db42f278ce64d" integrity sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg== +"@typescript-eslint/typescript-estree@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.49.0.tgz#99c5a53275197ccb4e849786dad68344e9924135" + integrity sha512-jrLdRuAbPfPIdYNppHJ/D0wN+wwNfJ32YTAm10eJVsFmrVpXQnDWBn8niCSMlWjvml8jsce5E/O+86IQtTbJWA== + dependencies: + "@typescript-eslint/project-service" "8.49.0" + "@typescript-eslint/tsconfig-utils" "8.49.0" + "@typescript-eslint/types" "8.49.0" + "@typescript-eslint/visitor-keys" "8.49.0" + debug "^4.3.4" + minimatch "^9.0.4" + semver "^7.6.0" + tinyglobby "^0.2.15" + ts-api-utils "^2.1.0" + "@typescript-eslint/typescript-estree@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz#3b9e57d8129a860c50864c42188f761bdef3eab0" @@ -3415,6 +3419,16 @@ tinyglobby "^0.2.15" ts-api-utils "^2.5.0" +"@typescript-eslint/utils@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.49.0.tgz#43b3b91d30afd6f6114532cf0b228f1790f43aff" + integrity sha512-N3W7rJw7Rw+z1tRsHZbK395TWSYvufBXumYtEGzypgMUthlg0/hmCImeA8hgO2d2G4pd7ftpxxul2J8OdtdaFA== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.49.0" + "@typescript-eslint/types" "8.49.0" + "@typescript-eslint/typescript-estree" "8.49.0" + "@typescript-eslint/utils@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.56.1.tgz#5a86acaf9f1b4c4a85a42effb217f73059f6deb7" @@ -3435,6 +3449,14 @@ "@typescript-eslint/types" "8.61.0" "@typescript-eslint/typescript-estree" "8.61.0" +"@typescript-eslint/visitor-keys@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.49.0.tgz#8e450cc502c0d285cad9e84d400cf349a85ced6c" + integrity sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA== + dependencies: + "@typescript-eslint/types" "8.49.0" + eslint-visitor-keys "^4.2.1" + "@typescript-eslint/visitor-keys@8.56.1": version "8.56.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz#50e03475c33a42d123dc99e63acf1841c0231f87" @@ -3758,9 +3780,9 @@ acorn@^7.0.0: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.0.0, acorn@^8.14.0, acorn@^8.15.0, acorn@^8.16.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.17.0.tgz#1785adb84faf8d8add10369b93826fc2bd08f1fe" - integrity sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg== + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== add-stream@^1.0.0: version "1.0.0" @@ -4055,9 +4077,9 @@ ast-types@^0.16.1: tslib "^2.0.1" ast-v8-to-istanbul@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.4.tgz#9b3c38bdcadbb17f0da8cab2ca3daf8cdf5e0af2" - integrity sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.3.tgz#ba858c396a3d45f36a6963594fdfcd4675dfd445" + integrity sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg== dependencies: "@jridgewell/trace-mapping" "^0.3.31" estree-walker "^3.0.3" @@ -4131,13 +4153,6 @@ b4a@^1.6.4: resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.8.1.tgz#7f16334ca80127aeb26064a28841acbf174840a4" integrity sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw== -babel-loader@10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-10.1.1.tgz#ce9748e85b7071eb88006e3cfa9e6cf14eeb97c5" - integrity sha512-JwKSzk2kjIe7mgPK+/lyZ2QAaJcpahNAdM+hgR2HI8D0OJVkdj8Rl6J3kaLYki9pwF7P2iWnD8qVv80Lq1ABtg== - dependencies: - find-up "^5.0.0" - bach@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bach/-/bach-2.0.1.tgz#45a3a3cbf7dbba3132087185c60357482b988972" @@ -4183,9 +4198,9 @@ base64-js@1.5.1, base64-js@^1.0.2, base64-js@^1.3.1: integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== baseline-browser-mapping@^2.10.12: - version "2.10.37" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz#3e636475b6b293244e2b23e2c71a2ab9d9e6ba7d" - integrity sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig== + version "2.10.34" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.34.tgz#dedb606362446777cfe328d30d4ee15056d06303" + integrity sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw== before-after-hook@^2.2.0: version "2.2.3" @@ -4647,9 +4662,9 @@ camelcase@^6.0.0, camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001782, caniuse-lite@^1.0.30001787: - version "1.0.30001799" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz#5c909138c27f1a61219d3e092071c1cc7d32dc55" - integrity sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw== + version "1.0.30001797" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz#1332709e1439f01ff92085dd17001e0a45897ec0" + integrity sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w== ccount@^1.0.0: version "1.1.0" @@ -5856,9 +5871,9 @@ ejs@5.0.1: integrity sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A== electron-to-chromium@^1.5.328: - version "1.5.372" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz#ae8ac69942a37b231773b8fb01759f73733599e3" - integrity sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA== + version "1.5.368" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.368.tgz#8e8d4600c5f5f01e891f8f843b4a941afb640412" + integrity sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw== elliptic@^6.5.3, elliptic@^6.6.1: version "6.6.1" @@ -5940,9 +5955,9 @@ end-of-stream@1.4.5, end-of-stream@^1.4.1, end-of-stream@^1.4.4: once "^1.4.0" enhanced-resolve@^5.17.1, enhanced-resolve@^5.18.1: - version "5.24.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz#cf14b9768a774cb6a5087220c0dc6e55df6ec35a" - integrity sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ== + version "5.23.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.23.0.tgz#dfdf8d1c9065e4b52f8a598356138931c07305f9" + integrity sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA== dependencies: graceful-fs "^4.2.4" tapable "^2.3.3" @@ -6072,9 +6087,9 @@ es-errors@1.3.0, es-errors@^1.3.0: integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== es-iterator-helpers@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz#0a229dc38ada0450b8cfaa85809fd73dbb34113c" - integrity sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g== + version "1.3.2" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz#8f4ff1f3603cbd09fbdb72c747a679779a65cc7f" + integrity sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw== dependencies: call-bind "^1.0.9" call-bound "^1.0.4" @@ -6191,36 +6206,36 @@ esast-util-from-js@^2.0.0: "@esbuild/win32-x64" "0.27.7" esbuild@~0.28.0: - version "0.28.1" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.1.tgz#ef45b4634c9c9d97a296aea4114a5f9840f95578" - integrity sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw== + version "0.28.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.0.tgz#5dee347ffb3e3874212a35a69836b077b1ce6d96" + integrity sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw== optionalDependencies: - "@esbuild/aix-ppc64" "0.28.1" - "@esbuild/android-arm" "0.28.1" - "@esbuild/android-arm64" "0.28.1" - "@esbuild/android-x64" "0.28.1" - "@esbuild/darwin-arm64" "0.28.1" - "@esbuild/darwin-x64" "0.28.1" - "@esbuild/freebsd-arm64" "0.28.1" - "@esbuild/freebsd-x64" "0.28.1" - "@esbuild/linux-arm" "0.28.1" - "@esbuild/linux-arm64" "0.28.1" - "@esbuild/linux-ia32" "0.28.1" - "@esbuild/linux-loong64" "0.28.1" - "@esbuild/linux-mips64el" "0.28.1" - "@esbuild/linux-ppc64" "0.28.1" - "@esbuild/linux-riscv64" "0.28.1" - "@esbuild/linux-s390x" "0.28.1" - "@esbuild/linux-x64" "0.28.1" - "@esbuild/netbsd-arm64" "0.28.1" - "@esbuild/netbsd-x64" "0.28.1" - "@esbuild/openbsd-arm64" "0.28.1" - "@esbuild/openbsd-x64" "0.28.1" - "@esbuild/openharmony-arm64" "0.28.1" - "@esbuild/sunos-x64" "0.28.1" - "@esbuild/win32-arm64" "0.28.1" - "@esbuild/win32-ia32" "0.28.1" - "@esbuild/win32-x64" "0.28.1" + "@esbuild/aix-ppc64" "0.28.0" + "@esbuild/android-arm" "0.28.0" + "@esbuild/android-arm64" "0.28.0" + "@esbuild/android-x64" "0.28.0" + "@esbuild/darwin-arm64" "0.28.0" + "@esbuild/darwin-x64" "0.28.0" + "@esbuild/freebsd-arm64" "0.28.0" + "@esbuild/freebsd-x64" "0.28.0" + "@esbuild/linux-arm" "0.28.0" + "@esbuild/linux-arm64" "0.28.0" + "@esbuild/linux-ia32" "0.28.0" + "@esbuild/linux-loong64" "0.28.0" + "@esbuild/linux-mips64el" "0.28.0" + "@esbuild/linux-ppc64" "0.28.0" + "@esbuild/linux-riscv64" "0.28.0" + "@esbuild/linux-s390x" "0.28.0" + "@esbuild/linux-x64" "0.28.0" + "@esbuild/netbsd-arm64" "0.28.0" + "@esbuild/netbsd-x64" "0.28.0" + "@esbuild/openbsd-arm64" "0.28.0" + "@esbuild/openbsd-x64" "0.28.0" + "@esbuild/openharmony-arm64" "0.28.0" + "@esbuild/sunos-x64" "0.28.0" + "@esbuild/win32-arm64" "0.28.0" + "@esbuild/win32-ia32" "0.28.0" + "@esbuild/win32-x64" "0.28.0" escalade@3.2.0, escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -6918,7 +6933,7 @@ foreground-child@^3.1.0, foreground-child@^3.1.1, foreground-child@^3.3.1: cross-spawn "^7.0.6" signal-exit "^4.0.1" -form-data@4.0.5: +form-data@4.0.5, form-data@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== @@ -6929,17 +6944,6 @@ form-data@4.0.5: hasown "^2.0.2" mime-types "^2.1.12" -form-data@^4.0.5: - version "4.0.6" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" - integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - es-set-tostringtag "^2.1.0" - hasown "^2.0.4" - mime-types "^2.1.35" - fraction.js@^5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-5.3.4.tgz#8c0fcc6a9908262df4ed197427bdeef563e0699a" @@ -6995,19 +6999,16 @@ function-bind@1.1.2, function-bind@^1.1.2: integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: - version "1.2.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.2.0.tgz#758f3e84fa542672454bd5e14cb081a5ce07f70c" - integrity sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew== + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: - call-bind "^1.0.9" - call-bound "^1.0.4" - es-define-property "^1.0.1" - es-errors "^1.3.0" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - hasown "^2.0.4" + hasown "^2.0.2" is-callable "^1.2.7" - is-document.all "^1.0.0" functions-have-names@^1.2.3: version "1.2.3" @@ -7572,7 +7573,7 @@ hasown@2.0.2: dependencies: function-bind "^1.1.2" -hasown@^2.0.0, hasown@^2.0.2, hasown@^2.0.3, hasown@^2.0.4: +hasown@^2.0.0, hasown@^2.0.2, hasown@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== @@ -7821,7 +7822,7 @@ ignore-walk@^8.0.0: dependencies: minimatch "^10.0.3" -ignore@7.0.5, ignore@^7.0.5: +ignore@7.0.5, ignore@^7.0.0, ignore@^7.0.5: version "7.0.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== @@ -8165,13 +8166,6 @@ is-docker@^3.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== -is-document.all@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-document.all/-/is-document.all-1.0.0.tgz#163a4bfb362c6ed7b118ce46cdecc4e37dee3195" - integrity sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g== - dependencies: - call-bound "^1.0.4" - is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" @@ -10068,7 +10062,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@2.1.35, mime-types@^2.1.12, mime-types@^2.1.35: +mime-types@2.1.35, mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -10836,9 +10830,9 @@ object.values@^1.1.6, object.values@^1.2.1: es-object-atoms "^1.0.0" obug@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.3.tgz#c02c60f95abd603409330e767db7f2823193331e" - integrity sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg== + version "2.1.2" + resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.2.tgz#024d704dceae438ef875556ebf9e22e47fd951c2" + integrity sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg== once@1.4.0, once@^1.3.0, once@^1.4.0: version "1.4.0" @@ -11108,9 +11102,9 @@ pacote@21.0.1: tar "^7.4.3" pacote@^21.0.0, pacote@^21.0.2: - version "21.5.1" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-21.5.1.tgz#74ab896fc7b1f00545ecbbbf666a61895cd50d38" - integrity sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg== + version "21.5.0" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-21.5.0.tgz#475fe00db73585dec296590bec484109522e9e6f" + integrity sha512-VtZ0SB8mb5Tzw3dXDfVAIjhyVKUHZkS/ZH9/5mpKenwC9sFOXNI0JI7kEF7IMkwOnsWMFrvAZHzx1T5fmrp9FQ== dependencies: "@gar/promise-retry" "^1.0.0" "@npmcli/git" "^7.0.0" @@ -11535,17 +11529,17 @@ postcss-safe-parser@^7.0.1: integrity sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A== postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: - version "6.1.4" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz#fdec4ca80f5781bd216ca9bf89a2a0fccfffa5f0" - integrity sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ== + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" postcss-selector-parser@^7.0.0, postcss-selector-parser@^7.1.0, postcss-selector-parser@^7.1.1: - version "7.1.4" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz#69dc7a526517572ff6b150e352b36a016017b485" - integrity sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg== + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz#e75d2e0d843f620e5df69076166f4e16f891cb9f" + integrity sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -12500,7 +12494,7 @@ semver@7.7.4: resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== -semver@7.8.4, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.2, semver@^7.7.3: +semver@7.8.4, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@^7.7.2, semver@^7.7.3: version "7.8.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.4.tgz#c73eceebae0616934be8dff28a7fd70757c8e696" integrity sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA== @@ -12630,7 +12624,7 @@ should@*, should@13.2.3: should-type-adaptors "^1.0.1" should-util "^1.0.0" -side-channel-list@^1.0.1: +side-channel-list@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== @@ -12660,13 +12654,13 @@ side-channel-weakmap@^1.0.2: side-channel-map "^1.0.1" side-channel@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab" - integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== dependencies: es-errors "^1.3.0" - object-inspect "^1.13.4" - side-channel-list "^1.0.1" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" @@ -13012,9 +13006,9 @@ stream-splicer@^2.0.0: readable-stream "^2.0.2" streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0: - version "2.28.0" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.28.0.tgz#035ab56057b7ed2211b51d532e6973f0f99fbf11" - integrity sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw== + version "2.27.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.27.0.tgz#0f4811c500e7f17156e4917df0190d21db703442" + integrity sha512-WZ189TKnHoAokYHvwzaAQMpd55cgUmFIcJFzBSgGcb886jau5DL+XdDhTWV4ps3FLvk+OORp0dLRTPsLZ21CSA== dependencies: events-universal "^1.0.0" fast-fifo "^1.3.2" @@ -13721,7 +13715,7 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== -ts-api-utils@^2.4.0, ts-api-utils@^2.5.0: +ts-api-utils@^2.1.0, ts-api-utils@^2.4.0, ts-api-utils@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1" integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== @@ -13734,9 +13728,9 @@ ts-declaration-location@^1.0.6: picomatch "^4.0.2" ts-dedent@^2.0.0, ts-dedent@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.3.0.tgz#8fac36c7902b541c154ac13a27ac467997af11f8" - integrity sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== ts-interface-checker@^0.1.9: version "0.1.13" @@ -13867,6 +13861,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typescript-eslint@8.49.0: + version "8.49.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.49.0.tgz#4a8b608ae48c0db876c8fb2a2724839fc5a7147c" + integrity sha512-zRSVH1WXD0uXczCXw+nsdjGPUdx4dfrs5VQoHnUWmv1U3oNlAKv4FUNdLDhVUg+gYn+a5hUESqch//Rv5wVhrg== + dependencies: + "@typescript-eslint/eslint-plugin" "8.49.0" + "@typescript-eslint/parser" "8.49.0" + "@typescript-eslint/typescript-estree" "8.49.0" + "@typescript-eslint/utils" "8.49.0" + typescript-eslint@8.61.0: version "8.61.0" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.61.0.tgz#6927fb94f5f29623e370d33fd9fa61f15d6d996b"