All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
8.3 KiB

1 year ago
  1. # DragonFlagon Module Buttons Library
  2. ![Forge Installs](https://img.shields.io/badge/dynamic/json?color=red&label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Flib-df-buttons) ![Latest Version](https://img.shields.io/badge/dynamic/json?label=Latest%20Release&prefix=v&query=package.versions%5B0%5D&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Flib-df-buttons) [![Foundry Hub Endorsements](https://img.shields.io/endpoint?logoColor=white&url=https%3A%2F%2Fwww.foundryvtt-hub.com%2Fwp-json%2Fhubapi%2Fv1%2Fpackage%2Flib-df-buttons%2Fshield%2Fendorsements)](https://www.foundryvtt-hub.com/package/lib-df-buttons/)
  3. Library for Foundry VTT module developers to use. It allows modules to register control buttons that appear on the right side of the screen.
  4. ![image-20211107113847436](../.assets/lib-df-buttons/cover.png)
  5. ##### [![become a patron](../.assets/patreon-image.png)](https://www.patreon.com/bePatron?u=46113583) If you want to support me or just help me buy doggy treats! Also, you can keep up to date on what I'm working on. I will be announcing any new modules or pre-releases there for anyone wanting to help me test things out!
  6. # For Module Developers
  7. ## How to Use
  8. All modules that wish to use the library should declare a dependency in their manifest as follows:
  9. ```json
  10. "dependencies": [ { "name": "lib-df-buttons" } ]
  11. ```
  12. ## How to Register Buttons
  13. The library uses Hooks in the same way that the `SceneControls` class does. This Hook call receives a list of `ToolGroup` objects which can be appended to.
  14. ```JavaScript
  15. Hooks.on('getModuleToolGroups', (controlManager/*: ControlManager*/, groups /*: ToolGroup[]*/) => {
  16. groups.push({
  17. name: 'my-tool-group',// Unique group ID
  18. icon: '<i class="fas fa-dice-one"></i>',// HTMLElement to be used as an Icon
  19. title: 'My Tool Group',// Plain text or a localization key
  20. tools: [
  21. {
  22. name: 'my-tool',// Unique tool ID within the scope of the parent Group
  23. title: 'My Special Tool',// Plain text or a localization key
  24. onClick: () => console.log("I've been clicked!"),// Click handler
  25. icon: '<i class="fas fa-dice-one"></i>',// HTMLElement to be used as an Icon
  26. button: true // This tool is just a button
  27. },
  28. ...
  29. ]
  30. });
  31. });
  32. ```
  33. By default, all `ToolGroup` and `Tool` configurations use a Radial Behaviour. This can be changed by setting either `button: true` or `toggle: true`.
  34. ## Configuration Interfaces
  35. ```TypeScript
  36. /** Standard single parameter handler */
  37. export type Handler<T> = (value?: T) => (Promise<void> | void);
  38. /** Standard boolean logic predicate */
  39. export type Predicate = () => (Promise<boolean> | boolean);
  40. /**
  41. * Tool Configuration for tools that appear on the secondary bar when their
  42. * parent group is active.
  43. */
  44. export interface Tool {
  45. /** Unique name ID of the Tool */
  46. name: string;
  47. /** Plain Text or a Localization Key */
  48. title: string;
  49. /** HTMLElement to be used as an icon */
  50. icon: string;
  51. /**
  52. * (default: false) If true, the tool will act as a simple button.
  53. * Must implement {@link onClick}
  54. */
  55. button?: boolean | null;
  56. /**
  57. * (default: false) If true, the tool will act as a toggle button.
  58. * Must implement {@link onClick}
  59. */
  60. toggle?: boolean | null;
  61. /**
  62. * (default: null) Used to add your own custom class name to the generated
  63. * control.
  64. */
  65. class?: string | null;
  66. /**
  67. * (default: false) Indicates your button or {@link ToolGroup} should be
  68. * allowed to render when there is no game board canvas.
  69. */
  70. noCanvas?: boolean;
  71. /**
  72. * (default: false) If {@link toggle} is true, this holds the toggle
  73. * button's state. If {@link toggle} and {@link button} are false, this
  74. * holds the activation state of the control and will be overridden by the
  75. * {@link ControlManager}.
  76. */
  77. isActive?: Predicate | boolean | null;
  78. /**
  79. * (default: true) Sets the visibility of the tool. Can be a function or a
  80. * boolean value
  81. */
  82. visible?: Predicate | boolean | null;
  83. /**
  84. * A click handler that is invoked when ever the tool is pressed. This
  85. * function is given an `active` state when either the default Radial or set
  86. * as a toggle button.
  87. *
  88. * If the Handler is unbound, it will be bound to the {@link Tool} instance it belongs to.
  89. *
  90. * - Radial Button (default): Invoked with `active:false` when deactivated, or `active:true` when activated.
  91. * - Toggle Button: Invoked with the new toggled state (true|false).
  92. * - Button: Invoked with no parameters.
  93. */
  94. onClick?: Handler<boolean> | null;
  95. }
  96. /**
  97. * A collection of Tools that appear on the main bar
  98. */
  99. export interface ToolGroup extends Tool {
  100. /** {@link Tool} collection */
  101. tools?: Tool[];
  102. /**
  103. * {@link Tool.name} of tool to be active. Defaults to the first tool in
  104. * the {@link tools} list.
  105. */
  106. activeTool?: string;
  107. }
  108. /** Manages the button UI, Hooks, and User Interactions. */
  109. export interface ControlManager {
  110. /** Complete list of {@link ToolGroup} objects. */
  111. get groups(): ToolGroup[];
  112. /** Name of currently active {@link ToolGroup}. */
  113. get activeGroupName(): string;
  114. /** Name of the currently active {@link Tool}. */
  115. get activeToolName(): string;
  116. /** The currently active {@link ToolGroup} object. */
  117. get activeGroup(): ToolGroup;
  118. /** The currently active {@link Tool} object. */
  119. get activeTool(): Tool;
  120. /**
  121. * Activates a {@link ToolGroup} by its unique name.
  122. * @param groupName Name of the group to be activated.
  123. */
  124. activateGroupByName(groupName: string): Promise<void>;
  125. /**
  126. * Activates a {@link Tool} inside the given {@link ToolGroup} via their unique names.
  127. * @param groupName Name of group that contains the {@link Tool}.
  128. * @param toolName Name of the {@link Tool} to be activated.
  129. * @param activateGroup (Default true) Also activate the {@link ToolGroup}.
  130. */
  131. activateToolByName(groupName: string, toolName: string, activateGroup?: boolean): Promise<void>;
  132. /** Reload the module buttons bar by rebuilding the {@link ToolGroup}s and rerendering. */
  133. reloadModuleButtons(): void;
  134. /** Refresh the button UI to reflect any external changes made */
  135. refresh(): void;
  136. }
  137. ```
  138. ## Hooks
  139. This library leverages the Hooks system for all of its interactions. This makes it easier for developers to register Tools/ToolGroups, or to listen to when groups or tools are activated. As well as to activate a Tool or ToolGroup programmatically.
  140. ### Hooks that are broadcast
  141. ```typescript
  142. /* Pre-ToolGroup populator. Invoked immediately before `getModuleToolGroups` */
  143. Hooks.on('getModuleToolGroupsPre', (app: ControlManager, groups: ToolGroup[]) => {});
  144. /* General request used to populate the list of Tool Groups and their collections of Tools */
  145. Hooks.on('getModuleToolGroups', (app: ControlManager, groups: ToolGroup[]) => {});
  146. /* Post-ToolGroup populator. Invoked immediately after `getModuleToolGroups` */
  147. Hooks.on('getModuleToolGroupsPost', (app: ControlManager, groups: ToolGroup[]) => {});
  148. /* Broadcast when a group has been activated, and the activated `ToolGroup` instance is passed to it */
  149. Hooks.on('toolGroupActivated', (app: ControlManager, groups: ToolGroup[]) => {});
  150. /* Broadcast when a Tool has been activated, and the parent `ToolGroup` and activated `Tool` instances are passed to it */
  151. Hooks.on('toolActivated', (app: ControlManager, groups: ToolGroup[]) => {});
  152. /* Broadcast when a request has been made to tear down and rebuild the module buttons. Called whenever `ControlManager.reloadModuleButtons()` is invoked */
  153. Hooks.on('moduleButtonsReloading', (app: ControlManager) => {});
  154. ```
  155. ### Hooks that are monitored
  156. ```typescript
  157. /* Invoking this Hook will tell the ControlManager to activate the named ToolGroup */
  158. Hooks.call('activateGroupByName', "my-group-name");
  159. /* Invoking this Hook will tell the ControlManager to activate the named Tool that
  160. * belongs to the named ToolGroup. You can also pass `true` as a 3rd parameter to
  161. * have the ToolGroup also activated. (default: false)
  162. */
  163. Hooks.call('activateToolByName', "my-group-name", "my-tool-name", true);
  164. /* Invoking this Hook will cause the ControlManager destroy the current ToolGroup
  165. * collection and re-build it, calling `getModuleToolGroupsPre`, `getModuleToolGroups`,
  166. * and `getModuleToolGroupsPost` as before. It then renders the new list of ToolGroups.
  167. */
  168. Hooks.call('reloadModuleButtons');
  169. /* Invoking this Hook will refresh the button UI to reflect any external changes made. */
  170. Hooks.call('refreshModuleButtons');
  171. ```