{"id":"furukan/customproximityprompts","name":"customproximityprompts","scope":"furukan","platform":"roblox","description":"Themeable custom UI for ProximityPrompts: Studio templates for the look, hooks for animations and hold fill","version":"0.1.0","latest":"0.1.0","versions":["0.1.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"6b5799849089eff8edc0d1e76f69897af13d0c6ba365046460c304175bce9aa8","likes":0,"downloads":0,"install":"forest install furukan/customproximityprompts","url":"https://forest.dev/p/roblox/furukan/customproximityprompts","files":"https://api.forest.dev/ai/package/roblox/furukan/customproximityprompts/files","readme":"# CustomProximityPrompts\n\nA small client module that draws custom UI for `ProximityPrompt`s. Each prompt picks a theme: a `BillboardGui` you\ndesign in Studio for the look, and optional hooks where you write its animations and its hold fill. The module only\ndoes the wiring every custom prompt needs; how a theme moves is up to you.\n\n```toml\n[dependencies]\nCustomProximityPrompts = \"furukan/customproximityprompts@0.1.0\"\n```\n\n## Usage\n\nRegister your themes and start the module once on the client:\n\n```luau\nlocal CustomProximityPrompts = require(ReplicatedStorage.Packages.CustomProximityPrompts)\n\nCustomProximityPrompts:RegisterTheme(\"Default\", {\n\tTemplate = ReplicatedStorage.Assets.ProximityPrompts.Default,\n\tOnShown = function(context) end,\n\tOnHidden = function(context) end,\n\tOnProgress = function(context, alpha) end,\n})\n\nCustomProximityPrompts:Start()\n```\n\nOnly prompts with `Style = Custom` are drawn; Roblox keeps drawing `Default` ones. A prompt chooses its theme with a\n`Theme` string attribute and falls back to `Default` when it has none or names a theme that is not registered.\n\n`Create` makes a custom prompt from a property table; `Theme` becomes the attribute and `Parent` is set last:\n\n```luau\nlocal prompt = CustomProximityPrompts:Create({\n\tActionText = \"Sell\",\n\tHoldDuration = 0.25,\n\tKeyboardKeyCode = Enum.KeyCode.X,\n\tTheme = \"Red\",\n\tParent = attachment,\n})\n```\n\n## Templates\n\nA theme's `Template` is a `BillboardGui`. Each time its prompt is shown it is cloned, adorned to the prompt's parent and\nput in a `CustomProximityPrompts` ScreenGui under `PlayerGui`. These descendants are filled in when present, found by\nname anywhere in the template:\n\n| Name | Class | Filled with |\n|------|-------|-------------|\n| `ActionText` | TextLabel | `prompt.ActionText` |\n| `ObjectText` | TextLabel | `prompt.ObjectText` |\n| `KeyText` | TextLabel | the key to press; visible only when the key is shown as text |\n| `KeyImage` | ImageLabel | the gamepad button or the touch icon; visible only when the key is shown as an image |\n| `Button` | GuiButton | pressing it holds the prompt, on touch or when `ClickablePrompt` is on |\n\nThey are refreshed whenever a property of the prompt changes. `UIOffset` shifts the gui through `SizeOffset` when its\n`Size` has a pixel part.\n\n## Hooks\n\nEvery hook gets a `Context` with the `Prompt`, its cloned `Gui` and the `InputType` it was shown for. A new context is\nmade each time a prompt is shown.\n\n| Hook | Called |\n|------|--------|\n| `OnShown(context)` | after the gui is parented |\n| `OnHidden(context)` | when the prompt hides, is disabled or is destroyed; the gui is destroyed after it returns, so it may yield for an exit animation |\n| `OnHoldBegan(context)` | when the hold starts |\n| `OnHoldEnded(context)` | when the hold is released or completes; reset the fill here |\n| `OnProgress(context, alpha)` | every frame while held, with `alpha` going from 0 to 1 over `HoldDuration` |\n| `OnTriggered(context)` | when the prompt triggers |\n| `OnTriggerEnded(context)` | when the trigger ends |\n\nRoblox still decides when a prompt shows (`MaxActivationDistance`, `RequiresLineOfSight`, `Exclusivity`), how long it\nis held (`HoldDuration`) and which keys trigger it (`KeyboardKeyCode`, `GamepadKeyCode`).\n\n## License\n\n[MIT](LICENSE)\n","readmeTruncated":false}