Monarch API

Alright, adventurous ones: I have a Beta version of Monarch with the new components API! Manifest: https://github.com/zeel01/monarch/releases/download/v0.3.6/module.json API Docs: https://github.com/zeel01/monarch/blob/dynamic-components/readme.md#-monarch-api This API allows you to respond to a hook, and manipulate a set of data that describes info badges and controls that will display on the cards in each app. You can remove items (hide suit, value, and type?), add badges and controls, or even re-arrange stuff if you like. Controls are similar to header buttons. They each get a class to name them, and an onclick method which will be called when the user clicks. This callback will be passed the Card that the user was interacting with, along with the Cards container it's held within. By this method, you can replicate all the card interactions that core uses, or create just about anything you can come up with. I used this system to implement a "discard" button which can be tested by pasting the id of a pile into the setting under module settings. I'll probably change this later to be a drop down menu or something. @mattr64 @floradical @norc. @Lucas Ferreira @badideasbureau Any feedback on the system/documentation would be super appreciated. I think I have a pretty robust implementation, but no plan survives contact with the enemy 😉
GitHub
monarch/readme.md at dynamic-components · zeel01/monarch
A Foundry VTT card UI fit for royalty. Contribute to zeel01/monarch development by creating an account on GitHub.
No description
F
FloRadical•835d ago
ohhhh I'll defo take a look during the weekend :O
B
BadIdeasBureau•835d ago
Shiny! Looking at the docs (will poke the actual module ~this weekend), it looks like the badges only display for the currently selected card, is that right? Being able to show a badge on all cards that fit a given criterion would be handy for Torg (to show all cards in pool at a glance)
Z
zeel•835d ago
A badge will show on all cards, unless hide is set to true for one of them. Of course, since the card HUD isn't visible for cards you aren't hovering you won't see more than one at a time in the hand. Markers of some form are a future addition though, and will likely have some means of seeing which cards are marked all the time. The function you pass as text will be called for each card. All the badges/controls on the cards use the new system now. So if you load up thr module you will see what I mean.
B
BadIdeasBureau•835d ago
Makes sense, thanks
Z
zeel•834d ago
Ah, I love it when you spend a day annoyed by something you did but can't for some reason come up with a better idea. Then the next day you immediately realize a better choice. I was bothered that I named the hook getMonarchHandCommands since it's commands and other stuff, but didn't want to make it multiple hooks. Then I looked at the title I gave my release: "Components API Beta" ...Components facepalmpicard So... breaking API change incoming (lmao): I'll be changing the name of the hook in the next pre-release. I'm pretty sure nobody wrote any code yet though, so 😆 So will be getMonarchHandComponents, getMonarchDeckComponents, etc. Hmm.... Query: Should I change the hook signature to pass all the component arrays in a "components" object, so that they can be referenced by name?
components = {
controls: Array<CardControl>,
badges: Array<CardBadge>,
markers: Array<CardMarker>,
...
}
components = {
controls: Array<CardControl>,
badges: Array<CardBadge>,
markers: Array<CardMarker>,
...
}
Then the order of the parameters won't matter, you would just do:
Hooks.on("getMonarchHandComponents", (monarch, components) => {
components.badges.push({
...
});
});
Hooks.on("getMonarchHandComponents", (monarch, components) => {
components.badges.push({
...
});
});
Thoughts? This would make it more robust against changes in the API later, as adding to this object would not cause the hook signature to change.
B
BadIdeasBureau•834d ago
I like that approach
Z
zeel•834d ago
Okay, I made those changes and updated the links above: https://github.com/zeel01/monarch/releases/download/v0.3.1/module.json
Z
zeel•834d ago
@badideasbureau Markers!
No description
B
BadIdeasBureau•834d ago
Yessss!
F
FloRadical•833d ago
dumb question BUT are there TS types xD
Z
zeel•833d ago
There are JS Doc types 😜
F
FloRadical•833d ago
I was asking because of the snippets above. Made it look like there are types I can probably throw smething together
Z
zeel•833d ago
Is there a way for me to define the types without using TS? I'm not opposed to maintaining a type definition, but I don't want to actually write my code in TS.
F
FloRadical•833d ago
yeah you can just write a d.ts file by hand it's how the foundryvtt types are made, we write them by hand
Z
zeel•833d ago
I'll look into it Do you mind opening a Github issue so I can't forget?
F
FloRadical•833d ago
distributing is the more "difficult" thing. You could just have it as a single downloadble file or make an npm package I'll ask the others how we should best define the hooks
Z
zeel•833d ago
Hooks man. So cool. But freaking impossible to properly define. JS Doc doesn't handle it right, I'm betting TS is all 🤷 about it too.
F
FloRadical•833d ago
suprisngly, the boys have found a way
Z
zeel•831d ago
@floradical As a test, I tried just having it generate .d.ts from the JS docs, and set my release workflow to attach that file to my releases. If you get a chance to check it, is the difinition attached to this sufficient? https://github.com/zeel01/monarch/releases/tag/v0.3.2.t
F
FloRadical•831d ago
MonarchApplicationMixin ?
Z
zeel•831d ago
Deep magic
F
FloRadical•831d ago
I'll need to test it but I'm not actually sure that it'll work
Z
zeel•831d ago
So that my apps that don't share the same base can share functionality.
F
FloRadical•831d ago
right
Z
zeel•831d ago
It's possible that I did one of thise "TS can not fathom this JS" things.
F
FloRadical•831d ago
like break polymorphism? xD
Z
zeel•831d ago
Mixins don't break polymorphism! (much) It's not my fault this language doesn't support multiple inheritance.
F
FloRadical•831d ago
nah mixins aren't a problem IIRC
Z
zeel•831d ago
Honestly the only things that you need types for are the typedefs in Components.js And the hook Which is still 🤷 to me
F
FloRadical•831d ago
yeah the only stuff we need typed are the components.
Z
zeel•831d ago
And they aren't even full classes, just objects of stuff
F
FloRadical•831d ago
yeah that's what interfaces are for
Z
zeel•831d ago
I maybe should type the callback functions though Actually, how does one do that.
F
FloRadical•831d ago
If I can get the time I'll try and write up the stuff if you want or we'll drop the subject. either works for me type the callback functions?
Z
zeel•831d ago
Well I would like for system devs using TS not to be angry with using it Like:
/**
* @typedef {Object} CardControl An object defining a control to display on a card.
* @property {string|Function<string>} [tooltip] - The tooltip of the control, or a function that returns the tooltip
* @property {string|Function<string>} [aria] - The aria label (for screen readers) of the control, or a function that returns the aria label
* @property {string|Function<string>} [icon] - The icon to display for the control, or a function that returns the icon
* @property {string} [class] - The css class to apply to the control
* @property {boolean|Function<boolean>} [disabled] - Whether the control is disabled, or a function that returns whether the control is disabled
* @property {Function} [onclick] - The function to call when the control is clicked
* @property {Array<CardControl>} [controls] - An array of controls to display as a group
*/
/**
* @typedef {Object} CardControl An object defining a control to display on a card.
* @property {string|Function<string>} [tooltip] - The tooltip of the control, or a function that returns the tooltip
* @property {string|Function<string>} [aria] - The aria label (for screen readers) of the control, or a function that returns the aria label
* @property {string|Function<string>} [icon] - The icon to display for the control, or a function that returns the icon
* @property {string} [class] - The css class to apply to the control
* @property {boolean|Function<boolean>} [disabled] - Whether the control is disabled, or a function that returns whether the control is disabled
* @property {Function} [onclick] - The function to call when the control is clicked
* @property {Array<CardControl>} [controls] - An array of controls to display as a group
*/
How do I type hint the parameters that get passed to onclick or to tooltip? I know how to do Function<boolean> to hint the return value
F
FloRadical•831d ago
I'm honestly not sure how to do that propely in JSDoc. TS is kinda self-documenting in that way. lemme try something does the onclick function get any inputs?
Z
zeel•831d ago
event, card, and container
F
FloRadical•831d ago
/** An object defining a control to display on a card. */
interface CardControl {
/** The tooltip of the control, or a function that returns the tooltip */
tooltip: string | (() => string);
/** The aria label (for screen readers) of the control, or a function that returns the aria label */
aria: string | (() => string);
/** The icon to display for the control, or a function that returns the icon */
icon: string | (() => string);
/** The css class to apply to the control */
class: string;
/**
* Whether or not to disable the control. The control will appear grayed out. May be a function that returns a boolean.
* @defaultValue `false`
*/
disabled?: string | (() => string);
/** A function that will run when the control is clicked*/
onclick: (event: MouseEvent, card: Card, container: Cards) => void;
/**
* An array of controls to be added as a control group. When included, you may omit all other properties except `class`.
* Instead, each item in this `controls` array should be a complete CardControl object. Does not support nesting.
*/
controls?: CardControl[];
}
/** An object defining a control to display on a card. */
interface CardControl {
/** The tooltip of the control, or a function that returns the tooltip */
tooltip: string | (() => string);
/** The aria label (for screen readers) of the control, or a function that returns the aria label */
aria: string | (() => string);
/** The icon to display for the control, or a function that returns the icon */
icon: string | (() => string);
/** The css class to apply to the control */
class: string;
/**
* Whether or not to disable the control. The control will appear grayed out. May be a function that returns a boolean.
* @defaultValue `false`
*/
disabled?: string | (() => string);
/** A function that will run when the control is clicked*/
onclick: (event: MouseEvent, card: Card, container: Cards) => void;
/**
* An array of controls to be added as a control group. When included, you may omit all other properties except `class`.
* Instead, each item in this `controls` array should be a complete CardControl object. Does not support nesting.
*/
controls?: CardControl[];
}
Z
zeel•831d ago
/**
* @callback clickCallback
* @param {Event} event
* @param {Card} card
* @param {Cards} container
* @returns {string}
*/
/**
* @callback clickCallback
* @param {Event} event
* @param {Card} card
* @param {Cards} container
* @returns {string}
*/
This seems to perhaps do the trick?
export type clickCallback = (event: Event, card: Card, container: Cards) => string;
export type clickCallback = (event: Event, card: Card, container: Cards) => string;
F
FloRadical•831d ago
^^ yay
Z
zeel•831d ago
Then if I use clickCallback as the type instead of Function it seems right?
F
FloRadical•831d ago
yup since you defined the signature and return type of the function as a type so you just reference that
Z
zeel•831d ago
Okay, so now how does the hook get handled? I have a Components typedef. So the signature for the Hook callback is: (monarch: FormApplication, components: Components) => void
F
FloRadical•831d ago
pretty much, yeah
Z
zeel•831d ago
components.contextMenu is an array of CardControl, so not much different from components.controls just displayed inside this nifty context menu. By default, I've added toggles for the seven colored markers I included in v0.3.2
UU
Unknown User•831d ago
Z
zeel•831d ago
Possibly Additional built in buttons/settings will be added when the API is done.
UU
Unknown User•831d ago
Z
zeel•831d ago
You can make it disabled too So the button is there, but can't be used. And you can disable it per-card. So if they have the mana for one card, but not another, you can control that. And you can always look through the controls array for the play button, and give it a disable function. Rather than replacing/removing the button.
UU
Unknown User•831d ago
Z
zeel•828d ago
Yep Wooo! Finally: AppControls These componenets are used to add the buttons on the sheet for manipulating the whole application or pile. https://github.com/zeel01/monarch/releases/download/v0.3.4/module.json Found in components.appControls these work very similarly to card controls, but the callback signatures are a little different since they don't reference specific cards. This array is empty/ignored for the Card sheet, for it use controls and a CardControl since those are designed to reference a Card object. And that I believe is the end of the Dynamic Components portion of the API! I have a few more API things I want to add before I release this is a public build, plus some non-API issues to deal with. I would greatly appreciate any API feedback I can get before then though. https://github.com/zeel01/monarch/releases/download/v0.3.5/module.json Added some hooks for other events. https://github.com/zeel01/monarch/releases/download/v0.3.6/module.json
F
FloRadical•827d ago
I'll give it a try this weekend
Want results from more Discord servers?
Add your server
More Posts
compacted chat cardsModules create problems to solve problems... Today's problem: "When I roll an attack, it eats the whdragdrop shenneneginsRight now, a user can drag a spell onto their character sheet. I store that in a 'spell' array and leffect mini modulesI've gotten to the point where I'm confident in releasing a slurry of tiny no-config Active Effect rdamage application hooksNew 5e Hook ideas, gimme yer thoughts: `Hooks.call('Actor5e.preDamageApplied')` args: `damageAmounthook conventionsRegarding hooks, is the convention that _all_ `pre...` hooks are executed on the machine that initiaexpand arraysIs there a way to `expandObject` except for an Array?edit-owned-item-effectI've made an abomination. This hacks its way past the limitations surrounding editing effects on ownItem Pile feedbackSimple is king!effects to chat@badideasbureau is the `temporary` flag you look for in Effects to Chat a convention from somewhere 5e AEsI've been messing pretty heavily with some Active Effect assumptions and mechanisms in 5e. This is mhero creator ui feedbackI'm trying to refactor the abilities' tab on the hero creation room to accomodate Race ASIs, but I deffect mechanic searchingI need someone to check me on a null hypothesis I'm making. > There are no abilities in 5e RAW whicDialog shennaneginsTIL the button callbacks for `Dialog.prompt` and `Dialog.confirm` can be asynchronous. ```js const Advancement Hooks@kandashi @ccjmk and anyone else who is currently working on modules that would interact with the AdAPI doc topicsGive me some ideas for what areas of the foundry core API would benefit from a wiki documentation paDiscord Permission IssueOh, I think you also need a Typescript roleDevelopment-APIA new section of the Wiki was created today: `development/api` This section is dedicated to documentitem to actors scriptI have this macro for updating actors in a compendium with spells from a compendium of spells (i.e. Primary and Embedded UpdatesTIL how to update embedded documents at the same time as parent documents. ``` game.actors.getName(compendium errors upgrading to v9hmm im not entirely sure how this will work though.. because I did just a quick smell test to my mod