@mostfeatured/dbi 0.1.46 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/DBI.d.ts.map +1 -0
- package/dist/src/DBI.js.map +1 -0
- package/dist/src/Events.d.ts.map +1 -0
- package/dist/src/Events.js.map +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/methods/handleMessageCommands.d.ts.map +1 -0
- package/dist/src/methods/handleMessageCommands.js.map +1 -0
- package/dist/src/methods/hookEventListeners.d.ts.map +1 -0
- package/dist/src/methods/hookEventListeners.js.map +1 -0
- package/dist/src/methods/hookInteractionListeners.d.ts.map +1 -0
- package/dist/{methods → src/methods}/hookInteractionListeners.js +22 -12
- package/dist/src/methods/hookInteractionListeners.js.map +1 -0
- package/dist/src/methods/publishInteractions.d.ts.map +1 -0
- package/dist/src/methods/publishInteractions.js.map +1 -0
- package/dist/src/types/ApplicationRoleConnectionMetadata.d.ts.map +1 -0
- package/dist/src/types/ApplicationRoleConnectionMetadata.js.map +1 -0
- package/dist/src/types/Builders/ButtonBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/ButtonBuilder.js.map +1 -0
- package/dist/src/types/Builders/ChannelSelectMenuBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/ChannelSelectMenuBuilder.js.map +1 -0
- package/dist/src/types/Builders/MentionableSelectMenuBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/MentionableSelectMenuBuilder.js.map +1 -0
- package/dist/src/types/Builders/ModalBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/ModalBuilder.js.map +1 -0
- package/dist/src/types/Builders/RoleSelectMenuBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/RoleSelectMenuBuilder.js.map +1 -0
- package/dist/src/types/Builders/StringSelectMenuBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/StringSelectMenuBuilder.js.map +1 -0
- package/dist/src/types/Builders/UserSelectMenuBuilder.d.ts.map +1 -0
- package/dist/src/types/Builders/UserSelectMenuBuilder.js.map +1 -0
- package/dist/src/types/ChatInput/ChatInput.d.ts.map +1 -0
- package/dist/src/types/ChatInput/ChatInput.js.map +1 -0
- package/dist/{types → src/types}/ChatInput/ChatInputOptions.d.ts +2 -2
- package/dist/src/types/ChatInput/ChatInputOptions.d.ts.map +1 -0
- package/dist/src/types/ChatInput/ChatInputOptions.js.map +1 -0
- package/dist/src/types/Components/Button.d.ts.map +1 -0
- package/dist/src/types/Components/Button.js.map +1 -0
- package/dist/src/types/Components/ChannelSelectMenu.d.ts.map +1 -0
- package/dist/src/types/Components/ChannelSelectMenu.js.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.d.ts.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.js.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/index.d.ts +91 -0
- package/dist/src/types/Components/HTMLComponentsV2/index.d.ts.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/index.js +300 -0
- package/dist/src/types/Components/HTMLComponentsV2/index.js.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/parser.d.ts.map +1 -0
- package/dist/{types → src/types}/Components/HTMLComponentsV2/parser.js +11 -4
- package/dist/src/types/Components/HTMLComponentsV2/parser.js.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts +35 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js +822 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts +24 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts.map +1 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js +294 -0
- package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js.map +1 -0
- package/dist/src/types/Components/MentionableSelectMenu.d.ts.map +1 -0
- package/dist/src/types/Components/MentionableSelectMenu.js.map +1 -0
- package/dist/src/types/Components/Modal.d.ts.map +1 -0
- package/dist/src/types/Components/Modal.js.map +1 -0
- package/dist/src/types/Components/RoleSelectMenu.d.ts.map +1 -0
- package/dist/src/types/Components/RoleSelectMenu.js.map +1 -0
- package/dist/src/types/Components/StringSelectMenu.d.ts.map +1 -0
- package/dist/src/types/Components/StringSelectMenu.js.map +1 -0
- package/dist/src/types/Components/UserSelectMenu.d.ts.map +1 -0
- package/dist/src/types/Components/UserSelectMenu.js.map +1 -0
- package/dist/src/types/Event.d.ts.map +1 -0
- package/dist/src/types/Event.js.map +1 -0
- package/dist/src/types/Interaction.d.ts.map +1 -0
- package/dist/src/types/Interaction.js.map +1 -0
- package/dist/src/types/other/CustomEvent.d.ts.map +1 -0
- package/dist/src/types/other/CustomEvent.js.map +1 -0
- package/dist/src/types/other/FakeMessageInteraction.d.ts.map +1 -0
- package/dist/src/types/other/FakeMessageInteraction.js.map +1 -0
- package/dist/src/types/other/InteractionLocale.d.ts.map +1 -0
- package/dist/src/types/other/InteractionLocale.js.map +1 -0
- package/dist/src/types/other/Locale.d.ts.map +1 -0
- package/dist/src/types/other/Locale.js.map +1 -0
- package/dist/src/types/other/MessageContextMenu.d.ts.map +1 -0
- package/dist/src/types/other/MessageContextMenu.js.map +1 -0
- package/dist/src/types/other/UserContextMenu.d.ts.map +1 -0
- package/dist/src/types/other/UserContextMenu.js.map +1 -0
- package/dist/src/utils/MemoryStore.d.ts.map +1 -0
- package/dist/src/utils/MemoryStore.js.map +1 -0
- package/dist/src/utils/UtilTypes.d.ts.map +1 -0
- package/dist/src/utils/UtilTypes.js.map +1 -0
- package/dist/src/utils/customId.d.ts.map +1 -0
- package/dist/src/utils/customId.js.map +1 -0
- package/dist/src/utils/permissions.d.ts.map +1 -0
- package/dist/src/utils/permissions.js.map +1 -0
- package/dist/src/utils/recursiveImport.d.ts.map +1 -0
- package/dist/src/utils/recursiveImport.js.map +1 -0
- package/dist/src/utils/recursiveUnload.d.ts.map +1 -0
- package/dist/src/utils/recursiveUnload.js.map +1 -0
- package/dist/src/utils/unloadModule.d.ts.map +1 -0
- package/dist/src/utils/unloadModule.js.map +1 -0
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +103 -0
- package/dist/test/index.js.map +1 -0
- package/docs/ADVANCED_FEATURES.md +836 -0
- package/docs/API_REFERENCE.md +925 -0
- package/docs/CHAT_INPUT.md +807 -0
- package/docs/COMPONENTS.md +1035 -0
- package/docs/EVENTS.md +564 -0
- package/docs/GETTING_STARTED.md +394 -0
- package/docs/LOCALIZATION.md +773 -0
- package/docs/README.md +341 -0
- package/docs/SVELTE_COMPONENTS.md +955 -0
- package/generated/globals.d.ts +1 -0
- package/generated/index.d.ts +30 -0
- package/generated/svelte-dbi.d.ts +588 -0
- package/package.json +57 -47
- package/readme.md +168 -491
- package/src/methods/hookInteractionListeners.ts +23 -12
- package/src/types/Components/HTMLComponentsV2/index.ts +353 -12
- package/src/types/Components/HTMLComponentsV2/parser.ts +14 -4
- package/src/types/Components/HTMLComponentsV2/svelteParser.ts +904 -0
- package/src/types/Components/HTMLComponentsV2/svelteRenderer.ts +332 -0
- package/test/index.ts +105 -0
- package/test/product-showcase.svelte +199 -0
- package/tsconfig.json +13 -3
- package/dist/DBI.d.ts.map +0 -1
- package/dist/DBI.js.map +0 -1
- package/dist/Events.d.ts.map +0 -1
- package/dist/Events.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/methods/handleMessageCommands.d.ts.map +0 -1
- package/dist/methods/handleMessageCommands.js.map +0 -1
- package/dist/methods/hookEventListeners.d.ts.map +0 -1
- package/dist/methods/hookEventListeners.js.map +0 -1
- package/dist/methods/hookInteractionListeners.d.ts.map +0 -1
- package/dist/methods/hookInteractionListeners.js.map +0 -1
- package/dist/methods/publishInteractions.d.ts.map +0 -1
- package/dist/methods/publishInteractions.js.map +0 -1
- package/dist/types/ApplicationRoleConnectionMetadata.d.ts.map +0 -1
- package/dist/types/ApplicationRoleConnectionMetadata.js.map +0 -1
- package/dist/types/Builders/ButtonBuilder.d.ts.map +0 -1
- package/dist/types/Builders/ButtonBuilder.js.map +0 -1
- package/dist/types/Builders/ChannelSelectMenuBuilder.d.ts.map +0 -1
- package/dist/types/Builders/ChannelSelectMenuBuilder.js.map +0 -1
- package/dist/types/Builders/MentionableSelectMenuBuilder.d.ts.map +0 -1
- package/dist/types/Builders/MentionableSelectMenuBuilder.js.map +0 -1
- package/dist/types/Builders/ModalBuilder.d.ts.map +0 -1
- package/dist/types/Builders/ModalBuilder.js.map +0 -1
- package/dist/types/Builders/RoleSelectMenuBuilder.d.ts.map +0 -1
- package/dist/types/Builders/RoleSelectMenuBuilder.js.map +0 -1
- package/dist/types/Builders/StringSelectMenuBuilder.d.ts.map +0 -1
- package/dist/types/Builders/StringSelectMenuBuilder.js.map +0 -1
- package/dist/types/Builders/UserSelectMenuBuilder.d.ts.map +0 -1
- package/dist/types/Builders/UserSelectMenuBuilder.js.map +0 -1
- package/dist/types/ChatInput/ChatInput.d.ts.map +0 -1
- package/dist/types/ChatInput/ChatInput.js.map +0 -1
- package/dist/types/ChatInput/ChatInputOptions.d.ts.map +0 -1
- package/dist/types/ChatInput/ChatInputOptions.js.map +0 -1
- package/dist/types/Components/Button.d.ts.map +0 -1
- package/dist/types/Components/Button.js.map +0 -1
- package/dist/types/Components/ChannelSelectMenu.d.ts.map +0 -1
- package/dist/types/Components/ChannelSelectMenu.js.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.d.ts.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.js.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/index.d.ts +0 -19
- package/dist/types/Components/HTMLComponentsV2/index.d.ts.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/index.js +0 -31
- package/dist/types/Components/HTMLComponentsV2/index.js.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/parser.d.ts.map +0 -1
- package/dist/types/Components/HTMLComponentsV2/parser.js.map +0 -1
- package/dist/types/Components/MentionableSelectMenu.d.ts.map +0 -1
- package/dist/types/Components/MentionableSelectMenu.js.map +0 -1
- package/dist/types/Components/Modal.d.ts.map +0 -1
- package/dist/types/Components/Modal.js.map +0 -1
- package/dist/types/Components/RoleSelectMenu.d.ts.map +0 -1
- package/dist/types/Components/RoleSelectMenu.js.map +0 -1
- package/dist/types/Components/StringSelectMenu.d.ts.map +0 -1
- package/dist/types/Components/StringSelectMenu.js.map +0 -1
- package/dist/types/Components/UserSelectMenu.d.ts.map +0 -1
- package/dist/types/Components/UserSelectMenu.js.map +0 -1
- package/dist/types/Event.d.ts.map +0 -1
- package/dist/types/Event.js.map +0 -1
- package/dist/types/Interaction.d.ts.map +0 -1
- package/dist/types/Interaction.js.map +0 -1
- package/dist/types/other/CustomEvent.d.ts.map +0 -1
- package/dist/types/other/CustomEvent.js.map +0 -1
- package/dist/types/other/FakeMessageInteraction.d.ts.map +0 -1
- package/dist/types/other/FakeMessageInteraction.js.map +0 -1
- package/dist/types/other/InteractionLocale.d.ts.map +0 -1
- package/dist/types/other/InteractionLocale.js.map +0 -1
- package/dist/types/other/Locale.d.ts.map +0 -1
- package/dist/types/other/Locale.js.map +0 -1
- package/dist/types/other/MessageContextMenu.d.ts.map +0 -1
- package/dist/types/other/MessageContextMenu.js.map +0 -1
- package/dist/types/other/UserContextMenu.d.ts.map +0 -1
- package/dist/types/other/UserContextMenu.js.map +0 -1
- package/dist/utils/MemoryStore.d.ts.map +0 -1
- package/dist/utils/MemoryStore.js.map +0 -1
- package/dist/utils/UtilTypes.d.ts.map +0 -1
- package/dist/utils/UtilTypes.js.map +0 -1
- package/dist/utils/customId.d.ts.map +0 -1
- package/dist/utils/customId.js.map +0 -1
- package/dist/utils/permissions.d.ts.map +0 -1
- package/dist/utils/permissions.js.map +0 -1
- package/dist/utils/recursiveImport.d.ts.map +0 -1
- package/dist/utils/recursiveImport.js.map +0 -1
- package/dist/utils/recursiveUnload.d.ts.map +0 -1
- package/dist/utils/recursiveUnload.js.map +0 -1
- package/dist/utils/unloadModule.d.ts.map +0 -1
- package/dist/utils/unloadModule.js.map +0 -1
- package/examples/modal/dbi.js +0 -30
- package/examples/modal/login.js +0 -15
- package/examples/modal/package.json +0 -15
- package/examples/modal/publish.js +0 -13
- package/examples/modal/src/chatInput.js +0 -38
- package/examples/modal/src/components.js +0 -33
- package/examples/modal/src/event.js +0 -20
- package/examples/modal/src/interactionlocales.js +0 -24
- package/examples/modal/src/locales.js +0 -38
- package/examples/modal/src/modal.js +0 -28
- /package/dist/{DBI.d.ts → src/DBI.d.ts} +0 -0
- /package/dist/{DBI.js → src/DBI.js} +0 -0
- /package/dist/{Events.d.ts → src/Events.d.ts} +0 -0
- /package/dist/{Events.js → src/Events.js} +0 -0
- /package/dist/{data → src/data}/eventMap.json +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{methods → src/methods}/handleMessageCommands.d.ts +0 -0
- /package/dist/{methods → src/methods}/handleMessageCommands.js +0 -0
- /package/dist/{methods → src/methods}/hookEventListeners.d.ts +0 -0
- /package/dist/{methods → src/methods}/hookEventListeners.js +0 -0
- /package/dist/{methods → src/methods}/hookInteractionListeners.d.ts +0 -0
- /package/dist/{methods → src/methods}/publishInteractions.d.ts +0 -0
- /package/dist/{methods → src/methods}/publishInteractions.js +0 -0
- /package/dist/{types → src/types}/ApplicationRoleConnectionMetadata.d.ts +0 -0
- /package/dist/{types → src/types}/ApplicationRoleConnectionMetadata.js +0 -0
- /package/dist/{types → src/types}/Builders/ButtonBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/ButtonBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/ChannelSelectMenuBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/ChannelSelectMenuBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/MentionableSelectMenuBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/MentionableSelectMenuBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/ModalBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/ModalBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/RoleSelectMenuBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/RoleSelectMenuBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/StringSelectMenuBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/StringSelectMenuBuilder.js +0 -0
- /package/dist/{types → src/types}/Builders/UserSelectMenuBuilder.d.ts +0 -0
- /package/dist/{types → src/types}/Builders/UserSelectMenuBuilder.js +0 -0
- /package/dist/{types → src/types}/ChatInput/ChatInput.d.ts +0 -0
- /package/dist/{types → src/types}/ChatInput/ChatInput.js +0 -0
- /package/dist/{types → src/types}/ChatInput/ChatInputOptions.js +0 -0
- /package/dist/{types → src/types}/Components/Button.d.ts +0 -0
- /package/dist/{types → src/types}/Components/Button.js +0 -0
- /package/dist/{types → src/types}/Components/ChannelSelectMenu.d.ts +0 -0
- /package/dist/{types → src/types}/Components/ChannelSelectMenu.js +0 -0
- /package/dist/{types → src/types}/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.d.ts +0 -0
- /package/dist/{types → src/types}/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.js +0 -0
- /package/dist/{types → src/types}/Components/HTMLComponentsV2/parser.d.ts +0 -0
- /package/dist/{types → src/types}/Components/MentionableSelectMenu.d.ts +0 -0
- /package/dist/{types → src/types}/Components/MentionableSelectMenu.js +0 -0
- /package/dist/{types → src/types}/Components/Modal.d.ts +0 -0
- /package/dist/{types → src/types}/Components/Modal.js +0 -0
- /package/dist/{types → src/types}/Components/RoleSelectMenu.d.ts +0 -0
- /package/dist/{types → src/types}/Components/RoleSelectMenu.js +0 -0
- /package/dist/{types → src/types}/Components/StringSelectMenu.d.ts +0 -0
- /package/dist/{types → src/types}/Components/StringSelectMenu.js +0 -0
- /package/dist/{types → src/types}/Components/UserSelectMenu.d.ts +0 -0
- /package/dist/{types → src/types}/Components/UserSelectMenu.js +0 -0
- /package/dist/{types → src/types}/Event.d.ts +0 -0
- /package/dist/{types → src/types}/Event.js +0 -0
- /package/dist/{types → src/types}/Interaction.d.ts +0 -0
- /package/dist/{types → src/types}/Interaction.js +0 -0
- /package/dist/{types → src/types}/other/CustomEvent.d.ts +0 -0
- /package/dist/{types → src/types}/other/CustomEvent.js +0 -0
- /package/dist/{types → src/types}/other/FakeMessageInteraction.d.ts +0 -0
- /package/dist/{types → src/types}/other/FakeMessageInteraction.js +0 -0
- /package/dist/{types → src/types}/other/InteractionLocale.d.ts +0 -0
- /package/dist/{types → src/types}/other/InteractionLocale.js +0 -0
- /package/dist/{types → src/types}/other/Locale.d.ts +0 -0
- /package/dist/{types → src/types}/other/Locale.js +0 -0
- /package/dist/{types → src/types}/other/MessageContextMenu.d.ts +0 -0
- /package/dist/{types → src/types}/other/MessageContextMenu.js +0 -0
- /package/dist/{types → src/types}/other/UserContextMenu.d.ts +0 -0
- /package/dist/{types → src/types}/other/UserContextMenu.js +0 -0
- /package/dist/{utils → src/utils}/MemoryStore.d.ts +0 -0
- /package/dist/{utils → src/utils}/MemoryStore.js +0 -0
- /package/dist/{utils → src/utils}/UtilTypes.d.ts +0 -0
- /package/dist/{utils → src/utils}/UtilTypes.js +0 -0
- /package/dist/{utils → src/utils}/customId.d.ts +0 -0
- /package/dist/{utils → src/utils}/customId.js +0 -0
- /package/dist/{utils → src/utils}/permissions.d.ts +0 -0
- /package/dist/{utils → src/utils}/permissions.js +0 -0
- /package/dist/{utils → src/utils}/recursiveImport.d.ts +0 -0
- /package/dist/{utils → src/utils}/recursiveImport.js +0 -0
- /package/dist/{utils → src/utils}/recursiveUnload.d.ts +0 -0
- /package/dist/{utils → src/utils}/recursiveUnload.js +0 -0
- /package/dist/{utils → src/utils}/unloadModule.d.ts +0 -0
- /package/dist/{utils → src/utils}/unloadModule.js +0 -0
|
@@ -0,0 +1,955 @@
|
|
|
1
|
+
# DBI Svelte Components System
|
|
2
|
+
|
|
3
|
+
DBI provides a powerful Svelte 5-based component system for building interactive Discord UI with **Components V2**. This system brings modern reactive programming patterns to Discord bot development, allowing you to create dynamic, stateful interfaces with minimal boilerplate.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Component Structure](#component-structure)
|
|
10
|
+
- [Props and Reactivity](#props-and-reactivity)
|
|
11
|
+
- [Lifecycle Hooks](#lifecycle-hooks)
|
|
12
|
+
- [Render Helpers](#render-helpers)
|
|
13
|
+
- [HTML Elements Reference](#html-elements-reference)
|
|
14
|
+
- [Handler Functions](#handler-functions)
|
|
15
|
+
- [Using External Modules](#using-external-modules)
|
|
16
|
+
- [Type Definitions](#type-definitions)
|
|
17
|
+
- [Complete Example](#complete-example)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
The DBI Svelte component system provides:
|
|
24
|
+
|
|
25
|
+
- **Svelte 5 Syntax** - Use modern `$props()` runes and reactive patterns
|
|
26
|
+
- **Auto-Reactivity** - UI automatically updates when data changes
|
|
27
|
+
- **Lifecycle Hooks** - `onMount` and `onDestroy` for managing timers, intervals, cleanup
|
|
28
|
+
- **Throttled Rendering** - Built-in rate limiting to prevent Discord API abuse
|
|
29
|
+
- **Type Safety** - Full TypeScript support with autocomplete for Discord components
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### 1. Register a Svelte Component
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { createDBI } from "@mostfeatured/dbi";
|
|
39
|
+
import path from "path";
|
|
40
|
+
|
|
41
|
+
const dbi = createDBI("my-bot", { /* config */ });
|
|
42
|
+
|
|
43
|
+
dbi.register(({ HTMLComponentsV2 }) => {
|
|
44
|
+
HTMLComponentsV2({
|
|
45
|
+
name: "my-component",
|
|
46
|
+
mode: "svelte",
|
|
47
|
+
file: path.join(__dirname, "my-component.svelte"),
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Create the Svelte File
|
|
53
|
+
|
|
54
|
+
```svelte
|
|
55
|
+
<script>
|
|
56
|
+
let { count = 0 } = $props();
|
|
57
|
+
|
|
58
|
+
function increment() {
|
|
59
|
+
data.count++;
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<components>
|
|
64
|
+
<text-display>Count: {count}</text-display>
|
|
65
|
+
<action-row>
|
|
66
|
+
<button style="Primary" handler={increment}>+1</button>
|
|
67
|
+
</action-row>
|
|
68
|
+
</components>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Send the Component
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
ChatInput({
|
|
75
|
+
name: "counter",
|
|
76
|
+
description: "Interactive counter",
|
|
77
|
+
async onExecute({ interaction, dbi }) {
|
|
78
|
+
const component = dbi.interaction("my-component");
|
|
79
|
+
|
|
80
|
+
await component.send(interaction, {
|
|
81
|
+
data: { count: 0 }
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Component Structure
|
|
90
|
+
|
|
91
|
+
A DBI Svelte component consists of two main parts:
|
|
92
|
+
|
|
93
|
+
### Script Block
|
|
94
|
+
|
|
95
|
+
Contains your reactive state, handler functions, and lifecycle hooks.
|
|
96
|
+
|
|
97
|
+
```svelte
|
|
98
|
+
<script>
|
|
99
|
+
// Type reference for IDE support
|
|
100
|
+
/// <reference types="@mostfeatured/dbi/svelte" />
|
|
101
|
+
|
|
102
|
+
// Import external modules
|
|
103
|
+
import stuffs from "stuffs";
|
|
104
|
+
|
|
105
|
+
// Declare props with Svelte 5 $props() rune
|
|
106
|
+
let {
|
|
107
|
+
products = [],
|
|
108
|
+
currentIndex = 0,
|
|
109
|
+
cart = [],
|
|
110
|
+
view = "browse",
|
|
111
|
+
} = $props();
|
|
112
|
+
|
|
113
|
+
// Handler functions (automatically bound to buttons/selects)
|
|
114
|
+
function nextProduct() {
|
|
115
|
+
data.currentIndex = (currentIndex + 1) % products.length;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function addToCart(ctx) {
|
|
119
|
+
const product = products[currentIndex];
|
|
120
|
+
data.cart = [...cart, product];
|
|
121
|
+
ctx.interaction.reply({
|
|
122
|
+
content: "Added to cart!",
|
|
123
|
+
flags: ["Ephemeral"],
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Lifecycle
|
|
128
|
+
onMount(() => {
|
|
129
|
+
const interval = setInterval(() => {
|
|
130
|
+
data.elapsedTime += 1;
|
|
131
|
+
}, 1000);
|
|
132
|
+
|
|
133
|
+
return () => clearInterval(interval); // Cleanup
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Template Block
|
|
139
|
+
|
|
140
|
+
Contains your Discord UI components wrapped in `<components>`.
|
|
141
|
+
|
|
142
|
+
```svelte
|
|
143
|
+
<components>
|
|
144
|
+
<container accent-color="5865F2">
|
|
145
|
+
<components>
|
|
146
|
+
<text-display>## Welcome!</text-display>
|
|
147
|
+
<action-row>
|
|
148
|
+
<button style="Primary" handler={nextProduct}>Next</button>
|
|
149
|
+
</action-row>
|
|
150
|
+
</components>
|
|
151
|
+
</container>
|
|
152
|
+
</components>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Props and Reactivity
|
|
158
|
+
|
|
159
|
+
### Declaring Props
|
|
160
|
+
|
|
161
|
+
Use Svelte 5's `$props()` rune to declare component props with default values:
|
|
162
|
+
|
|
163
|
+
```svelte
|
|
164
|
+
<script>
|
|
165
|
+
let {
|
|
166
|
+
count = 0,
|
|
167
|
+
items = [],
|
|
168
|
+
settings = { theme: "dark" },
|
|
169
|
+
} = $props();
|
|
170
|
+
</script>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### The `data` Object
|
|
174
|
+
|
|
175
|
+
Inside handlers, use the global `data` object to update state. Changes automatically trigger re-renders:
|
|
176
|
+
|
|
177
|
+
```svelte
|
|
178
|
+
<script>
|
|
179
|
+
let { count = 0 } = $props();
|
|
180
|
+
|
|
181
|
+
function increment() {
|
|
182
|
+
// Use 'data' to update - triggers auto-render
|
|
183
|
+
data.count++;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function reset() {
|
|
187
|
+
data.count = 0;
|
|
188
|
+
}
|
|
189
|
+
</script>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Reactive Updates
|
|
193
|
+
|
|
194
|
+
The `data` object is wrapped in a Proxy that:
|
|
195
|
+
|
|
196
|
+
1. Detects property changes
|
|
197
|
+
2. Automatically re-renders the component
|
|
198
|
+
3. Throttles updates (default: 250ms minimum between renders)
|
|
199
|
+
|
|
200
|
+
```svelte
|
|
201
|
+
<script>
|
|
202
|
+
let { items = [] } = $props();
|
|
203
|
+
|
|
204
|
+
function addItem(ctx) {
|
|
205
|
+
// Arrays must be reassigned to trigger reactivity
|
|
206
|
+
data.items = [...items, { name: "New Item" }];
|
|
207
|
+
}
|
|
208
|
+
</script>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Lifecycle Hooks
|
|
214
|
+
|
|
215
|
+
### onMount
|
|
216
|
+
|
|
217
|
+
Runs when the component is first sent. Perfect for setting up timers, intervals, or fetching data.
|
|
218
|
+
|
|
219
|
+
```svelte
|
|
220
|
+
<script>
|
|
221
|
+
let { seconds = 0 } = $props();
|
|
222
|
+
|
|
223
|
+
onMount(() => {
|
|
224
|
+
console.log("Component mounted!");
|
|
225
|
+
|
|
226
|
+
// Start a timer
|
|
227
|
+
const interval = setInterval(() => {
|
|
228
|
+
data.seconds++;
|
|
229
|
+
}, 1000);
|
|
230
|
+
|
|
231
|
+
// Return cleanup function (optional)
|
|
232
|
+
return () => {
|
|
233
|
+
clearInterval(interval);
|
|
234
|
+
console.log("Timer cleared!");
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
</script>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### onDestroy
|
|
241
|
+
|
|
242
|
+
Runs when the component is destroyed (via `$unRef` or manual `destroy()` call).
|
|
243
|
+
|
|
244
|
+
```svelte
|
|
245
|
+
<script>
|
|
246
|
+
let timer;
|
|
247
|
+
|
|
248
|
+
onMount(() => {
|
|
249
|
+
timer = setInterval(() => data.count++, 1000);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
onDestroy(() => {
|
|
253
|
+
clearInterval(timer);
|
|
254
|
+
console.log("Component destroyed, cleanup complete!");
|
|
255
|
+
});
|
|
256
|
+
</script>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Manual Destruction
|
|
260
|
+
|
|
261
|
+
Call `destroy()` from any handler to manually clean up:
|
|
262
|
+
|
|
263
|
+
```svelte
|
|
264
|
+
<script>
|
|
265
|
+
function handleClose() {
|
|
266
|
+
destroy(); // Runs onDestroy callbacks, removes ref
|
|
267
|
+
}
|
|
268
|
+
</script>
|
|
269
|
+
|
|
270
|
+
<components>
|
|
271
|
+
<action-row>
|
|
272
|
+
<button style="Danger" handler={handleClose}>Close</button>
|
|
273
|
+
</action-row>
|
|
274
|
+
</components>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Render Helpers
|
|
280
|
+
|
|
281
|
+
### render()
|
|
282
|
+
|
|
283
|
+
Force an immediate render of the component:
|
|
284
|
+
|
|
285
|
+
```svelte
|
|
286
|
+
<script>
|
|
287
|
+
function forceUpdate() {
|
|
288
|
+
data.value = computeExpensiveValue();
|
|
289
|
+
render(); // Force immediate render
|
|
290
|
+
}
|
|
291
|
+
</script>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### update()
|
|
295
|
+
|
|
296
|
+
Update the message using `interaction.update()`. Best for button clicks:
|
|
297
|
+
|
|
298
|
+
```svelte
|
|
299
|
+
<script>
|
|
300
|
+
async function handleButton() {
|
|
301
|
+
data.count++;
|
|
302
|
+
await update(); // Uses interaction.update()
|
|
303
|
+
}
|
|
304
|
+
</script>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### rerender()
|
|
308
|
+
|
|
309
|
+
Re-render using `message.edit()`. Use after `reply()` or `followUp()`:
|
|
310
|
+
|
|
311
|
+
```svelte
|
|
312
|
+
<script>
|
|
313
|
+
async function processData(ctx) {
|
|
314
|
+
await ctx.interaction.reply({ content: "Processing..." });
|
|
315
|
+
|
|
316
|
+
data.result = await fetchData();
|
|
317
|
+
await rerender(); // Uses message.edit()
|
|
318
|
+
}
|
|
319
|
+
</script>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### noRender()
|
|
323
|
+
|
|
324
|
+
Disable auto-render for the current handler:
|
|
325
|
+
|
|
326
|
+
```svelte
|
|
327
|
+
<script>
|
|
328
|
+
function backgroundTask() {
|
|
329
|
+
noRender(); // Don't update UI
|
|
330
|
+
data.internalState = calculate(); // Won't trigger render
|
|
331
|
+
}
|
|
332
|
+
</script>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### setThrottle(ms)
|
|
336
|
+
|
|
337
|
+
Set minimum interval between renders:
|
|
338
|
+
|
|
339
|
+
```svelte
|
|
340
|
+
<script>
|
|
341
|
+
// For a timer that updates every second
|
|
342
|
+
setThrottle(1000);
|
|
343
|
+
|
|
344
|
+
onMount(() => {
|
|
345
|
+
setInterval(() => data.seconds++, 1000);
|
|
346
|
+
});
|
|
347
|
+
</script>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## HTML Elements Reference
|
|
353
|
+
|
|
354
|
+
### Layout Components
|
|
355
|
+
|
|
356
|
+
#### `<components>`
|
|
357
|
+
Root wrapper for all Discord components.
|
|
358
|
+
|
|
359
|
+
```svelte
|
|
360
|
+
<components>
|
|
361
|
+
<!-- Your components here -->
|
|
362
|
+
</components>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `<action-row>`
|
|
366
|
+
Container for buttons (max 5) or a single select menu.
|
|
367
|
+
|
|
368
|
+
```svelte
|
|
369
|
+
<action-row>
|
|
370
|
+
<button style="Primary">Click Me</button>
|
|
371
|
+
<button style="Secondary">Or Me</button>
|
|
372
|
+
</action-row>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### `<container>`
|
|
376
|
+
Colored container with optional accent color.
|
|
377
|
+
|
|
378
|
+
```svelte
|
|
379
|
+
<container accent-color="5865F2" spoiler>
|
|
380
|
+
<components>
|
|
381
|
+
<!-- Content -->
|
|
382
|
+
</components>
|
|
383
|
+
</container>
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
| Attribute | Type | Description |
|
|
387
|
+
|-----------|------|-------------|
|
|
388
|
+
| `accent-color` | string | Hex color (e.g., "5865F2", "#FF0000") |
|
|
389
|
+
| `spoiler` | boolean | Hide content behind spoiler |
|
|
390
|
+
|
|
391
|
+
#### `<section>`
|
|
392
|
+
Section with components and optional accessory (thumbnail/button).
|
|
393
|
+
|
|
394
|
+
```svelte
|
|
395
|
+
<section>
|
|
396
|
+
<components>
|
|
397
|
+
<text-display>Main content</text-display>
|
|
398
|
+
</components>
|
|
399
|
+
<thumbnail url="https://example.com/image.png"></thumbnail>
|
|
400
|
+
</section>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
#### `<separator>`
|
|
404
|
+
Visual divider between components.
|
|
405
|
+
|
|
406
|
+
```svelte
|
|
407
|
+
<separator divider spacing="2"></separator>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
| Attribute | Type | Description |
|
|
411
|
+
|-----------|------|-------------|
|
|
412
|
+
| `divider` | boolean | Show divider line |
|
|
413
|
+
| `spacing` | number | Spacing size (1-3) |
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
### Interactive Components
|
|
418
|
+
|
|
419
|
+
#### `<button>`
|
|
420
|
+
Discord button with various styles.
|
|
421
|
+
|
|
422
|
+
```svelte
|
|
423
|
+
<button
|
|
424
|
+
style="Primary"
|
|
425
|
+
emoji="🚀"
|
|
426
|
+
handler={handleClick}
|
|
427
|
+
disabled
|
|
428
|
+
>
|
|
429
|
+
Click Me
|
|
430
|
+
</button>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
| Attribute | Type | Description |
|
|
434
|
+
|-----------|------|-------------|
|
|
435
|
+
| `style` | "Primary" \| "Secondary" \| "Success" \| "Danger" \| "Link" \| "Premium" | Button style |
|
|
436
|
+
| `handler` | function | Handler function reference |
|
|
437
|
+
| `emoji` | string | Emoji to display |
|
|
438
|
+
| `disabled` | boolean | Disable the button |
|
|
439
|
+
| `url` | string | URL for Link style |
|
|
440
|
+
| `sku-id` | string | SKU ID for Premium style |
|
|
441
|
+
|
|
442
|
+
**Note:** You can also use `onclick` as an alias for `handler`.
|
|
443
|
+
|
|
444
|
+
#### `<string-select>`
|
|
445
|
+
Dropdown menu with custom options.
|
|
446
|
+
|
|
447
|
+
```svelte
|
|
448
|
+
<string-select
|
|
449
|
+
placeholder="Choose an option..."
|
|
450
|
+
min-values="1"
|
|
451
|
+
max-values="3"
|
|
452
|
+
handler={handleSelect}
|
|
453
|
+
>
|
|
454
|
+
<option value="a" description="First option" emoji="1️⃣" default>
|
|
455
|
+
Option A
|
|
456
|
+
</option>
|
|
457
|
+
<option value="b" description="Second option">
|
|
458
|
+
Option B
|
|
459
|
+
</option>
|
|
460
|
+
</string-select>
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
| Attribute | Type | Description |
|
|
464
|
+
|-----------|------|-------------|
|
|
465
|
+
| `placeholder` | string | Placeholder text |
|
|
466
|
+
| `min-values` | number | Minimum selections |
|
|
467
|
+
| `max-values` | number | Maximum selections |
|
|
468
|
+
| `handler` | function | Handler function |
|
|
469
|
+
| `disabled` | boolean | Disable the menu |
|
|
470
|
+
|
|
471
|
+
#### `<option>`
|
|
472
|
+
Option for select menus.
|
|
473
|
+
|
|
474
|
+
| Attribute | Type | Description |
|
|
475
|
+
|-----------|------|-------------|
|
|
476
|
+
| `value` | string | Value sent when selected |
|
|
477
|
+
| `description` | string | Description below label |
|
|
478
|
+
| `emoji` | string | Emoji to display |
|
|
479
|
+
| `default` | boolean | Selected by default |
|
|
480
|
+
|
|
481
|
+
#### Other Select Menus
|
|
482
|
+
|
|
483
|
+
```svelte
|
|
484
|
+
<user-select placeholder="Select users..." handler={handleUsers}></user-select>
|
|
485
|
+
<role-select placeholder="Select roles..." handler={handleRoles}></role-select>
|
|
486
|
+
<channel-select placeholder="Select channels..." handler={handleChannels}></channel-select>
|
|
487
|
+
<mentionable-select placeholder="Select users/roles..." handler={handleMentionables}></mentionable-select>
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
### Display Components
|
|
493
|
+
|
|
494
|
+
#### `<text-display>`
|
|
495
|
+
Renders markdown text.
|
|
496
|
+
|
|
497
|
+
```svelte
|
|
498
|
+
<text-display>
|
|
499
|
+
## Heading
|
|
500
|
+
**Bold** and *italic* text
|
|
501
|
+
|
|
502
|
+
- List item 1
|
|
503
|
+
- List item 2
|
|
504
|
+
</text-display>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
#### `<thumbnail>`
|
|
508
|
+
Thumbnail image for sections.
|
|
509
|
+
|
|
510
|
+
```svelte
|
|
511
|
+
<thumbnail url="https://example.com/image.png"></thumbnail>
|
|
512
|
+
<!-- or -->
|
|
513
|
+
<thumbnail media="https://example.com/image.png"></thumbnail>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
#### `<media-gallery>`
|
|
517
|
+
Gallery of images.
|
|
518
|
+
|
|
519
|
+
```svelte
|
|
520
|
+
<media-gallery>
|
|
521
|
+
<item url="https://example.com/1.png" description="Image 1"></item>
|
|
522
|
+
<item url="https://example.com/2.png" spoiler></item>
|
|
523
|
+
</media-gallery>
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
#### `<file>`
|
|
527
|
+
File attachment display.
|
|
528
|
+
|
|
529
|
+
```svelte
|
|
530
|
+
<file url="attachment://document.pdf" spoiler></file>
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
### Modal Components
|
|
536
|
+
|
|
537
|
+
#### `<text-input>`
|
|
538
|
+
Text input for modal forms.
|
|
539
|
+
|
|
540
|
+
```svelte
|
|
541
|
+
<text-input
|
|
542
|
+
id="username"
|
|
543
|
+
label="Username"
|
|
544
|
+
placeholder="Enter your username"
|
|
545
|
+
style="Short"
|
|
546
|
+
min-length="3"
|
|
547
|
+
max-length="32"
|
|
548
|
+
required
|
|
549
|
+
>Default value</text-input>
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
| Attribute | Type | Description |
|
|
553
|
+
|-----------|------|-------------|
|
|
554
|
+
| `id` / `custom-id` | string | Input identifier |
|
|
555
|
+
| `label` | string | Label above input |
|
|
556
|
+
| `placeholder` | string | Placeholder text |
|
|
557
|
+
| `style` | "Short" \| "Paragraph" | Input style |
|
|
558
|
+
| `min-length` | number | Minimum characters |
|
|
559
|
+
| `max-length` | number | Maximum characters |
|
|
560
|
+
| `required` | boolean | Is required |
|
|
561
|
+
| `value` | string | Default value |
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## Handler Functions
|
|
566
|
+
|
|
567
|
+
Handler functions receive a `ctx` object with the interaction context:
|
|
568
|
+
|
|
569
|
+
```svelte
|
|
570
|
+
<script>
|
|
571
|
+
function handleButton(ctx) {
|
|
572
|
+
// Access the Discord interaction
|
|
573
|
+
const { interaction } = ctx;
|
|
574
|
+
|
|
575
|
+
// Reply to the user
|
|
576
|
+
ctx.interaction.reply({
|
|
577
|
+
content: "Button clicked!",
|
|
578
|
+
flags: ["Ephemeral"],
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
// Access DBI instance
|
|
582
|
+
const { dbi } = ctx;
|
|
583
|
+
|
|
584
|
+
// Access locale helpers
|
|
585
|
+
const { locale } = ctx;
|
|
586
|
+
const text = locale.user("greeting");
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Handler without ctx - just updates data
|
|
590
|
+
function simpleHandler() {
|
|
591
|
+
data.count++;
|
|
592
|
+
// Auto-renders after handler completes
|
|
593
|
+
}
|
|
594
|
+
</script>
|
|
595
|
+
|
|
596
|
+
<components>
|
|
597
|
+
<action-row>
|
|
598
|
+
<button handler={handleButton}>With Context</button>
|
|
599
|
+
<button handler={simpleHandler}>Simple</button>
|
|
600
|
+
</action-row>
|
|
601
|
+
</components>
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Context Object
|
|
605
|
+
|
|
606
|
+
| Property | Type | Description |
|
|
607
|
+
|----------|------|-------------|
|
|
608
|
+
| `interaction` | ButtonInteraction / SelectMenuInteraction | Discord.js interaction |
|
|
609
|
+
| `dbi` | DBI | DBI instance |
|
|
610
|
+
| `locale` | object | Locale helpers (`user()`, `guild()`) |
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Using External Modules
|
|
615
|
+
|
|
616
|
+
You can import external modules in your Svelte scripts:
|
|
617
|
+
|
|
618
|
+
```svelte
|
|
619
|
+
<script>
|
|
620
|
+
import stuffs from "stuffs";
|
|
621
|
+
import lodash from "lodash";
|
|
622
|
+
import { someUtil } from "./utils";
|
|
623
|
+
|
|
624
|
+
function formatTime(seconds) {
|
|
625
|
+
return stuffs.formatSeconds(seconds);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
function sortItems() {
|
|
629
|
+
data.items = lodash.sortBy(items, "name");
|
|
630
|
+
}
|
|
631
|
+
</script>
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
Modules are loaded via `require()` at runtime, so they must be installed in your project.
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## Type Definitions
|
|
639
|
+
|
|
640
|
+
For full IDE support with autocomplete, add the type reference at the top of your script:
|
|
641
|
+
|
|
642
|
+
```svelte
|
|
643
|
+
<script>
|
|
644
|
+
/// <reference types="@mostfeatured/dbi/svelte" />
|
|
645
|
+
|
|
646
|
+
// Now you get autocomplete for:
|
|
647
|
+
// - render(), update(), rerender(), noRender(), setThrottle()
|
|
648
|
+
// - onMount(), onDestroy(), destroy()
|
|
649
|
+
// - ctx, data
|
|
650
|
+
// - All HTML elements (text-display, button, etc.)
|
|
651
|
+
</script>
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## Complete Example
|
|
657
|
+
|
|
658
|
+
Here's a complete example of a product showcase component:
|
|
659
|
+
|
|
660
|
+
### Registration (index.ts)
|
|
661
|
+
|
|
662
|
+
```typescript
|
|
663
|
+
import { createDBI } from "@mostfeatured/dbi";
|
|
664
|
+
import path from "path";
|
|
665
|
+
|
|
666
|
+
const dbi = createDBI("shop-bot", {
|
|
667
|
+
discord: {
|
|
668
|
+
token: process.env.DISCORD_TOKEN,
|
|
669
|
+
options: {
|
|
670
|
+
intents: ["GuildMessages", "Guilds"],
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
references: {
|
|
674
|
+
autoClear: {
|
|
675
|
+
ttl: 60000 * 60, // 60 minutes
|
|
676
|
+
check: 60000 // Check every 60 seconds
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
dbi.register(({ ChatInput, HTMLComponentsV2 }) => {
|
|
682
|
+
// Register Svelte component
|
|
683
|
+
HTMLComponentsV2({
|
|
684
|
+
name: "product-showcase",
|
|
685
|
+
mode: "svelte",
|
|
686
|
+
file: path.join(__dirname, "product-showcase.svelte"),
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
// Command to show the component
|
|
690
|
+
ChatInput({
|
|
691
|
+
name: "shop",
|
|
692
|
+
description: "Browse our product catalog",
|
|
693
|
+
async onExecute({ interaction, dbi }) {
|
|
694
|
+
const showcase = dbi.interaction("product-showcase");
|
|
695
|
+
|
|
696
|
+
await showcase.send(interaction, {
|
|
697
|
+
data: {
|
|
698
|
+
products: [
|
|
699
|
+
{ name: "Keyboard", price: 149, image: "https://..." },
|
|
700
|
+
{ name: "Mouse", price: 79, image: "https://..." },
|
|
701
|
+
],
|
|
702
|
+
currentIndex: 0,
|
|
703
|
+
cart: [],
|
|
704
|
+
view: "browse",
|
|
705
|
+
elapsedTime: 0,
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
dbi.load().then(() => console.log("Bot ready!"));
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### Component (product-showcase.svelte)
|
|
716
|
+
|
|
717
|
+
```svelte
|
|
718
|
+
<script>
|
|
719
|
+
/// <reference types="@mostfeatured/dbi/svelte" />
|
|
720
|
+
import stuffs from "stuffs";
|
|
721
|
+
|
|
722
|
+
let {
|
|
723
|
+
products = [],
|
|
724
|
+
currentIndex = 0,
|
|
725
|
+
cart = [],
|
|
726
|
+
view = "browse",
|
|
727
|
+
elapsedTime = 0,
|
|
728
|
+
} = $props();
|
|
729
|
+
|
|
730
|
+
// Format elapsed time
|
|
731
|
+
function formatTime(seconds) {
|
|
732
|
+
return stuffs.formatSeconds(seconds);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Navigation
|
|
736
|
+
function nextProduct() {
|
|
737
|
+
data.currentIndex = (currentIndex + 1) % products.length;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function prevProduct() {
|
|
741
|
+
data.currentIndex = (currentIndex - 1 + products.length) % products.length;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Cart actions
|
|
745
|
+
function addToCart(ctx) {
|
|
746
|
+
const product = products[currentIndex];
|
|
747
|
+
data.cart = [...cart, product];
|
|
748
|
+
ctx.interaction.reply({
|
|
749
|
+
content: `✅ Added **${product.name}** to cart!`,
|
|
750
|
+
flags: ["Ephemeral"],
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function clearCart(ctx) {
|
|
755
|
+
data.cart = [];
|
|
756
|
+
ctx.interaction.reply({
|
|
757
|
+
content: "🗑️ Cart cleared!",
|
|
758
|
+
flags: ["Ephemeral"],
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function checkout(ctx) {
|
|
763
|
+
if (cart.length === 0) {
|
|
764
|
+
ctx.interaction.reply({
|
|
765
|
+
content: "Cart is empty!",
|
|
766
|
+
flags: ["Ephemeral"],
|
|
767
|
+
});
|
|
768
|
+
noRender(); // Don't update UI
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
const total = cart.reduce((sum, p) => sum + p.price, 0);
|
|
773
|
+
ctx.interaction.reply({
|
|
774
|
+
content: `💳 **Order Placed!**\nTotal: $${total}`,
|
|
775
|
+
flags: ["Ephemeral"],
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
data.cart = [];
|
|
779
|
+
data.view = "browse";
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// View switching
|
|
783
|
+
function showCart() { data.view = "cart"; }
|
|
784
|
+
function showBrowse() { data.view = "browse"; }
|
|
785
|
+
function showDetails() { data.view = "details"; }
|
|
786
|
+
|
|
787
|
+
// Lifecycle - start timer on mount
|
|
788
|
+
onMount(() => {
|
|
789
|
+
data.elapsedTime = 0;
|
|
790
|
+
const interval = setInterval(() => {
|
|
791
|
+
data.elapsedTime += 1;
|
|
792
|
+
}, 1000);
|
|
793
|
+
|
|
794
|
+
// Cleanup on destroy
|
|
795
|
+
return () => clearInterval(interval);
|
|
796
|
+
});
|
|
797
|
+
</script>
|
|
798
|
+
|
|
799
|
+
<components>
|
|
800
|
+
{#if view === "browse"}
|
|
801
|
+
<container accent-color="5865F2">
|
|
802
|
+
<components>
|
|
803
|
+
<section>
|
|
804
|
+
<components>
|
|
805
|
+
<text-display>## 🛍️ Product Showcase</text-display>
|
|
806
|
+
<text-display>
|
|
807
|
+
**{products[currentIndex]?.name}**
|
|
808
|
+
{products[currentIndex]?.description}
|
|
809
|
+
</text-display>
|
|
810
|
+
<text-display>💰 **${products[currentIndex]?.price}**</text-display>
|
|
811
|
+
</components>
|
|
812
|
+
<thumbnail media={products[currentIndex]?.image}></thumbnail>
|
|
813
|
+
</section>
|
|
814
|
+
|
|
815
|
+
<separator></separator>
|
|
816
|
+
|
|
817
|
+
<text-display>
|
|
818
|
+
📦 Product {currentIndex + 1} of {products.length} | 🛒 Cart: {cart.length} items
|
|
819
|
+
</text-display>
|
|
820
|
+
|
|
821
|
+
<action-row>
|
|
822
|
+
<button style="Secondary" handler={prevProduct}>◀️ Prev</button>
|
|
823
|
+
<button style="Secondary" handler={nextProduct}>Next ▶️</button>
|
|
824
|
+
<button style="Success" handler={addToCart}>🛒 Add to Cart</button>
|
|
825
|
+
<button style="Primary" handler={showDetails}>📋 Details</button>
|
|
826
|
+
<button style="Primary" handler={showCart}>🛒 View Cart ({cart.length})</button>
|
|
827
|
+
</action-row>
|
|
828
|
+
|
|
829
|
+
<separator></separator>
|
|
830
|
+
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
831
|
+
</components>
|
|
832
|
+
</container>
|
|
833
|
+
|
|
834
|
+
{:else if view === "cart"}
|
|
835
|
+
<container accent-color="57F287">
|
|
836
|
+
<components>
|
|
837
|
+
<text-display>## 🛒 Your Cart</text-display>
|
|
838
|
+
|
|
839
|
+
{#if cart.length === 0}
|
|
840
|
+
<text-display>*Your cart is empty*</text-display>
|
|
841
|
+
{:else}
|
|
842
|
+
{#each cart as item, i}
|
|
843
|
+
<text-display>• **{item.name}** - ${item.price}</text-display>
|
|
844
|
+
{/each}
|
|
845
|
+
<separator></separator>
|
|
846
|
+
<text-display>
|
|
847
|
+
**Total: ${cart.reduce((sum, p) => sum + p.price, 0)}**
|
|
848
|
+
</text-display>
|
|
849
|
+
{/if}
|
|
850
|
+
|
|
851
|
+
<action-row>
|
|
852
|
+
<button style="Secondary" handler={showBrowse}>◀️ Back</button>
|
|
853
|
+
<button style="Danger" handler={clearCart}>🗑️ Clear</button>
|
|
854
|
+
<button style="Success" handler={checkout}>💳 Checkout</button>
|
|
855
|
+
</action-row>
|
|
856
|
+
|
|
857
|
+
<separator></separator>
|
|
858
|
+
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
859
|
+
</components>
|
|
860
|
+
</container>
|
|
861
|
+
|
|
862
|
+
{:else if view === "details"}
|
|
863
|
+
<container accent-color="FEE75C">
|
|
864
|
+
<components>
|
|
865
|
+
<section>
|
|
866
|
+
<components>
|
|
867
|
+
<text-display>## 📋 Product Details</text-display>
|
|
868
|
+
<text-display>**{products[currentIndex]?.name}**</text-display>
|
|
869
|
+
</components>
|
|
870
|
+
<thumbnail media={products[currentIndex]?.image}></thumbnail>
|
|
871
|
+
</section>
|
|
872
|
+
|
|
873
|
+
<separator></separator>
|
|
874
|
+
<text-display>{products[currentIndex]?.description}</text-display>
|
|
875
|
+
|
|
876
|
+
<action-row>
|
|
877
|
+
<button style="Secondary" handler={showBrowse}>◀️ Back</button>
|
|
878
|
+
<button style="Success" handler={addToCart}>🛒 Add to Cart</button>
|
|
879
|
+
</action-row>
|
|
880
|
+
|
|
881
|
+
<separator></separator>
|
|
882
|
+
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
883
|
+
</components>
|
|
884
|
+
</container>
|
|
885
|
+
{/if}
|
|
886
|
+
</components>
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
## API Reference
|
|
892
|
+
|
|
893
|
+
### Component Class Methods
|
|
894
|
+
|
|
895
|
+
```typescript
|
|
896
|
+
const component = dbi.interaction("my-component");
|
|
897
|
+
|
|
898
|
+
// Send to interaction or channel
|
|
899
|
+
await component.send(interaction, { data: { count: 0 } });
|
|
900
|
+
await component.send(channel, { data: { count: 0 } });
|
|
901
|
+
|
|
902
|
+
// Manually destroy a specific instance by ref
|
|
903
|
+
component.destroy(refId);
|
|
904
|
+
|
|
905
|
+
// Destroy all active instances
|
|
906
|
+
component.destroyAll();
|
|
907
|
+
|
|
908
|
+
// Get JSON representation
|
|
909
|
+
const json = component.toJSON({ data: { count: 0 } });
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
### Send Options
|
|
913
|
+
|
|
914
|
+
```typescript
|
|
915
|
+
interface SendOptions {
|
|
916
|
+
data?: Record<string, any>; // Initial data
|
|
917
|
+
flags?: string[]; // Message flags
|
|
918
|
+
content?: string; // Text content
|
|
919
|
+
ephemeral?: boolean; // Ephemeral message
|
|
920
|
+
reply?: boolean; // Force reply
|
|
921
|
+
followUp?: boolean; // Use followUp instead
|
|
922
|
+
}
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
---
|
|
926
|
+
|
|
927
|
+
## Best Practices
|
|
928
|
+
|
|
929
|
+
1. **Use `$props()` for initial state** - Destructure with defaults for clean code
|
|
930
|
+
2. **Mutate `data` for updates** - Don't reassign the entire data object
|
|
931
|
+
3. **Return cleanup from `onMount`** - Prevents memory leaks
|
|
932
|
+
4. **Use `noRender()` for background tasks** - Avoid unnecessary renders
|
|
933
|
+
5. **Set appropriate throttle** - Match your update frequency
|
|
934
|
+
6. **Use `destroy()` for cleanup** - Clean up timers when done
|
|
935
|
+
7. **Add type reference** - Get full IDE support
|
|
936
|
+
|
|
937
|
+
---
|
|
938
|
+
|
|
939
|
+
## Troubleshooting
|
|
940
|
+
|
|
941
|
+
### Component not updating?
|
|
942
|
+
- Make sure you're using `data.property = value`, not reassigning `data`
|
|
943
|
+
- Check that `noRender()` wasn't called earlier
|
|
944
|
+
|
|
945
|
+
### Timer keeps running after message deleted?
|
|
946
|
+
- Return a cleanup function from `onMount`
|
|
947
|
+
- Or use `onDestroy` to clear intervals
|
|
948
|
+
|
|
949
|
+
### Rate limited by Discord?
|
|
950
|
+
- Increase throttle with `setThrottle(500)` or higher
|
|
951
|
+
- The system automatically retries on rate limits (max 3 retries)
|
|
952
|
+
|
|
953
|
+
### IDE not showing autocomplete?
|
|
954
|
+
- Add `/// <reference types="@mostfeatured/dbi/svelte" />` at top of script
|
|
955
|
+
- Make sure `@mostfeatured/dbi` is installed
|