### Installed Plugins Example Source: https://shelter.uwu.network/reference Provides an example of the structure returned by the `installedPlugins` signal, which is a record of installed Shelter plugins, including their JavaScript code, status, source URL, update status, and manifest. ```typescript installedPlugins() === { "yellowsink.github.io/shelter-plugins/antitrack/": { js: "...", on: true, src: "https://yellowsink.github.io/shelter-plugins/antitrack/", update: true, manifest: { author: "Yellowsink", description: "The essential.", hash: "2d8d76c008e0b37ed4e2eb1d9ea56a6d", name: "AntiTrack" } } } ``` -------------------------------- ### Full Shelter Plugin Example Source: https://shelter.uwu.network/guides/plugin A comprehensive example demonstrating how to subscribe to Flux events, observe DOM changes, and modify UI elements with mutexing. ```javascript const { GuildMemberStore, ChannelStore, SelectedChannelStore, RelationshipStore } = shelter.flux.storesFlat; const { util: { getFiber, reactFiberWalker }, observeDom } = shelter; const { subscribe } = shelter.plugin.scoped.flux; function handleElement(elem) { if (elem.dataset.showuname) return; elem.dataset.showuname = 1; const fiber = getFiber(elem); const message = reactFiberWalker(getFiber(elem), "message", true)?.pendingProps?.message; if (!message) return; const { type, guild_id } = ChannelStore.getChannel(message.channel_id); // type = 0 -> guild, type = 1 -> DM const nick = type ? RelationshipStore.getNickname(message.author_id) : GuildMemberStore.getNick(guild_id, message.author_id); if (!nick) return; elem.firstElementChild.textContent += ` (${message.author.username})`; } function handleDispatch(payload) { // only listen for message_create in the current channel if (payload.type === "MESSAGE_CREATE" && payload.channelId !== SelectedChannelStore.getChannelId() ) return; const unObserve = observeDom("[id^=message-username-]", (elem) => { handleElement(elem); unObserve(); }); setTimeout(unObserve, 500); } const triggers = ["MESSAGE_CREATE", "CHANNEL_SELECT", "LOAD_MESSAGES_SUCCESS", "UPDATE_CHANNEL_DIMENSIONS"]; for (const t of triggers) subscribe(t, handleDispatch); ``` -------------------------------- ### shelter.plugins.startPlugin Source: https://shelter.uwu.network/reference Starts an installed but unloaded plugin by its ID. ```APIDOC ## shelter.plugins.startPlugin ### Description Starts an installed but unloaded plugin. ### Method Signature ```typescript function startPlugin(id: string): void ``` ### Parameters * **id** (string) - The unique identifier of the plugin to start. ``` -------------------------------- ### Start a Plugin Source: https://shelter.uwu.network/reference Starts an installed but unloaded plugin by its ID. ```typescript function startPlugin(id: string): void ``` -------------------------------- ### Install Dependencies and Build Plugin Source: https://shelter.uwu.network/guides Install project dependencies, including Lune and type definitions, using npm. Then, run the Lune build command to compile your plugin. ```bash npm i npm lune ci ``` -------------------------------- ### Lune Configuration File Example Source: https://shelter.uwu.network/guides/lune Lune can be configured using `lune.config.js` or `lune.config.json`. This example demonstrates a JavaScript configuration file exporting an object with builder and minify options. ```javascript export default { builder: "esbuild", minify: true, cssModules: true } ``` -------------------------------- ### shelter.plugins.addRemotePlugin Source: https://shelter.uwu.network/reference Installs a plugin from a remote URL. ```APIDOC ## shelter.plugins.addRemotePlugin ### Description Installs a plugin from a provided URL. ### Method Signature ```typescript function addRemotePlugin(id: string, src: string, update = true): Promise ``` ### Parameters * **id** (string) - The unique identifier for the plugin. * **src** (string) - The URL from which to install the plugin. * **update** (boolean, optional) - Whether to update the plugin if it already exists. Defaults to true. ``` -------------------------------- ### Configuring SHELTER_INJECTOR_PLUGINS with Remote and Local Plugins Source: https://shelter.uwu.network/guides/injectors Example demonstrating how to configure the global `SHELTER_INJECTOR_PLUGINS` variable with both remote and local plugin definitions. Ensure `shelter` is evaluated after setting this global. ```javascript window.SHELTER_INJECTOR_PLUGINS = { // obviously in a client you're unlikely to use both remote and local together, but we do here for education purposes "myclient-settings": ["myclient://shelter-plugins/settings.js", { isVisible: false, allowedActions: {} }], "myclient-rpc": { js: MyClient.ShelterPlugins.Rpc.CodeText, manifest: { name: "MyClient RPC Fix", author: "MyClient Authors", description: "Provides Rich Presence support for MyClient" }, injectorIntegration: { isVisible: true, allowedActions: { toggle: true } } } }; (0, eval)(shelter); ``` -------------------------------- ### shelter.plugins.installedPlugins Source: https://shelter.uwu.network/reference `installedPlugins` is a Solid signal that returns the installed shelter plugins, as a `Record`. ```APIDOC ### `shelter.plugins.installedPlugins` `installedPlugins` is a Solid signal that returns the installed shelter plugins, as a `Record`. An example: ts``` installedPlugins() === { "yellowsink.github.io/shelter-plugins/antitrack/": { js: "...", on: true, src: "https://yellowsink.github.io/shelter-plugins/antitrack/", update: true, manifest: { author: "Yellowsink", description: "The essential.", hash: "2d8d76c008e0b37ed4e2eb1d9ea56a6d", name: "AntiTrack" } } } ``` ``` -------------------------------- ### CSS Modules Example Source: https://shelter.uwu.network/guides/lune When CSS Modules are enabled, import CSS files to get a `classes` object. The CSS is automatically injected and un-injected. This example shows how to import and use the `classes` object. ```css /* styles.css */ .btn { margin: 1rem; } ``` -------------------------------- ### Plugin Manifest Example Source: https://shelter.uwu.network/reference Shows the structure of the plugin manifest object, which contains metadata about the plugin such as its name, author, description, and hash. ```typescript // for example: plugin.manifest === { name: "Antitrack", author: "Yellowsink", description: "The essential.", hash: "2d8d76c008e0b37ed4e2eb1d9ea56a6d" } ``` -------------------------------- ### Add a Remote Plugin Source: https://shelter.uwu.network/reference Installs a plugin from a given URL. By default, it attempts to update the plugin if it already exists. ```typescript function addRemotePlugin(id: string, src: string, update = true): Promise ``` -------------------------------- ### Provide Injector Settings via Global (JavaScript) Source: https://shelter.uwu.network/guides/injectors Example of setting injector settings using a global variable. This method has limitations, such as not having direct access to SolidJS. The settings are reactive if a SolidJS accessor is provided. ```javascript window.SHELTER_INJECTOR_SETTINGS = [ ["divider"] ["header", "My Client"], ["section", "myclient_settings", "Settings", () => { // solidjs component here const [toggle, setToggle] = shelter.solid.createSignal(); // have fun without jsx i guess - thats the other of the flaws i mentioned return document.createElement("div"); } ], ["buttton", "myclient_clog", "Changelog", MyClient.ShowChangelogModal] ]; (0,eval)(shelter); ``` -------------------------------- ### Plugin Store Example Source: https://shelter.uwu.network/reference Demonstrates the usage of the plugin store for persisting data. Top-level properties modified on the store are automatically saved. Only serializable data types are allowed; functions are not permitted. ```typescript // run this one time... store.foo = 5; // then the next time your plugin loads: store.foo // 5 ``` -------------------------------- ### Await Shelter HTTP Ready Source: https://shelter.uwu.network/reference Ensure Shelter's HTTP functions are available by awaiting `shelter.http.ready` before making requests. This is recommended for `get`, `post`, `put`, `patch`, and `del`. ```typescript await shelter.http.ready; ``` -------------------------------- ### shelter.plugins.updatePlugin Source: https://shelter.uwu.network/reference Checks for and installs updates for a specified plugin. ```APIDOC ## shelter.plugins.updatePlugin ### Description Checks for an update for the specified plugin and installs it if available. Returns whether an update was installed. ### Method Signature ```typescript function updatePlugin(id: string): Promise ``` ### Parameters * **id** (string) - The unique identifier of the plugin to update. ### Returns * **Promise** - A promise that resolves to true if an update was installed, false otherwise. ``` -------------------------------- ### Clone Shelter Template Repository Source: https://shelter.uwu.network/guides Use degit to clone the Shelter template repository locally to start developing plugins. This sets up a monorepo structure with pre-configured build and CI scripts. ```bash npx degit uwu/shelter-template shelter-plugins ``` -------------------------------- ### Get Plugin Settings Component Source: https://shelter.uwu.network/reference Retrieves the Solid settings component for a plugin, if one is provided. Returns undefined if the plugin has no settings. ```typescript function getSettings(id: string): solid.Component | undefined ``` -------------------------------- ### shelter.http Methods (get, post, put, patch, del) Source: https://shelter.uwu.network/reference Provides access to Discord's internal HTTP functions for making authenticated requests. Use with caution as it carries a risk of selfbot-related bans. ```APIDOC ## shelter.http Methods ### Description Provides access to Discord's internal HTTP functions for making authenticated requests. Use with caution as it carries a risk of selfbot-related bans. These functions are intended for Discord endpoints only. ### Available Methods - `get(url | options)` - `post(url | options)` - `put(url | options)` - `patch(url | options)` - `del(url | options)` ### Parameters - **url** (string): The URL to make the request to. - **options** (object): An object containing request details. Refer to shelter typings for extensive description. ### Usage ```typescript await shelter.http.ready; // Example using URL string const response = await shelter.http.get("https://discord.com/api/v9/users/@me"); // Example using request object const postResponse = await shelter.http.post({ url: "https://discord.com/api/v9/channels/1234567890/messages", body: { content: "Hello from Shelter!" } }); ``` ### WARNING These are specifically for Discord endpoints only, not for anything else. Do not try to use these for general fetching. ``` -------------------------------- ### Conditionally Render UI Element Based on Setting Source: https://shelter.uwu.network/guides/settings Applies a setting to conditionally modify UI elements. This example shows adding a username with or without a fancy tag based on the 'fancyTag' store value. ```jsx if (store.fancyTag) elem.firstElementChild.append({message.author.username}); else elem.firstElementChild.textContent += ` (${message.author.username})`; ``` -------------------------------- ### shelter.plugins.getSettings Source: https://shelter.uwu.network/reference Retrieves the Solid settings component for a plugin, if available. ```APIDOC ## shelter.plugins.getSettings ### Description Retrieves the Solid settings component for a plugin, if the plugin provides one. ### Method Signature ```typescript function getSettings(id: string): solid.Component | undefined ``` ### Parameters * **id** (string) - The unique identifier of the plugin whose settings component is requested. ### Returns * **solid.Component | undefined** - The Solid component for the plugin's settings, or undefined if none exists. ``` -------------------------------- ### shelter.plugin.showSettings Source: https://shelter.uwu.network/reference `showSettings` imperatively shows the settings modal for your plugin, assuming you have settings. ```APIDOC ### `shelter.plugin.showSettings` ts``` function showSettings(): void ``` `showSettings` imperatively shows the settings modal for your plugin, assuming you have settings. ``` -------------------------------- ### shelter.plugins.showSettingsFor Source: https://shelter.uwu.network/reference Displays a settings modal for a plugin. ```APIDOC ## shelter.plugins.showSettingsFor ### Description Shows a settings modal for the plugin with the specified ID. The returned promise resolves when the modal is closed. ### Method Signature ```typescript function showSettingsFor(id: string): Promise ``` ### Parameters * **id** (string) - The unique identifier of the plugin for which to show settings. ``` -------------------------------- ### shelter.plugin.stopPlugin Source: https://shelter.uwu.network/reference Stops an installed and loaded plugin by its ID. ```APIDOC ## shelter.plugin.stopPlugin ### Description Stops an installed and loaded plugin. ### Method Signature ```typescript function stopPlugin(id: string): void ``` ### Parameters * **id** (string) - The unique identifier of the plugin to stop. ``` -------------------------------- ### initToasts Source: https://shelter.uwu.network/ui Sets up the necessary environment for toasts to function. Must be called if not using shelter. Returns a cleanup function. ```APIDOC ## `initToasts` standalone only ### Description Sets up necessary things for toasts to work. You must call this if you are using toasts and are not using shelter. Pass the element where toasts should be mounted. Returns a cleanup function. ### Type Signature ts ``` (mountPoint: HTMLElement) => () => void ``` ### Parameters - **mountPoint** (HTMLElement) - The DOM element where toasts will be mounted. ``` -------------------------------- ### Stop a Plugin Source: https://shelter.uwu.network/reference Stops an installed and loaded plugin by its ID. ```typescript function stopPlugin(id: string): void ``` -------------------------------- ### Get Discord-Style Scrollbar Class Source: https://shelter.uwu.network/ui A getter that returns a class name to apply to an element for Discord-style scrollbars. ```typescript () => string ``` ```jsx
``` -------------------------------- ### Initialize Plugin Store with Default Value Source: https://shelter.uwu.network/guides/settings Grabs the plugin store and sets a default value for a setting if it's the first run. The store behaves like a reactive object. ```javascript const { // other stuff ... plugin: { store } } = shelter; store.fancyTag ??= true; // set default ``` -------------------------------- ### Update a Plugin Source: https://shelter.uwu.network/reference Checks for an update for a given plugin ID. Returns true if an update was found and installed, false otherwise. ```typescript function updatePlugin(id: string): Promise ``` -------------------------------- ### Get React Props from DOM Node Source: https://shelter.uwu.network/reference Use shelter.util.getProps to access the React props associated with a given DOM node. ```typescript function getProps(node: DOMNode): any ``` -------------------------------- ### ReactiveRoot Source: https://shelter.uwu.network/ui Creates a Solid reactive root to ensure `onCleanup` works correctly and to fix certain reactivity bugs. It's recommended when inserting Solid elements directly into the document. ```APIDOC ## `` ### Description `ReactiveRoot` creates a solid reactive root, to ensure that `onCleanup` works, and fix some reactivity bugs. You won't always need it - for example inside of shelter settings and modals you won't need one, and if your elements do not have any lifecycle they might be fine, but if you're inserting solid elements directly into the document, and reactivity is being weird, wrap your inserted elements in one of these. ### Props - **children**: `JSX.Element` - The child elements to be rendered within the reactive root. ``` -------------------------------- ### Block HTTP Requests Source: https://shelter.uwu.network/guides/patterns Completely block outgoing HTTP requests. Use this to prevent specific requests from being sent, for example, 'science' events. ```javascript shelter.http.intercept("POST", "/science", () => {}); ``` -------------------------------- ### Configure Lune SSG in lune.config.js Source: https://shelter.uwu.network/guides/lune-ssg Configure repository name and base URL for static site generation. This helps in generating correct plugin links and naming the site. ```javascript import { defineConfig } from "@uwu/lune"; export default defineConfig({ ssg: { repo_name: "Name Here's Plugins", base_url: "https://your.site/shelter-plugins" } }); ``` -------------------------------- ### Get Channel Type and Nickname Source: https://shelter.uwu.network/guides/plugin Retrieve channel type and user nickname using Flux stores. Stops execution if no nickname is found. ```javascript const { type, guild_id } = ChannelStore.getChannel(message.channel_id); // type = 0 -> guild, type = 1 -> DM const nick = type ? RelationshipStore.getNickname(message.author_id) : GuildMemberStore.getNick(guild_id, message.author_id); if (!nick) return; ``` -------------------------------- ### Get Fiber from DOM Element Source: https://shelter.uwu.network/guides/plugin Obtain the React Fiber associated with a given DOM element. This is the first step in accessing richer data structures. ```javascript function handleElement(elem) { const fiber = getFiber(elem); } ``` -------------------------------- ### Show Settings Modal for Plugin Source: https://shelter.uwu.network/reference Displays a modal window for a plugin's settings. The returned promise resolves when the modal is closed. ```typescript function showSettingsFor(id: string): Promise ``` -------------------------------- ### Get React Fiber Owner Source: https://shelter.uwu.network/reference Retrieves the nearest React fiber owner instance from a DOM node or Fiber. Useful for accessing component-specific methods like `forceUpdate` after patching. ```typescript function getFiberOwner(node: DOMNode | Fiber): FiberOwner ``` -------------------------------- ### Initialize Toasts Source: https://shelter.uwu.network/ui Sets up the necessary environment for toasts to function. Must be called if using toasts outside of Shelter. Returns a cleanup function. ```typescript (mountPoint: HTMLElement) => () => void ``` -------------------------------- ### Create Reactive UI Elements with Shelter's html Tag Source: https://shelter.uwu.network/reference Use the html tagged template literal for JSX-like syntax to create SolidJS elements at runtime. Reactive values should be passed as no-element functions. Event handlers require an explicit argument. ```javascript const [count, setCount] = createSignal(); setInterval(() => setCount(count() + 1), 500); // html`` return html`
${() => count() * 2}
`; // JSX equivalent: // return
{count() * 2}
; ``` ```typescript // YES ⬇️ return html` `; // NO ⬇️ // return html` `; ``` -------------------------------- ### Create a Modal Dialog Source: https://shelter.uwu.network/ui Construct Discord-styled modals using ModalRoot, ModalHeader, ModalBody, and ModalFooter. The size can be adjusted using ModalSizes. ```jsx My cool modal Look mom! I'm on the shelter-ui modal! Uhhhhh idk this is the footer ig, its a good place for buttons! ``` -------------------------------- ### shelter.plugin.manifest Source: https://shelter.uwu.network/reference `manifest` contains the manifest object for your plugin. ```APIDOC ### `shelter.plugin.manifest` `manifest` contains the manifest object for your plugin. ts``` // for example: plugin.manifest === { name: "Antitrack", author: "Yellowsink", description: "The essential.", hash: "2d8d76c008e0b37ed4e2eb1d9ea56a6d" } ``` ``` -------------------------------- ### Implement Reactive UI Updates with SolidJS Source: https://shelter.uwu.network/guides/settings Rewrites the UI logic to leverage SolidJS's reactivity. It uses the 'Show' component to dynamically update the display based on the 'store.fancyTag' value, ensuring immediate UI changes when the setting is toggled. ```jsx // when you're putting non-trivial solid onto the page you should *ideally* create a reactive root // this is not necessary, and by all means test your code without them, but if you encounter bugs try adding one! const { SwitchItem, ReactiveRoot } = shelter.ui; import { Show } from "solid-js"; elem.firstElementChild.append( {message.author.username} ); ``` -------------------------------- ### Create a primary filled Button Source: https://shelter.uwu.network/ui The Button component is a versatile UI element. This example shows a default filled button with primary color. Customize `look`, `color`, `size`, and other props as needed. ```jsx ``` -------------------------------- ### Create a reactive root for SolidJS Source: https://shelter.uwu.network/ui Use `ReactiveRoot` to create a SolidJS reactive root. This is recommended when inserting Solid elements directly into the document to ensure `onCleanup` works correctly and to fix potential reactivity bugs. It is often not needed within existing Solid environments like settings or modals. ```jsx elem.append({/* ... */}); ``` -------------------------------- ### Render Default Text Component Source: https://shelter.uwu.network/ui Demonstrates the basic usage of the Text component with default settings. ```jsx Default text ``` -------------------------------- ### shelter.util.log Source: https://shelter.uwu.network/reference A wrapper around console logging functions that prepends a Shelter logo to the output, making logs easily identifiable. ```APIDOC ## shelter.util.log ### Description `log` is shelter's log function. It prints a pretty shelter logo before your logs! You may choose to use this to make your plugin's logs more identifiable. ### Method ```ts function log(text: any | any[], func: "log" | "warn" | "error" = "log"): void; ``` ### Parameters #### Path Parameters - **text** (any | any[]) - The message(s) to log. - **func** ("log" | "warn" | "error", optional) - The logging function to use. Defaults to "log". ``` -------------------------------- ### Get React Fiber from DOM Node Source: https://shelter.uwu.network/reference Use shelter.util.getFiber to retrieve a React fiber from a DOM node. This fiber contains information about the React element's state and can be used to extract data like message objects. ```typescript function getFiber(node: DOMNode): Fiber ``` -------------------------------- ### Traditional Injection Directory Structure Source: https://shelter.uwu.network/guides/injection Illustrates the directory structure before and after the traditional injection method. The injected structure includes an 'app' directory with modified entry points and the original asar file. ```tree 🗁 resources ├── 🗋 app.asar ├── 🗁 bootstrap └── 🗋 build_info.json ``` ```tree 🗁 resources ├── 🗁 app │ ├── 🗋 index.js │ ├── 🗋 preload.js │ └── 🗋 package.json ├── 🗁 bootstrap ├── 🗋 build_info.json └── 🗋 original.asar ``` -------------------------------- ### Create a Settings UI Component with a Switch Source: https://shelter.uwu.network/guides/settings Exposes a Solid component named 'settings' that renders a SwitchItem from shelter.ui. This allows users to toggle the 'fancyTag' setting. ```jsx const { SwitchItem } = shelter.ui; export const settings = () => ( {store.fancyTag = v}}> Use fancy looking tags ) ``` -------------------------------- ### Show Plugin Settings Modal Source: https://shelter.uwu.network/reference Imperatively displays the settings modal for a plugin, provided that the plugin has defined settings. ```typescript function showSettings(): void ``` -------------------------------- ### Setting up Flux Dispatch Listener Source: https://shelter.uwu.network/guides/plugin Set up a listener for specific Flux event types that indicate potential changes to the UI. This allows your plugin to react to events like new messages or channel selections. ```javascript function handleDispatch(payload) { } const triggers = ["MESSAGE_CREATE", "CHANNEL_SELECT", "LOAD_MESSAGES_SUCCESS", "UPDATE_CHANNEL_DIMENSIONS"]; for (const t of triggers) // the subscribe function we imported earlier subscribe(t, handleDispatch); ``` -------------------------------- ### shelter.http.ready Source: https://shelter.uwu.network/reference A Promise that resolves when the internal HTTP functions are available. It is recommended to await this before using HTTP methods. ```APIDOC ## shelter.http.ready ### Description A Promise that resolves when the internal HTTP functions are available. It is recommended to await this before using HTTP methods. ### Usage ```typescript await shelter.http.ready; // Now you can use shelter.http.get, shelter.http.post, etc. ``` ``` -------------------------------- ### Importing and Injecting CSS/Sass/Scss Source: https://shelter.uwu.network/guides/lune Import CSS, Sass, or SCSS files directly. The default export contains the compiled CSS as a string, ready to be injected using `shelter.ui.injectCss`. This is useful for applying styles to your plugin. ```javascript import styles from "./styles.css"; import sassStyles from "./moreStyles.sass"; import scssStyles from "./yetMore.scss"; const remove = shelter.ui.injectCss(styles); console.log(styles); // ".my-button { color: red; }" etc. ``` -------------------------------- ### Await Flux Store Initialization Source: https://shelter.uwu.network/reference Use `awaitStore` to safely access a Flux store, especially at plugin load, to avoid issues with stores not being initialized yet. The `name` parameter is case-sensitive. ```typescript function awaitStore(name: string, awaitInit = true): Promise ``` -------------------------------- ### Create a persistence helper for cleanup reinsertion Source: https://shelter.uwu.network/ui `createPersistenceHelper` provides a `` component to manage cleanup reinsertion. The `inject` function is re-run if the component is removed. Ensure `isPluginEnabled` is checked and handle cases where the parent element might be missing. ```jsx function MyComponent() { // ReactiveRoot optional but recommended if you // encounter any weird reactivity issues without it return (

My Header

) } const insertComponent = createPersistenceHelper((PersistenceHelper) => { // see warning below if (!isPluginEnabled) return; const parent = document.querySelector(`[class*="whatever"]`) parent?.append(, ) // you should still probably handle the case where `parent` is missing... }); ``` -------------------------------- ### shelter.plugin.flushStore Source: https://shelter.uwu.network/reference `flushStore` forces a save of the store if deep modifications were made. ```APIDOC ### `shelter.plugin.flushStore` ts``` function flushStore(): void ``` If you deeply modify something in the store, where it will not be automatically picked up (e.g. `store.foo.bar = "baz"`), you may call `flushStore()` to force a save. ``` -------------------------------- ### Provide Injector Settings via Function (JavaScript) Source: https://shelter.uwu.network/guides/injectors An alternative method to provide injector settings without polluting the global scope. This uses `new Function` to execute code that defines `SHELTER_INJECTOR_SECTIONS`. ```javascript new Function("SHELTER_INJECTOR_SECTIONS", shelter)([/*...*/]); ``` -------------------------------- ### shelter.solidH.html Source: https://shelter.uwu.network/reference A tagged template literal for creating SolidJS elements using JSX-like syntax at runtime. It supports reactive values and event handlers. ```APIDOC ## `shelter.solidH.html` This is a htm tagged template, that lets you use JSX-like syntax to create solid elements at runtime. To template using reactive values, you should pass them as no-element functions e.g.: ```javascript const [count, setCount] = createSignal(); setInterval(() => setCount(count() + 1), 500); // html`` return html`
${() => count() * 2}
`; // JSX equivalent: return
{count() * 2}
; ``` Note that you must also make sure you have the argument specified for event handlers, else they will be interpreted by solid's templater as a reactive value: ```typescript // YES ⬇️ return html` `; // NO ⬇️ return html` `; ``` Remember that this returns a function, which you call within a component to retreive the value, for reactivity reasons. ``` -------------------------------- ### shelter.util.storeAssign Source: https://shelter.uwu.network/reference A utility function similar to `Object.assign` but optimized for Solid reactive stores to minimize unnecessary reactive updates. ```APIDOC ## shelter.util.storeAssign ### Description `storeAssign` works precisely like `Object.assign`, but it is useful for using Solid reactive stores, as it will reduce extraneous reactive updates. ### Method ```ts function storeAssign(store: T, toApply: T): T ``` ### Parameters #### Path Parameters - **store** (T) - The target store. - **toApply** (T) - The properties to assign to the store. ``` -------------------------------- ### Open a confirmation modal Source: https://shelter.uwu.network/ui `openConfirmationModal` displays a pre-styled modal with configurable header, body, and buttons. It returns a promise that resolves when confirmed and rejects when canceled or closed. Use this for user confirmation actions. ```js openConfirmationModal({ header: () => "Are you sure????", body: () => "Really destroy your entire hard disk? You sure? What?", type: "danger", confirmText: "Yes, really.", cancelText: "Oh shoot!" }).then( () => console.log("let's delete!"), () => console.log("chicken.") ); ``` -------------------------------- ### Importing Shelter APIs Source: https://shelter.uwu.network/guides/plugin Import necessary APIs from the shelter global object for interacting with Discord's flux stores and utilities. These imports are essential for querying data and manipulating the DOM. ```javascript const { GuildMemberStore, ChannelStore, SelectedChannelStore, RelationshipStore } = shelter.flux.storesFlat; const { util: { getFiber, reactFiberWalker }, observeDom } = shelter; const { subscribe } = shelter.plugin.scoped.flux; ``` -------------------------------- ###
Source: https://shelter.uwu.network/ui Renders a header element with customizable tag, font weight, and margin. The `tag` prop determines the semantic HTML tag and visual style, while `weight` allows for font weight adjustments using `HeaderWeights`. The `margin` prop controls the bottom margin. ```APIDOC ##
### Description Renders a header element with customizable tag, font weight, and margin. The `tag` prop determines the semantic HTML tag and visual style, while `weight` allows for font weight adjustments using `HeaderWeights`. The `margin` prop controls the bottom margin. ### Props - **tag** (string) - Required - The semantic tag for the header (e.g., from `HeaderTags`). - **weight** (string) - Optional - The font weight, using values from `HeaderWeights`. Defaults to `semibold`. - **margin** (boolean) - Optional - Controls whether to include bottom margin. Defaults to `true`. - **children** (JSX.Element) - Required - The content of the header. - **class** (string) - Optional - CSS class for styling. - **id** (string) - Optional - ID for the header element. ### Usage Example ```jsx
My cool page
``` #### `HeaderTags` Enum: - `HeadingXXL`: A large header, suitable for main titles. - `HeadingXL`: A slightly smaller header. - `HeadingLG`: A smaller header, similar to section titles. - `HeadingMD`: Even smaller header. - `HeadingSM`: Small header. - `EYEBROW`: A descriptive phrase placed above a headline. #### `HeaderWeights` Enum: - `normal`: Normal weight (400). - `medium`: Medium weight (500). - `semibold`: Semi-bold weight (600, default). - `bold`: Bold weight (700). - `extrabold`: Extra bold weight (800). ``` -------------------------------- ### Render Styled Text Component Source: https://shelter.uwu.network/ui Shows how to use the Text component with custom tags and weights for different text styles. ```jsx Large bold text ``` ```jsx Medium display title ``` -------------------------------- ### createScopedApi Source: https://shelter.uwu.network/reference `createScopedApi` creates a copy of all reversible shelter APIs, that can be all undone at once. The returned object contains some but not all of the main shelter APIs, untouched. ```APIDOC ## `shelter.util.createScopedApi` ts``` function createScopedApi(): ScopedApi ``` `createScopedApi` creates a copy of all reversible shelter APIs, that can be all undone at once. The returned object contains some but not all of the main shelter APIs, untouched. The APIs returned are: * `shelter.flux.intercept` * `shelter.http.intercept` * `shelter.observeDom` * `shelter.patcher.*` * `shelter.settings.registerSection` * `shelter.ui.injectCss` In addition, these new APIs are returned. ts``` interface { disposeAllNow(): void; disposes: (() => void)[]; onDispose(callback: () => void): void; flux: { subscribe(type: string, cb: (payload: any) => void): () => void; } } ``` When any API on this object is called, its undo will be added automatically to the disposes array to be cleaned up. `subscribe` matches `shelter.flux.dispatcher.subscribe`, but returns the unsubscribe function. `disposes` is the array used to keep track of dispose callbacks. `onDispose` allows you to easily register your own callback to be disposed. `disposeAllNow` will call all dispose callbacks and clear the array. TIP Inside shelter plugins, you have a scoped API instance pre-provided under `shelter.plugin.scoped`. ``` -------------------------------- ### Inject CSS into the Plugin Scope Source: https://shelter.uwu.network/guides/settings Imports CSS from a file and injects it into the plugin's scope using shelter's UI tools. ```javascript import css from "./styles.css"; shelter.plugin.scoped.ui.injectCss(css); ``` -------------------------------- ### Private SHELTER_INJECTOR_PLUGINS Configuration Source: https://shelter.uwu.network/guides/injectors Alternative method to configure `SHELTER_INJECTOR_PLUGINS` privately using a new Function constructor, avoiding global scope pollution. The `shelter` argument is passed to the function. ```javascript new Function("SHELTER_INJECTOR_PLUGINS", shelter)({/*...*/}); ``` -------------------------------- ### shelter.util.createSubscription Source: https://shelter.uwu.network/reference Creates a Solid signal that derives its value from a Flux store. The signal updates whenever the specified data within the store changes. ```APIDOC ## shelter.util.createSubscription ### Description `createSubscription` creates a Solid signal that derives its value from a Flux store. This will update the value of the signal every time the data in the store changes. ### Method ```ts function createSubscription( store: FluxStore, getStateFromStore: (store: FluxStore) => TState ): solid.Accessor ``` ### Parameters #### Path Parameters - **store** (FluxStore) - The Flux store to subscribe to. - **getStateFromStore** ((store: FluxStore) => TState) - A function that extracts the desired state from the store. ### Example ```ts const userObj = createSubscription( stores.UserStore, (ustore) => ustore.getUser("1045796505535135855") ); // userObj() will be the most up to date user object for that user at any given point ``` ``` -------------------------------- ### shelter.plugins.addLocalPlugin Source: https://shelter.uwu.network/reference Adds a local plugin using its JavaScript source code and manifest object. ```APIDOC ## shelter.plugins.addLocalPlugin ### Description Adds a plugin from local JavaScript source code and a manifest object. ### Method Signature ```typescript function addLocalPlugin(id: string, plugin: { js: string, update: boolean, src?: string, manifest: Record }): void ``` ### Parameters * **id** (string) - The unique identifier for the plugin. * **plugin** (object) - An object containing the plugin's code and manifest. * **js** (string) - The JavaScript source code of the plugin. * **update** (boolean) - Indicates if the plugin should be updated. * **src** (string, optional) - The source URL of the plugin. * **manifest** (Record) - The manifest object for the plugin. ``` -------------------------------- ### shelter.flux.storesFlat Source: https://shelter.uwu.network/reference Provides a flat object of Flux stores, exposing only the first store found by name and ignoring collisions. Useful when you only need one instance of a store. ```APIDOC ## shelter.flux.storesFlat ### Description Provides a flat object of Flux stores, exposing only the first store found by name and ignoring collisions. Useful when you only need one instance of a store. ### Usage Access directly like an object: `shelter.flux.storesFlat.storeName` ``` -------------------------------- ### shelter.solidH.h Source: https://shelter.uwu.network/reference The hyperscript function for creating SolidJS elements. It can be used for creating UI components, especially for in-console debugging or plugin development without a build tool. ```APIDOC ## `shelter.solidH.h` The hyperscript interface to SolidJS. Intended to help in-console debugging and writing plugins without Lune. ### Signatures ```typescript function h(type: string | Component, ...children: (JSXElement | (() => JSXElement))[]): () => JSXElement; function h(type: string | Component, props: Record, ...children: (JSXElement | (() => JSXElement))[]): () => JSXElement; ``` ``` -------------------------------- ### shelter.plugin.store Source: https://shelter.uwu.network/reference `store` is a solid mutable store, which you can use to store persistent data. You may treat it just like an object. Whenever you modify a property on the store, it will be saved. ```APIDOC ### `shelter.plugin.store` `store` is a solid mutable store, which you can use to store persistent data. You may treat it just like an object. Whenever you modify a property on the store, it will be saved. (note this applies to only top level properties, not objects inside objects) You may store anything as long as it is serializable. The list of types allowed can be found here, circular references are not allowed. Notably, functions are not allowed. For example: ts``` // run this one time... store.foo = 5; // then the next time your plugin loads: store.foo // 5 ``` ``` -------------------------------- ### Injecting Solid JSX into DOM Source: https://shelter.uwu.network/guides/plugin Demonstrates how to append Solid JSX elements to an existing DOM element, facilitating reactive UI development. ```jsx someElement.appendChild(
Hi guys
); ``` -------------------------------- ### Plugin Settings UI Export Source: https://shelter.uwu.network/reference An optional export that provides a Solid component for the plugin's settings GUI. It should utilize Shelter's UI components. ```typescript function settings(): JSX.Element ``` -------------------------------- ### shelter.util.createListener Source: https://shelter.uwu.network/reference Creates a Solid signal that holds the most recent dispatch object of a specified type. Updates automatically when a relevant dispatch occurs. ```APIDOC ## shelter.util.createListener ### Description This creates a Solid signal that contains the most recent dispatch object of the given type. The signal will contain `undefined` initially, until a relevant dispatch happens. ### Method ```ts function createListener(type: string): solid.Accesssor ``` ### Parameters #### Path Parameters - **type** (string) - The type of dispatch to listen for. ``` -------------------------------- ### openConfirmationModal Source: https://shelter.uwu.network/ui Displays a pre-made modal with a header, body, and confirm/cancel buttons. Returns a promise that resolves on confirm or rejects on cancel/close. ```APIDOC ### `openConfirmationModal` #### Signature `({ body: solid.Component, header: solid.Component, confirmText?: string, cancelText?: string, type?: ModalTypes, size?: string }) => Promise` #### Description `openConfirmationModal` shows a premade modal with a header, body, and confirm and cancel buttons. It returns a promise that resolves on confirm, and rejects on cancel or close. #### Parameters - **header**: `solid.Component` - The component to render as the modal header. - **body**: `solid.Component` - The component to render as the modal body. - **confirmText?**: `string` - Text for the confirm button. - **cancelText?**: `string` - Text for the cancel button. - **type?**: `ModalTypes` - The type of the modal (e.g., 'danger'). - **size?**: `string` - The size of the modal. #### Example ```js openConfirmationModal({ header: () => "Are you sure????", body: () => "Really destroy your entire hard disk? You sure? What?", type: "danger", confirmText: "Yes, really.", cancelText: "Oh shoot!" }).then( () => console.log("let's delete!"), () => console.log("chicken.") ); ``` ``` -------------------------------- ### Modal Components Source: https://shelter.uwu.network/ui Components for creating Discord-styled modals, including a root container, header, body, and footer. ```APIDOC ## Modals ### `` #### Description The root component of a discord-styled modal. It wraps the header, body, and footer. #### Props - `size` (string, optional): The size of the modal, using values from `ModalSizes`. Defaults to `ModalSizes.SMALL`. - `children` (JSX.Element, optional): The content of the modal (header, body, footer). - `class` (string, optional): CSS class to apply to the modal root. - `style` (JSX.CSSProperties | string, optional): Inline styles to apply to the modal root. #### `ModalSizes` - `ModalSizes.SMALL`: 442px wide - `ModalSizes.MEDIUM`: 602px wide - `ModalSizes.LARGE`: 800px wide - `ModalSizes.DYNAMIC`: Fits content ### `` #### Description The header of a discord-styled modal. Can contain a title and a close button. #### Props - `noClose` (boolean, optional): If true, hides the close button. - `close` (function(): void, required): Function to call when the close button is clicked. - `children` (JSX.Element, optional): The content of the modal header. ### `` #### Description The body of a discord-styled modal. Provides styling for scrollbars and content. #### Props - `children` (JSX.Element, optional): The content of the modal body. ### `` #### Description The footer of a discord-styled modal, typically used for buttons. #### Props - `children` (JSX.Element, required): The content of the modal footer. ``` -------------------------------- ### shelter.plugin.scoped Source: https://shelter.uwu.network/reference A scoped API instance that cleans up automatically on unload. ```APIDOC ### `shelter.plugin.scoped` A scoped API instance that cleans up automatically on unload. ``` -------------------------------- ### Observe DOM Changes Continuously Source: https://shelter.uwu.network/guides/patterns Use this pattern for plugins that need to react to DOM changes without a specific trigger. It involves setting up a persistent DOM observer. Be aware that this can impact performance, though it's often negligible on modern systems. ```javascript function handleElement(e) { e.dataset.myPluginName = 1; const fiber = shelter.util.getFiber(e); // do whatever you want with the element here n stuff. } shelter.plugin.scoped.observeDom("whatever:not([data-my-plugin-name])", handleElement); ``` -------------------------------- ### Define CSS for Custom UI Elements Source: https://shelter.uwu.network/guides/settings Provides CSS styles for custom UI elements, such as the 'showuname-tag' class used for displaying usernames. ```css /* styles.css thx to wiz for styles btw */ .showuname-tag { font-weight: 600; border-radius: 5px; padding: 0 3px; background: var(--background-surface-highest); } ``` -------------------------------- ### createPersistenceHelper Source: https://shelter.uwu.network/ui A utility to manage component reinsertion using a `` component. It helps leverage the cleanup reinsertion pattern. ```APIDOC ### `createPersistenceHelper` #### Signature `createPersistenceHelper(inject: (PersistenceHelper: solid.Component) => T): () => T` #### Description `createPersistenceHelper` helps you take advantage of the cleanup reinsertion pattern, by giving you a `` component that you can place into the document as many times as you like, that will cause `inject` to be re-run if it gets removed. #### Example ```jsx function MyComponent() { // ReactiveRoot optional but recommended if you // encounter any weird reactivity issues without it return (

My Header

) } const insertComponent = createPersistenceHelper((PersistenceHelper) => { // see warning below if (!isPluginEnabled) return; const parent = document.querySelector(`[class*="whatever"]`) parent?.append(, ) // you should still probably handle the case where `parent` is missing... }); ``` ``` -------------------------------- ### injectInternalStyles Source: https://shelter.uwu.network/ui Inserts internal shelter-ui styles onto the page. Should only be called once. Use in Shadow DOM contexts requires the `` component instead. ```APIDOC ## `injectInternalStyles` standalone only ### Description Inserts internal shelter-ui styles onto the page. If you are not using shelter and do not call this, components will be unstyled. Only call this once. You should use `injectInternalStyles()` if you are using shelter-ui in the main document, and you should inject `` in style-isolated contexts like Shadow DOMs. ### Type Signature ts ``` () => void ``` ```