Переглянути джерело

feat: expose showPrompt() on interface

Sv443 7 місяців тому
батько
коміт
b7182d20f6
4 змінених файлів з 60 додано та 15 видалено
  1. 2 1
      changelog.md
  2. 53 14
      contributing.md
  3. 2 0
      src/interface.ts
  4. 3 0
      src/types.ts

+ 2 - 1
changelog.md

@@ -63,9 +63,10 @@
   - Added new components:
     -  `createLongBtn()` to create a button with an icon and text (works either as normal or as a toggle button)  
       The design follows that of the subscribe button on YTM's channel pages, but the consistent class names make it easy to style it differently.
+    - `createRipple()` to create a click ripple animation effect on a given element (experimental)
     - `showToast()` to show a custom toast notification with a message string or element and duration
     - `showIconToast()` to show a custom toast notification with a message string or element, icon and duration
-    - `createRipple()` to create a click ripple animation effect on a given element (experimental)
+    - `showPrompt()` to show a styled prompt dialog that replaces the `confirm()` and `alert()` functions
     - `ExImDialog` class for creating a BytmDialog instance that is designed for exporting and importing generic data as a string
   - Changed components:
     - BytmDialog now has the option `removeListenersOnDestroy` (true by default) to configure removing all event listeners when the dialog is destroyed

+ 53 - 14
contributing.md

@@ -393,9 +393,10 @@ Functions marked with 🔒 need to be passed a per-session and per-plugin authen
   - [createToggleInput()](#createtoggleinput) - Creates a toggle input element
   - [createCircularBtn()](#createcircularbtn) - Creates a generic, circular button element with just an icon
   - [createLongBtn()](#createlongbtn) - Creates a generic, long and circular button element with an icon and text
+  - [createRipple()](#createripple) - Creates a click ripple effect on the given element
   - [showToast()](#showtoast) - Shows a toast notification and a message string or element
   - [showIconToast()](#showicontoast) - Shows a toast notification with an icon and a message string or element
-  - [createRipple()](#createripple) - Creates a click ripple effect on the given element
+  - [showPrompt()](#showprompt) - Shows a styled prompt of the type `confirm` or `alert`
 - Translations:
   - [setLocale()](#setlocale) 🔒 - Sets the locale for BetterYTM
   - [getLocale()](#getlocale) - Returns the currently set locale
@@ -1855,6 +1856,32 @@ Functions marked with 🔒 need to be passed a per-session and per-plugin authen
 
 <br>
 
+> #### createRipple()
+> Usages:  
+> ```ts
+> unsafeWindow.BYTM.createRipple<TElement>(rippleElement: TElement, props?: RippleProps): TElement
+> unsafeWindow.BYTM.createRipple(rippleElement?: undefined, props?: RippleProps): HTMLDivElement
+> ```
+>   
+> Creates a circular, expanding ripple effect on the specified element or creates a new one with the effect already applied if none is provided.  
+> Returns either the new element or the initially passed one.  
+> External CSS overrides can be used to change the color, size, speed values and opacity.  
+> The exact speed values and variable names and locations can be found in [`src/components/ripple.css`](./src/components/ripple.css)
+>   
+> Properties:  
+> - `speed?: string` - The speed of the ripple effect. Can be "faster", "fast", "normal", "slow" or "slower" (defaults to "normal")
+> 
+> <details><summary><b>Example <i>(click to expand)</i></b></summary>
+> 
+> ```ts
+> const myBoringButton = document.querySelector("#my-boring-button");
+> if(myBoringButton)
+>   unsafeWindow.BYTM.createRipple(myBoringButton, { speed: "slowest" }); // it's as easy as this
+> ```
+> </details>
+
+<br>
+
 > #### showToast()
 > Usages:  
 > ```ts
@@ -1933,27 +1960,39 @@ Functions marked with 🔒 need to be passed a per-session and per-plugin authen
 
 <br>
 
-> #### createRipple()
-> Usages:  
+> #### showPrompt()
+> Usage:  
 > ```ts
-> unsafeWindow.BYTM.createRipple<TElement>(rippleElement: TElement, props?: RippleProps): TElement
-> unsafeWindow.BYTM.createRipple(rippleElement?: undefined, props?: RippleProps): HTMLDivElement
+> unsafeWindow.BYTM.showPrompt(props: ShowPromptProps): Promise<boolean>
 > ```
 >   
-> Creates a circular, expanding ripple effect on the specified element or creates a new one with the effect already applied if none is provided.  
-> Returns either the new element or the initially passed one.  
-> External CSS overrides can be used to change the color, size, speed values and opacity.  
-> The exact speed values and variable names and locations can be found in [`src/components/ripple.css`](./src/components/ripple.css)
+> Shows a prompt dialog with the specified message and type.  
+> The user can choose between confirming or canceling the prompt.  
+> Closing the dialog counts as canceling.  
+> The Promise resolves with `true` if the user confirmed the prompt and `false` if they canceled it.  
+> The Promise always resolves with `true` when the type `alert` is used.  
 >   
 > Properties:  
-> - `speed?: string` - The speed of the ripple effect. Can be "faster", "fast", "normal", "slow" or "slower" (defaults to "normal")
-> 
+> - `message: string` - The message to show in the prompt
+> - `type?: "confirm" | "alert"` - The type of the prompt. Can be "confirm" or "alert" (default)
+>   
 > <details><summary><b>Example <i>(click to expand)</i></b></summary>
 > 
 > ```ts
-> const myBoringButton = document.querySelector("#my-boring-button");
-> if(myBoringButton)
->   unsafeWindow.BYTM.createRipple(myBoringButton, { speed: "slowest" }); // it's as easy as this
+> const confirmed = await unsafeWindow.BYTM.showPrompt({
+>   message: "Are you sure you want to delete this?",
+>   type: "confirm",
+> });
+>
+> if(confirmed) {
+>   await deleteSomething();
+>   unsafeWindow.BYTM.showPrompt({
+>     // uses type "alert" by default
+>     message: "Deleted successfully.",
+>   });
+> }
+> else
+>   console.log("The user canceled the prompt.");
 > ```
 > </details>
 

+ 2 - 0
src/interface.ts

@@ -8,6 +8,7 @@ import { autoLikeStore, featInfo, fetchLyricsUrlTop, getLyricsCacheEntry, saniti
 import { allSiteEvents, type SiteEventsMap } from "./siteEvents.js";
 import { LogLevel, type FeatureConfig, type FeatureInfo, type LyricsCacheEntry, type PluginDef, type PluginInfo, type PluginRegisterResult, type PluginDefResolvable, type PluginEventMap, type PluginItem, type BytmObject, type AutoLikeData, type InterfaceFunctions } from "./types.js";
 import { BytmDialog, ExImDialog, MarkdownDialog, createCircularBtn, createHotkeyInput, createRipple, createToggleInput, showIconToast, showToast } from "./components/index.js";
+import { showPrompt } from "./dialogs/prompt.js";
 
 const { getUnsafeWindow, randomId, NanoEmitter } = UserUtils;
 
@@ -159,6 +160,7 @@ const globalFuncs: InterfaceFunctions = {
   createRipple,
   showToast,
   showIconToast,
+  showPrompt,
 };
 
 /** Initializes the BYTM interface */

+ 3 - 0
src/types.ts

@@ -10,6 +10,7 @@ import type { InterfaceEventsMap, getAutoLikeDataInterface, getFeaturesInterface
 import type { BytmDialog, ExImDialog, createCircularBtn, createHotkeyInput, createRipple, createToggleInput, showIconToast, showToast } from "./components/index.js";
 import type { fetchLyricsUrlTop, sanitizeArtists, sanitizeSong } from "./features/lyrics.js";
 import type { getLyricsCacheEntry } from "./features/lyricsCache.js";
+import type { showPrompt } from "./dialogs/prompt.js";
 
 //#region other
 
@@ -350,6 +351,8 @@ export type InterfaceFunctions = {
   showToast: typeof showToast;
   /** Shows a toast with the provided text and an icon */
   showIconToast: typeof showIconToast;
+  /** Shows a styled confirm() or alert() dialog with the provided message */
+  showPrompt: typeof showPrompt;
 };
 
 //#region feature defs