From e39d7c5464a939aec75cc4597d47b03d1bc70f6a Mon Sep 17 00:00:00 2001 From: Gaxeer <44334376+Gaxeer@users.noreply.github.com> Date: Sun, 10 Dec 2023 19:32:31 +0200 Subject: [PATCH] feat: adds search to changeling evolution menu (#22936) * refactor: make changeling ability categories more flexible, adjust serach for categories * refactor: adjust to codestyle * fix: fix compilation error --- code/__HELPERS/cmp.dm | 3 + .../changeling/changeling_power.dm | 4 +- .../changeling/changeling_power_category.dm | 21 ++++ .../antagonists/changeling/evolution_menu.dm | 86 ++++++++++----- .../changeling/powers/augmented_eyesight.dm | 2 +- .../changeling/powers/become_headslug.dm | 2 +- .../changeling/powers/biodegrade.dm | 2 +- .../changeling/powers/chameleon_skin.dm | 2 +- .../changeling/powers/contort_body.dm | 2 +- .../changeling/powers/digitalcamo.dm | 2 +- .../changeling/powers/epinephrine.dm | 2 +- .../changeling/powers/fleshmend.dm | 2 +- .../antagonists/changeling/powers/hivemind.dm | 2 +- .../changeling/powers/lesserform.dm | 2 +- .../changeling/powers/mimic_voice.dm | 2 +- .../changeling/powers/mutations.dm | 10 +- .../antagonists/changeling/powers/panacea.dm | 2 +- .../antagonists/changeling/powers/shriek.dm | 4 +- .../changeling/powers/strained_muscles.dm | 2 +- .../changeling/powers/summon_spiders.dm | 2 +- .../changeling/powers/swap_form.dm | 2 +- .../changeling/powers/tiny_prick.dm | 2 +- paradise.dme | 1 + .../packages/tgui/interfaces/EvolutionMenu.js | 100 +++++++++++++----- tgui/packages/tgui/public/tgui.bundle.js | 6 +- 25 files changed, 184 insertions(+), 83 deletions(-) create mode 100644 code/modules/antagonists/changeling/changeling_power_category.dm diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 402ba2c7e3b..e8bbb9c728d 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -54,3 +54,6 @@ /proc/cmp_login_processor_priority(datum/client_login_processor/A, datum/client_login_processor/B) return A.priority - B.priority + +/proc/cmp_changeling_power_category_asc(datum/changeling_power_category/a, datum/changeling_power_category/b) + return initial(a.priority) - initial(b.priority) diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index 5a34f372a8d..a88759b5467 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -13,6 +13,8 @@ background_icon_state = "bg_changeling" /// A reference to the changeling's changeling antag datum. var/datum/antagonist/changeling/cling + /// Datum path used to determine the location and name of the power in changeling evolution menu UI + var/datum/changeling_power_category/category /// Determines whether the power is always given to the changeling or if it must be purchased. var/power_type = CHANGELING_UNOBTAINABLE_POWER /// A description of what the power does. @@ -31,8 +33,6 @@ var/active = FALSE /// If this power can be used while the changeling has the `TRAIT_FAKE_DEATH` trait. var/bypass_fake_death = FALSE - /// Where this ability should be stored in the changeling menu - var/menu_location /* * Changeling code relies on on_purchase to grant powers. diff --git a/code/modules/antagonists/changeling/changeling_power_category.dm b/code/modules/antagonists/changeling/changeling_power_category.dm new file mode 100644 index 00000000000..2d1ea2ee4d9 --- /dev/null +++ b/code/modules/antagonists/changeling/changeling_power_category.dm @@ -0,0 +1,21 @@ +/datum/changeling_power_category + /// The name of the category + var/name = "common" + /// The number used to determine category position in changeling evolution menu UI + var/priority = 0 + +/datum/changeling_power_category/offence + name = "Offence" + priority = 1 + +/datum/changeling_power_category/defence + name = "Defence" + priority = 2 + +/datum/changeling_power_category/utility + name = "Utility" + priority = 3 + +/datum/changeling_power_category/stings + name = "Stings" + priority = 4 diff --git a/code/modules/antagonists/changeling/evolution_menu.dm b/code/modules/antagonists/changeling/evolution_menu.dm index f3e47bdfca2..cfc62411a7e 100644 --- a/code/modules/antagonists/changeling/evolution_menu.dm +++ b/code/modules/antagonists/changeling/evolution_menu.dm @@ -3,11 +3,6 @@ /// The evolution menu will be shown in the expanded mode, with powers, costs, and power descriptions being displayed. #define EXPANDED_MODE 1 -#define CLING_MENU_ATTACK 1 -#define CLING_MENU_DEFENSE 2 -#define CLING_MENU_UTILITY 3 -#define CLING_MENU_STINGS 4 - /datum/action/changeling/evolution_menu name = "Evolution Menu" desc = "Choose our method of subjugation." @@ -17,29 +12,8 @@ var/view_mode = EXPANDED_MODE /// A list containing the typepaths of bought changeling abilities. For use with the UI. var/list/purchased_abilities = list() - /// A list containing every purchasable changeling power. Includes its name, description, helptext and cost. - var/static/list/ability_list = list() - -/datum/action/changeling/evolution_menu/Grant(mob/M) - ..() - if(length(ability_list)) - return // List is already populated. - - // This is a list of lists, each lower-level list corresponding to one of the CLING_MENU section - ability_list = list(list(), list(), list(), list()) - - for(var/power_path in cling.purchaseable_powers) - var/datum/action/changeling/C = power_path - if(!C.menu_location) - stack_trace("Cling power [C], [C.type] had no corresponding menu location!") - continue - ability_list[C.menu_location] += list(list( - "name" = initial(C.name), - "description" = initial(C.desc), - "helptext" = initial(C.helptext), - "cost" = initial(C.dna_cost), - "power_path" = power_path - )) + /// A list containing lists of category and abilities, related to this category. For each ability includes its name, description, helptext and cost. For use with the UI. + var/static/list/ability_tabs = list() /datum/action/changeling/evolution_menu/try_to_sting(mob/user, mob/target) ui_interact(user) @@ -62,7 +36,7 @@ /datum/action/changeling/evolution_menu/ui_static_data(mob/user) var/list/data = list( - "ability_list" = ability_list + "ability_tabs" = get_ability_tabs() ) return data @@ -92,6 +66,8 @@ return TRUE /datum/action/changeling/evolution_menu/proc/try_purchase_power(power_type) + PRIVATE_PROC(TRUE) + if(!(power_type in cling.purchaseable_powers)) return FALSE if(power_type in purchased_abilities) @@ -110,3 +86,55 @@ cling.give_power(new power_type) return TRUE + +/datum/action/changeling/evolution_menu/proc/get_ability_tabs() + PRIVATE_PROC(TRUE) + + if(!length(ability_tabs)) + ability_tabs = build_ability_tabs() + + return ability_tabs + +/datum/action/changeling/evolution_menu/proc/build_ability_tabs() + PRIVATE_PROC(TRUE) + + var/list/abilities_by_category_name = get_abilities_grouped_by_category_name() + if(!length(abilities_by_category_name)) + return list() + + var/list/sorted_ability_categories = sortTim(subtypesof(/datum/changeling_power_category), GLOBAL_PROC_REF(cmp_changeling_power_category_asc)) + + var/list/sorted_ability_tabs = list() + for(var/datum/changeling_power_category/category as anything in sorted_ability_categories) + var/list/abilities = abilities_by_category_name[initial(category.name)] + sorted_ability_tabs += list(list( + "category" = initial(category.name), + "abilities" = abilities)) + + return sorted_ability_tabs + +/datum/action/changeling/evolution_menu/proc/get_abilities_grouped_by_category_name() + PRIVATE_PROC(TRUE) + + var/list/abilities_by_category_name = list() + for(var/power_path in cling.purchaseable_powers) + var/datum/action/changeling/changeling_ability = power_path + + if(!changeling_ability.category) + stack_trace("Cling power [changeling_ability], [changeling_ability.type] had no assigned category!") + continue + + var/category_name = initial(changeling_ability.category.name) + var/list/abilities = abilities_by_category_name[category_name] + if(!islist(abilities)) + abilities_by_category_name[category_name] = abilities = list() + + abilities += list(list( + "name" = initial(changeling_ability.name), + "description" = initial(changeling_ability.desc), + "helptext" = initial(changeling_ability.helptext), + "cost" = initial(changeling_ability.dna_cost), + "power_path" = power_path + )) + + return abilities_by_category_name diff --git a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm index 8e443fdbf61..a156a58467f 100644 --- a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm +++ b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm @@ -7,7 +7,7 @@ dna_cost = 4 active = FALSE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /datum/action/changeling/augmented_eyesight/on_purchase(mob/user, /datum/antagonist/changeling/C) //The ability starts inactive, so we should be protected from flashes. if(!..()) diff --git a/code/modules/antagonists/changeling/powers/become_headslug.dm b/code/modules/antagonists/changeling/powers/become_headslug.dm index ee810352049..be1f1fdbfae 100644 --- a/code/modules/antagonists/changeling/powers/become_headslug.dm +++ b/code/modules/antagonists/changeling/powers/become_headslug.dm @@ -9,7 +9,7 @@ req_stat = DEAD bypass_fake_death = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence /datum/action/changeling/headslug/try_to_sting(mob/user, mob/target) if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No") == "No") diff --git a/code/modules/antagonists/changeling/powers/biodegrade.dm b/code/modules/antagonists/changeling/powers/biodegrade.dm index 0d4fbfc0cd3..645c9189d10 100644 --- a/code/modules/antagonists/changeling/powers/biodegrade.dm +++ b/code/modules/antagonists/changeling/powers/biodegrade.dm @@ -7,7 +7,7 @@ dna_cost = 4 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence /// Type of acid hand we give to person var/hand = /obj/item/melee/changeling_corrosive_acid /// Current hand given to human, null is we did not give hand, object if hand is given diff --git a/code/modules/antagonists/changeling/powers/chameleon_skin.dm b/code/modules/antagonists/changeling/powers/chameleon_skin.dm index b69ee5c0add..18229432573 100644 --- a/code/modules/antagonists/changeling/powers/chameleon_skin.dm +++ b/code/modules/antagonists/changeling/powers/chameleon_skin.dm @@ -7,7 +7,7 @@ chemical_cost = 25 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /datum/action/changeling/chameleon_skin/sting_action(mob/user) var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = TRUE diff --git a/code/modules/antagonists/changeling/powers/contort_body.dm b/code/modules/antagonists/changeling/powers/contort_body.dm index 3c705db5345..8d8e611ee85 100644 --- a/code/modules/antagonists/changeling/powers/contort_body.dm +++ b/code/modules/antagonists/changeling/powers/contort_body.dm @@ -5,7 +5,7 @@ chemical_cost = 25 dna_cost = 4 power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /datum/action/changeling/contort_body/Remove(mob/M) REMOVE_TRAIT(M, TRAIT_CONTORTED_BODY, CHANGELING_TRAIT) diff --git a/code/modules/antagonists/changeling/powers/digitalcamo.dm b/code/modules/antagonists/changeling/powers/digitalcamo.dm index be29d8a42f6..4ce7480153a 100644 --- a/code/modules/antagonists/changeling/powers/digitalcamo.dm +++ b/code/modules/antagonists/changeling/powers/digitalcamo.dm @@ -5,7 +5,7 @@ button_icon_state = "digital_camo" dna_cost = 2 power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /datum/action/changeling/digitalcamo/Remove(mob/M) REMOVE_TRAIT(M, TRAIT_AI_UNTRACKABLE, CHANGELING_TRAIT) diff --git a/code/modules/antagonists/changeling/powers/epinephrine.dm b/code/modules/antagonists/changeling/powers/epinephrine.dm index 070cc912064..00e1f19e7b1 100644 --- a/code/modules/antagonists/changeling/powers/epinephrine.dm +++ b/code/modules/antagonists/changeling/powers/epinephrine.dm @@ -8,7 +8,7 @@ req_human = TRUE req_stat = UNCONSCIOUS power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence //Recover from stuns. /datum/action/changeling/epinephrine/sting_action(mob/living/user) diff --git a/code/modules/antagonists/changeling/powers/fleshmend.dm b/code/modules/antagonists/changeling/powers/fleshmend.dm index d5968b247cd..a2d46914432 100644 --- a/code/modules/antagonists/changeling/powers/fleshmend.dm +++ b/code/modules/antagonists/changeling/powers/fleshmend.dm @@ -7,7 +7,7 @@ dna_cost = 4 req_stat = UNCONSCIOUS power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence //Starts healing you every second for 10 seconds. Can be used whilst unconscious. /datum/action/changeling/fleshmend/sting_action(mob/living/user) diff --git a/code/modules/antagonists/changeling/powers/hivemind.dm b/code/modules/antagonists/changeling/powers/hivemind.dm index a2d21070cfd..0b67742098e 100644 --- a/code/modules/antagonists/changeling/powers/hivemind.dm +++ b/code/modules/antagonists/changeling/powers/hivemind.dm @@ -9,7 +9,7 @@ GLOBAL_LIST_EMPTY(hivemind_bank) chemical_cost = 10 dna_cost = 4 power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /datum/action/changeling/hivemind_pick/on_purchase(mob/user, datum/antagonist/changeling/C) if(!..()) diff --git a/code/modules/antagonists/changeling/powers/lesserform.dm b/code/modules/antagonists/changeling/powers/lesserform.dm index 85e960b8ce4..ea297fe802d 100644 --- a/code/modules/antagonists/changeling/powers/lesserform.dm +++ b/code/modules/antagonists/changeling/powers/lesserform.dm @@ -7,7 +7,7 @@ dna_cost = 2 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility //Transform into a monkey. /datum/action/changeling/lesserform/sting_action(mob/living/carbon/human/user) diff --git a/code/modules/antagonists/changeling/powers/mimic_voice.dm b/code/modules/antagonists/changeling/powers/mimic_voice.dm index 558e54e92cd..17347810c99 100644 --- a/code/modules/antagonists/changeling/powers/mimic_voice.dm +++ b/code/modules/antagonists/changeling/powers/mimic_voice.dm @@ -7,7 +7,7 @@ dna_cost = 2 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility // Fake Voice diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 50d92248b8b..48c133b545b 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -128,8 +128,8 @@ weapon_type = /obj/item/melee/arm_blade weapon_name_simple = "blade" power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_ATTACK recharge_slowdown = 0.75 + category = /datum/changeling_power_category/offence /obj/item/melee/arm_blade name = "arm blade" @@ -194,7 +194,7 @@ weapon_name_simple = "tentacle" silent = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_ATTACK + category = /datum/changeling_power_category/offence /obj/item/gun/magic/tentacle name = "tentacle" @@ -398,7 +398,7 @@ weapon_type = /obj/item/shield/changeling weapon_name_simple = "shield" power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence /datum/action/changeling/weapon/shield/sting_action(mob/user) var/obj/item/shield/changeling/S = ..(user) @@ -453,7 +453,7 @@ helmet_name_simple = "space helmet" recharge_slowdown = 0.5 blood_on_castoff = 1 - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /obj/item/clothing/suit/space/changeling name = "flesh mass" @@ -499,7 +499,7 @@ suit_name_simple = "armor" helmet_name_simple = "helmet" recharge_slowdown = 0.25 - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence /obj/item/clothing/suit/armor/changeling name = "chitinous mass" diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm index 69682dd18e1..231af787959 100644 --- a/code/modules/antagonists/changeling/powers/panacea.dm +++ b/code/modules/antagonists/changeling/powers/panacea.dm @@ -7,7 +7,7 @@ dna_cost = 2 req_stat = UNCONSCIOUS power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence //Heals the things that the other regenerative abilities don't. /datum/action/changeling/panacea/sting_action(mob/living/user) diff --git a/code/modules/antagonists/changeling/powers/shriek.dm b/code/modules/antagonists/changeling/powers/shriek.dm index f0c843b0aab..90c98ab8e6c 100644 --- a/code/modules/antagonists/changeling/powers/shriek.dm +++ b/code/modules/antagonists/changeling/powers/shriek.dm @@ -7,7 +7,7 @@ dna_cost = 2 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_ATTACK + category = /datum/changeling_power_category/offence //A flashy ability, good for crowd control and sowing chaos. /datum/action/changeling/resonant_shriek/sting_action(mob/user) @@ -44,7 +44,7 @@ chemical_cost = 30 dna_cost = 2 power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility //A flashy ability, good for crowd control and sewing chaos. /datum/action/changeling/dissonant_shriek/sting_action(mob/user) diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm index cca63a4f73d..c3ff08b0293 100644 --- a/code/modules/antagonists/changeling/powers/strained_muscles.dm +++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm @@ -10,7 +10,7 @@ dna_cost = 2 req_human = TRUE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_DEFENSE + category = /datum/changeling_power_category/defence /datum/action/changeling/strained_muscles/Remove(mob/living/L) L.remove_status_effect(STATUS_EFFECT_SPEEDLEGS) diff --git a/code/modules/antagonists/changeling/powers/summon_spiders.dm b/code/modules/antagonists/changeling/powers/summon_spiders.dm index e4d37c51e4a..3ef00c46c0b 100644 --- a/code/modules/antagonists/changeling/powers/summon_spiders.dm +++ b/code/modules/antagonists/changeling/powers/summon_spiders.dm @@ -16,7 +16,7 @@ /// Checks if changeling is already spawning a spider var/is_operating = FALSE power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_UTILITY + category = /datum/changeling_power_category/utility /// Makes a spider. Good for setting traps and combat. /datum/action/changeling/spiders/sting_action(mob/user) diff --git a/code/modules/antagonists/changeling/powers/swap_form.dm b/code/modules/antagonists/changeling/powers/swap_form.dm index 9fec3a5e3d6..71a838c1fdc 100644 --- a/code/modules/antagonists/changeling/powers/swap_form.dm +++ b/code/modules/antagonists/changeling/powers/swap_form.dm @@ -7,7 +7,7 @@ dna_cost = 2 req_human = TRUE //Monkeys can't grab power_type = CHANGELING_PURCHASABLE_POWER - menu_location = CLING_MENU_ATTACK + category = /datum/changeling_power_category/offence /datum/action/changeling/swap_form/can_sting(mob/living/carbon/user) if(!..()) diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index 798dd999a38..504c568f8a3 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -2,7 +2,7 @@ name = "Tiny Prick" desc = "Stabby stabby" power_type = CHANGELING_UNOBTAINABLE_POWER - menu_location = CLING_MENU_STINGS + category = /datum/changeling_power_category/stings var/sting_icon = null /// A middle click override used to intercept changeling stings performed on a target. var/datum/middleClickOverride/callback_invoker/click_override diff --git a/paradise.dme b/paradise.dme index 4cdd2d16db1..4ec2d991fa3 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1357,6 +1357,7 @@ #include "code\modules\antagonists\_common\antag_spawner.dm" #include "code\modules\antagonists\_common\antag_team.dm" #include "code\modules\antagonists\changeling\changeling_power.dm" +#include "code\modules\antagonists\changeling\changeling_power_category.dm" #include "code\modules\antagonists\changeling\datum_changeling.dm" #include "code\modules\antagonists\changeling\evolution_menu.dm" #include "code\modules\antagonists\changeling\powers\absorb.dm" diff --git a/tgui/packages/tgui/interfaces/EvolutionMenu.js b/tgui/packages/tgui/interfaces/EvolutionMenu.js index 04e7c0c6e3f..62ec6e8f5e8 100644 --- a/tgui/packages/tgui/interfaces/EvolutionMenu.js +++ b/tgui/packages/tgui/interfaces/EvolutionMenu.js @@ -1,7 +1,10 @@ import { Fragment } from 'inferno'; +import { createSearch } from 'common/string'; import { useBackend, useLocalState } from '../backend'; -import { Box, Button, Flex, Icon, Section, Tabs } from '../components'; +import { Box, Button, Flex, Section, Tabs, Input } from '../components'; import { Window } from '../layouts'; +import { flow } from 'common/fp'; +import { filter, sortBy } from 'common/collections'; export const EvolutionMenu = (props, context) => { return ( @@ -48,14 +51,69 @@ const EvolutionPoints = (props, context) => { const Abilities = (props, context) => { const { act, data } = useBackend(context); - const { evo_points, ability_list, purchased_abilities, view_mode } = data; - const [tab, setTab] = useLocalState(context, 'tab', 0); + const { evo_points, ability_tabs, purchased_abilities, view_mode } = data; + const [selectedTab, setSelectedTab] = useLocalState( + context, + 'selectedTab', + ability_tabs[0] + ); + const [searchText, setSearchText] = useLocalState(context, 'searchText', ''); + const [abilities, setAbilities] = useLocalState( + context, + 'ability_tabs', + ability_tabs[0].abilities + ); + + const selectAbilities = (abilities, searchText = '') => { + if (!abilities || abilities.length === 0) { + return []; + } + + const AbilitySearch = createSearch(searchText, (ability) => { + return ability.name + '|' + ability.description; + }); + + return flow([ + filter((ability) => ability?.name), + filter(AbilitySearch), + sortBy((ability) => ability?.name), + ])(abilities); + }; + + const handleSearch = (value) => { + setSearchText(value); + if (value === '') { + return setAbilities(selectedTab.abilities); + } + + setAbilities( + selectAbilities( + ability_tabs.map((ability_entry) => ability_entry.abilities).flat(), + value + ) + ); + }; + + const handleTabChange = (selectedTab) => { + setSelectedTab(selectedTab); + setAbilities(selectedTab.abilities); + setSearchText(''); + }; + return (
+ { + handleSearch(value); + }} + value={searchText} + />