diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index b414128d..5abef0b2 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -2,7 +2,7 @@ name: Release Creation
on:
release:
- types: [published]
+ types: [ published ]
jobs:
build:
@@ -39,10 +39,14 @@ jobs:
manifest: https://raw.githubusercontent.com/${{github.repository}}/next/module.json
download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip
+ # Install packages.
+ - run: npm install
+ # Build distribution.
+ - run: npm run build
# Create a zip file with all files required by the module to add to the release
- - run: zip -r ./module.zip module.json LICENSE styles/ scripts/ templates/ languages/
+ - run: zip -r ./module.zip module.json LICENSE styles/ templates/ languages/ module.js style.css
# Create a release for this specific version
- name: Update Release with Files
diff --git a/module.js.map b/module.js.map
index 00169853..2354010c 100644
--- a/module.js.map
+++ b/module.js.map
@@ -1 +1 @@
-{"version":3,"file":"module.js","sources":["src/systems/dnd5e.js","src/systems/pf1.js","src/systems/pf2e.js","src/systems/ds4.js","src/systems/d35e.js","src/systems/sfrpg.js","src/systems/swade.js","src/systems/tormenta20.js","src/systems/wfrp4e.js","src/systems/splittermond.js","src/systems.js","src/constants/settings.js","src/constants/constants.js","src/helpers/helpers.js","src/helpers/utilities.js","src/helpers/pile-utilities.js","node_modules/svelte/internal/index.mjs","node_modules/svelte/store/index.mjs","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/util/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/store/index.js","node_modules/svelte/easing/index.mjs","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/math/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/animation/AnimationControl.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/animation/AnimationManager.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/constants.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/convertRelative.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/animation/AnimationAPI.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/animation/AnimationGroupControl.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/animation/AnimationGroupAPI.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/initial/Centered.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/initial/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/PositionChangeSet.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/PositionData.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/PositionStateAPI.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/StyleCache.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/transform/TransformData.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/validators/AdapterValidators.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/validators/BasicBounds.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/validators/TransformBounds.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/validators/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/transform/Transforms.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/update/UpdateElementData.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/animate/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/update/UpdateElementManager.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/position/Position.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/internal/ApplicationState.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/internal/GetSvelteData.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/internal/loadSvelteConfig.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/internal/SvelteReactive.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/SvelteApplication.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/TJSContainer.svelte","node_modules/svelte/transition/index.mjs","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/transition/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/TJSGlassPane.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/action/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/helper/index.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/application/TJSHeaderButton.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/application/TJSApplicationHeader.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/application/ResizableHandle.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/application/ApplicationShell.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/dialog/DialogContent.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/component/core/dialog/DialogShell.svelte","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/internal/DialogData.js","node_modules/@typhonjs-fvtt/runtime/_dist/svelte/application/TJSDialog.js","src/applications/components/FilePicker.svelte","src/helpers/sharing-utilities.js","src/applications/components/SliderInput.svelte","src/applications/editors/price-modifiers-editor/price-modifiers-editor.svelte","src/applications/editors/price-modifiers-editor/price-modifiers-editor.js","src/applications/components/DropZone.svelte","src/applications/editors/currencies-editor/CurrencyList.svelte","src/applications/editors/currencies-editor/currency-store.js","src/applications/editors/currencies-editor/currencies-editor-shell.svelte","src/applications/editors/currencies-editor/currencies-editor.js","src/applications/editors/item-filters-editor/item-filters-editor.svelte","src/applications/editors/item-filters-editor/item-filters-editor.js","src/applications/components/Tabs.svelte","src/constants/hooks.js","src/hotkeys.js","src/applications/dialogs/drop-item-dialog/drop-item-dialog-shell.svelte","src/applications/dialogs/drop-item-dialog/drop-item-dialog.js","src/applications/item-pile-inventory-app/ListEntry.svelte","src/applications/item-pile-inventory-app/ItemList.svelte","src/applications/dialogs/drop-currency-dialog/drop-currency-dialog-shell.svelte","src/applications/dialogs/drop-currency-dialog/drop-currency-dialog.js","src/applications/item-pile-inventory-app/CurrencyList.svelte","src/applications/item-pile-inventory-app/ActorPicker.svelte","src/stores/pile-item.js","src/stores/item-pile-store.js","src/applications/item-pile-inventory-app/item-pile-inventory-shell.svelte","src/applications/item-pile-inventory-app/item-pile-inventory-app.js","src/helpers/transaction.js","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/internal/StyleManager.js","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/internal/cssVariables.js","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/internal/FoundryStyles.js","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/standard/label/TJSToggleLabel.svelte","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/standard/menu/TJSMenu.svelte","node_modules/@typhonjs-fvtt/svelte-standard/_dist/component/standard/index.js","src/applications/components/PriceSelector.svelte","src/applications/dialogs/buy-item-dialog/buy-item-dialog-shell.svelte","src/applications/dialogs/buy-item-dialog/buy-item-dialog.js","src/stores/merchant-store.js","src/applications/merchant-app/MerchantLeftPane.svelte","src/applications/editors/item-editor/ItemPriceStore.js","node_modules/svelte/animate/index.mjs","node_modules/svelte-dnd-action/src/helpers/dispatcher.js","node_modules/svelte-dnd-action/src/constants.js","node_modules/svelte-dnd-action/src/helpers/intersection.js","node_modules/svelte-dnd-action/src/helpers/listUtil.js","node_modules/svelte-dnd-action/src/helpers/scroller.js","node_modules/svelte-dnd-action/src/helpers/util.js","node_modules/svelte-dnd-action/src/helpers/observer.js","node_modules/svelte-dnd-action/src/helpers/windowScroller.js","node_modules/svelte-dnd-action/src/helpers/svelteNodeClone.js","node_modules/svelte-dnd-action/src/helpers/styler.js","node_modules/svelte-dnd-action/src/pointerAction.js","node_modules/svelte-dnd-action/src/helpers/aria.js","node_modules/svelte-dnd-action/src/keyboardAction.js","node_modules/svelte-dnd-action/src/action.js","src/applications/editors/item-editor/PriceList.svelte","src/applications/editors/item-editor/item-editor-shell.svelte","src/applications/editors/item-editor/item-editor.js","src/applications/merchant-app/MerchantItemEntry.svelte","src/applications/merchant-app/MerchantBuyTab.svelte","src/applications/merchant-app/MerchantRightPane.svelte","src/applications/merchant-app/MerchantTopBar.svelte","src/applications/merchant-app/merchant-app-shell.svelte","src/applications/merchant-app/merchant-app.js","src/API/private-api.js","src/applications/components/CustomDialog.svelte","src/applications/trade-dialogs/ActorDropSelect.svelte","src/applications/trade-dialogs/trade-dialog-prompt.svelte","node_modules/svelte/motion/index.mjs","src/applications/trade-dialogs/trade-dialog-request.svelte","src/applications/trade-dialogs/trade-dialogs.js","src/applications/trading-app/trade-store.js","src/applications/trading-app/TradeEntry.svelte","src/applications/trading-app/trading-app-shell.svelte","src/applications/trading-app/trading-app.js","src/API/trade-api.js","src/API/chat-api.js","src/socket.js","src/API/api.js","src/applications/editors/item-type-price-modifiers-editor/item-type-price-modifiers-editor.svelte","src/applications/editors/item-type-price-modifiers-editor/item-type-price-modifiers-editor.js","src/applications/item-pile-config/item-pile-config.svelte","src/applications/item-pile-config/item-pile-config.js","src/foundry-ui-overrides.js","src/libwrapper.js","src/applications/settings-app/Setting.svelte","src/applications/editors/item-similarities-editor/item-similarities-editor.svelte","src/applications/editors/item-similarities-editor/item-similarities-editor.js","src/applications/editors/index.js","src/applications/settings-app/SettingButton.svelte","src/applications/settings-app/settings-shell.svelte","src/applications/settings-app/settings-app.js","src/settings.js","src/module.js"],"sourcesContent":["export default {\n \n \"VERSION\": \"1.0.0\",\n \n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\n \"ACTOR_CLASS_TYPE\": \"character\",\n \n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\n \n // The item price attribute is the path to the attribute on each item that determine how much it costs\n \"ITEM_PRICE_ATTRIBUTE\": \"data.price\",\n \n // Item filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\n \"ITEM_FILTERS\": [\n {\n \"path\": \"type\",\n \"filters\": \"spell,feat,class\"\n },\n {\n \"path\": \"data.weaponType\",\n \"filters\": \"natural\"\n }\n ],\n \n \"ITEM_TRANSFORMER\": async (itemData) => {\n [\"equipped\", \"proficient\", \"prepared\"].forEach(key => delete itemData.data[key]);\n itemData.data.attunement = Math.min(CONFIG.DND5E.attunementTypes.REQUIRED, itemData.data.attunement);\n if (itemData.type === \"spell\") {\n const scroll = await Item.implementation.createScrollFromSpell(itemData);\n itemData = scroll.data;\n }\n return itemData;\n },\n \n // Item similarities determines how item piles detect similarities and differences in the system\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\n \n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\n // In the case of attributes, the path is relative to the \"actor.data\"\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\n \"CURRENCIES\": [\n {\n type: \"attribute\",\n name: \"DND5E.CurrencyPP\",\n img: \"icons/commodities/currency/coin-inset-snail-silver.webp\",\n abbreviation: \"{#}PP\",\n data: {\n path: \"data.currency.pp\"\n },\n primary: false,\n exchangeRate: 10\n },\n {\n type: \"attribute\",\n name: \"DND5E.CurrencyGP\",\n img: \"icons/commodities/currency/coin-embossed-crown-gold.webp\",\n abbreviation: \"{#}GP\",\n data: {\n path: \"data.currency.gp\",\n },\n primary: true,\n exchangeRate: 1\n },\n {\n type: \"attribute\",\n name: \"DND5E.CurrencyEP\",\n img: \"icons/commodities/currency/coin-inset-copper-axe.webp\",\n abbreviation: \"{#}EP\",\n data: {\n path: \"data.currency.ep\",\n },\n primary: false,\n exchangeRate: 0.5\n },\n {\n type: \"attribute\",\n name: \"DND5E.CurrencySP\",\n img: \"icons/commodities/currency/coin-engraved-moon-silver.webp\",\n abbreviation: \"{#}SP\",\n data: {\n path: \"data.currency.sp\",\n },\n primary: false,\n exchangeRate: 0.1\n },\n {\n type: \"attribute\",\n name: \"DND5E.CurrencyCP\",\n img: \"icons/commodities/currency/coin-engraved-waves-copper.webp\",\n abbreviation: \"{#}CP\",\n data: {\n path: \"data.currency.cp\",\n },\n primary: false,\n exchangeRate: 0.01\n }\n ]\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"npc\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"attack,buff,class,feat,race,spell\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"attribute\",\r\n name: \"PF1.CurrencyPlatinumP\",\r\n img: \"systems/pf1/icons/items/inventory/coins-silver.jpg\",\r\n abbreviation: \"{#}PP\",\r\n data: {\r\n path: \"data.currency.gold\",\r\n },\r\n primary: true,\r\n exchangeRate: 10\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"DS4.CharacterCurrencyGold\",\r\n img: \"systems/pf1/icons/items/inventory/coin-gold.jpg\",\r\n abbreviation: \"{#}G\",\r\n data: {\r\n path: \"data.currency.gold\",\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"PF1.CurrencySilverP\",\r\n img: \"systems/pf1/icons/items/inventory/coin-silver.jpg\",\r\n abbreviation: \"{#}SP\",\r\n data: {\r\n path: \"data.currency.sp\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"PF1.CurrencyCopperP\",\r\n img: \"systems/pf1/icons/items/inventory/coin-copper.jpg\",\r\n abbreviation: \"{#}C\",\r\n data: {\r\n path: \"data.currency.cp\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.01\r\n }\r\n ]\r\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"loot\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\r\n\r\n // The item price attribute is the path to the attribute on each item that determine how much it costs\r\n \"ITEM_PRICE_ATTRIBUTE\": \"data.price\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"action,spell,melee,lore,heritage,feat,effect,class,background,ancestry\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\", \"data.temporary.value\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()`, put it into `data.item`, and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"item\",\r\n name: \"Platinum Pieces\",\r\n img: \"systems/pf2e/icons/equipment/treasure/currency/platinum-pieces.webp\",\r\n abbreviation: \"{#}PP\",\r\n data: {\r\n uuid: \"Compendium.pf2e.equipment-srd.JuNPeK5Qm1w6wpb4\"\r\n },\r\n primary: false,\r\n exchangeRate: 10\r\n },\r\n {\r\n type: \"item\",\r\n name: \"Gold Pieces\",\r\n img: \"systems/pf2e/icons/equipment/treasure/currency/gold-pieces.webp\",\r\n abbreviation: \"{#}GP\",\r\n data: {\r\n uuid: \"Compendium.pf2e.equipment-srd.B6B7tBWJSqOBz5zz\"\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n },\r\n {\r\n type: \"item\",\r\n name: \"Silver Pieces\",\r\n img: \"systems/pf2e/icons/equipment/treasure/currency/silver-pieces.webp\",\r\n abbreviation: \"{#}SP\",\r\n data: {\r\n uuid: \"Compendium.pf2e.equipment-srd.5Ew82vBF9YfaiY9f\"\r\n },\r\n primary: false,\r\n exchangeRate: 0.1\r\n },\r\n {\r\n type: \"item\",\r\n name: \"Copper Pieces\",\r\n img: \"systems/pf2e/icons/equipment/treasure/currency/copper-pieces.webp\",\r\n abbreviation: \"{#}CP\",\r\n data: {\r\n uuid: \"Compendium.pf2e.equipment-srd.lzJ8AVhRcbFul5fh\"\r\n },\r\n primary: false,\r\n exchangeRate: 0.01\r\n }\r\n ]\r\n}\r\n","// Item Piles Definitions for Foundry VTT Game System Dungeonslayers 4\n\nexport default {\n\n \"VERSION\": \"1.0.0\",\n\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\n \"ACTOR_CLASS_TYPE\": \"character\",\n\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\n\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\n \"ITEM_FILTERS\": [\n {\n \"path\": \"type\",\n \"filters\": \"spell,talent,racialAbility,language,alphabet,specialCreatureAbility\"\n }\n ],\n\n // Item similarities determines how item piles detect similarities and differences in the system\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\n\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\n // In the case of attributes, the path is relative to the \"actor.data\"\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\n \"CURRENCIES\": [\n {\n type: \"attribute\",\n name: \"DS4.CharacterCurrencyGold\",\n img: \"icons/commodities/currency/coin-embossed-crown-gold.webp\",\n abbreviation: \"{#}G\",\n data: {\n path: \"data.currency.gold\",\n },\n primary: true,\n exchangeRate: 1\n },\n {\n type: \"attribute\",\n name: \"DS4.CharacterCurrencySilver\",\n img: \"icons/commodities/currency/coin-inset-snail-silver.webp\",\n abbreviation: \"{#}S\",\n data: {\n path: \"data.currency.silver\",\n },\n primary: false,\n exchangeRate: 0.1\n },\n {\n type: \"attribute\",\n name: \"DS4.CharacterCurrencyCopper\",\n img: \"icons/commodities/currency/coin-engraved-waves-copper.webp\",\n abbreviation: \"{#}C\",\n data: {\n path: \"data.currency.copper\",\n },\n primary: false,\n exchangeRate: 0.01\n }\n ]\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"npc\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"spell,feat,class,race,attack,full-attack,buff,aura,alignment,enhancement,damage-type,material\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"attribute\",\r\n name: \"DND5E.CurrencyPP\",\r\n img: \"icons/commodities/currency/coin-inset-snail-silver.webp\",\r\n abbreviation: \"{#}PP\",\r\n data: {\r\n path: \"data.currency.pp\"\r\n },\r\n primary: false,\r\n exchangeRate: 10\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"DND5E.CurrencyGP\",\r\n img: \"icons/commodities/currency/coin-embossed-crown-gold.webp\",\r\n abbreviation: \"{#}GP\",\r\n data: {\r\n path: \"data.currency.gp\",\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"DND5E.CurrencySP\",\r\n img: \"icons/commodities/currency/coin-engraved-moon-silver.webp\",\r\n abbreviation: \"{#}SP\",\r\n data: {\r\n path: \"data.currency.sp\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"DND5E.CurrencyCP\",\r\n img: \"icons/commodities/currency/coin-engraved-waves-copper.webp\",\r\n abbreviation: \"{#}CP\",\r\n data: {\r\n path: \"data.currency.cp\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.01\r\n }\r\n ]\r\n}","export default {\n\n \"VERSION\": \"1.0.0\",\n\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\n \"ACTOR_CLASS_TYPE\": \"npc2\",\n\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\n\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\n \"ITEM_FILTERS\": [\n {\n \"path\": \"type\",\n \"filters\": \"attack,buff,class,feat,race,spell\"\n }\n ],\n\n // Item similarities determines how item piles detect similarities and differences in the system\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\n\n \"CURRENCIES\": {\n \"Credits\": [\n {\n type: \"attribute\",\n name: \"SFRPG.Currencies.Credits\",\n img: \"systems/sfrpg/icons/equipment/goods/credstick.jpg\",\n abbreviation: \"{#}C\",\n data: {\n path: \"data.currency.credit\",\n },\n primary: true,\n exchangeRate: 1\n }\n ],\n \"Universal Polymer Base\": [\n {\n type: \"attribute\",\n name: \"SFRPG.Currencies.UPBs\",\n img: \"systems/sfrpg/icons/equipment/goods/upb.jpg\",\n abbreviation: \"{#} UBP\",\n data: {\n path: \"data.currency.upb\",\n },\n primary: false,\n exchangeRate: 1\n }\n ]\n }\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"character\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"edge,hindrance,skill,power,ability\"\r\n }\r\n ],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"attribute\",\r\n name: \"SWADE.Currency\",\r\n img: \"icons/svg/coins.svg\",\r\n abbreviation: \"{#}T\",\r\n data: {\r\n path: \"data.details.currency\",\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n }\r\n ]\r\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"character\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.qtd\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"magia, poder, classe\"\r\n },\r\n {\r\n \"path\": \"data.tipoUso\",\r\n \"filters\": \"nat\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"attribute\",\r\n name: \"Ouro\",\r\n img: \"icons/commodities/currency/coin-embossed-insect-gold.webp\",\r\n abbreviation: \"{#}O\",\r\n data: {\r\n path: \"data.dinheiro.to\",\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"Prata\",\r\n img: \"icons/commodities/currency/coin-embossed-unicorn-silver.webp\",\r\n abbreviation: \"{#}P\",\r\n data: {\r\n path: \"data.dinheiro.tp\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.1\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"Cobre\",\r\n img: \"icons/commodities/currency/coin-engraved-waves-copper.webp\",\r\n abbreviation: \"{#}C\",\r\n data: {\r\n path: \"data.dinheiro.tc\",\r\n },\r\n primary: false,\r\n exchangeRate: 0.01\r\n }\r\n ]\r\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"character\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity.value\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"career,container,critical,disease,injury,mutation,prayer,psychology,talent,skill,spell,trait,extendedTest,vehicleMod,cargo\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": []\r\n}","export default {\r\n\r\n \"VERSION\": \"1.0.0\",\r\n\r\n // The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.\r\n \"ACTOR_CLASS_TYPE\": \"npc\",\r\n\r\n // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists\r\n \"ITEM_QUANTITY_ATTRIBUTE\": \"data.quantity\",\r\n\r\n // Item types and the filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes\r\n \"ITEM_FILTERS\": [\r\n {\r\n \"path\": \"type\",\r\n \"filters\": \"spell,strength,weakness,mastery,species,culture,ancestry,education,resource,npcfeature,moonsign,language,culturelore,statuseffect,spelleffect\"\r\n }\r\n ],\r\n\r\n // Item similarities determines how item piles detect similarities and differences in the system\r\n \"ITEM_SIMILARITIES\": [\"name\", \"type\", \"data.sufferedDamage\", \"data.quality\"],\r\n\r\n // Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)\r\n // In the case of attributes, the path is relative to the \"actor.data\"\r\n // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data\r\n \"CURRENCIES\": [\r\n {\r\n type: \"attribute\",\r\n name: \"Solare\",\r\n img: \"icons/commodities/currency/coins-assorted-mix-copper.webp\",\r\n abbreviation: \"{#}S\",\r\n data: {\r\n path: \"data.currency.S\",\r\n },\r\n primary: false,\r\n exchangeRate: 10000\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"Lunare\",\r\n img: \"icons/commodities/currency/coin-embossed-unicorn-silver.webp\",\r\n abbreviation: \"{#}L\",\r\n data: {\r\n path: \"data.currency.L\",\r\n },\r\n primary: false,\r\n exchangeRate: 100\r\n },\r\n {\r\n type: \"attribute\",\r\n name: \"Telare\",\r\n img: \"icons/commodities/currency/coins-assorted-mix-platinum.webp\",\r\n abbreviation: \"{#}T\",\r\n data: {\r\n path: \"data.currency.T\",\r\n },\r\n primary: true,\r\n exchangeRate: 1\r\n }\r\n ]\r\n}","import dnd5e from \"./systems/dnd5e.js\";\n\n// ↓ IMPORT SYSTEMS HERE ↓\nimport pf1 from \"./systems/pf1.js\";\nimport pf2e from \"./systems/pf2e.js\";\nimport ds4 from \"./systems/ds4.js\";\nimport d35e from \"./systems/d35e.js\";\nimport sfrpg from \"./systems/sfrpg.js\";\nimport swade from \"./systems/swade.js\";\nimport tormenta20 from \"./systems/tormenta20.js\";\nimport wfrp4e from \"./systems/wfrp4e.js\"\nimport splittermond from \"./systems/splittermond.js\"\n// ↑ IMPORT SYSTEMS HERE ↑\n\n/**\n * NOTE: YOUR PULL REQUEST WILL NOT BE ACCEPTED IF YOU DO NOT\n * FOLLOW THE CONVENTION IN THE D&D 5E SYSTEM FILE\n */\nexport const SYSTEMS = {\n\n SUPPORTED_SYSTEMS: {\n dnd5e,\n // ↓ ADD SYSTEMS HERE ↓\n pf1,\n pf2e,\n ds4,\n d35e,\n sfrpg,\n swade,\n tormenta20,\n wfrp4e,\n splittermond\n // ↑ ADD SYSTEMS HERE ↑\n },\n\n DEFAULT_SETTINGS: {\n ACTOR_CLASS_TYPE: \"\",\n ITEM_QUANTITY_ATTRIBUTE: \"\",\n ITEM_PRICE_ATTRIBUTE: \"\",\n ITEM_FILTERS: [],\n ITEM_SIMILARITIES: [],\n CURRENCIES: {\n \"itemBased\": false,\n \"list\": []\n }\n },\n\n get HAS_SYSTEM_SUPPORT() {\n return !!this.SUPPORTED_SYSTEMS?.[game.system.id];\n },\n\n get DATA() {\n return this.SUPPORTED_SYSTEMS?.[game.system.id] ?? this.DEFAULT_SETTINGS;\n }\n};","import { SYSTEMS } from \"../systems.js\";\r\n\r\nconst SETTINGS = {\r\n \r\n // Client settings\r\n OUTPUT_TO_CHAT: \"outputToChat\",\r\n INVERT_SHEET_OPEN: \"invertSheetOpen\",\r\n HIDE_ACTOR_HEADER_TEXT: \"hideActorHeaderText\",\r\n PRELOAD_FILES: \"preloadFiles\",\r\n DEBUG: \"debug\",\r\n DEBUG_HOOKS: \"debugHooks\",\r\n \r\n // Module Settings\r\n ENABLE_DROPPING_ITEMS: \"enableDroppingItems\",\r\n ENABLE_TRADING: \"enableTrading\",\r\n SHOW_TRADE_BUTTON: \"showTradeButton\",\r\n DELETE_EMPTY_PILES: \"deleteEmptyPiles\",\r\n INSPECT_ITEMS_IN_TRADE: \"inspectItemsInTrade\",\r\n \r\n // System Settings\r\n CURRENCIES: \"currencies\",\r\n ITEM_FILTERS: \"itemFilters\",\r\n ACTOR_CLASS_TYPE: \"actorClassType\",\r\n ITEM_QUANTITY_ATTRIBUTE: \"itemQuantityAttribute\",\r\n ITEM_PRICE_ATTRIBUTE: \"itemPriceAttribute\",\r\n ITEM_SIMILARITIES: \"itemSimilarities\",\r\n \r\n // Hidden settings\r\n DEFAULT_ITEM_PILE_JOURNAL_ID: \"defaultItemPileJournalID\",\r\n DEFAULT_ITEM_PILE_ACTOR_ID: \"defaultItemPileActorID\",\r\n SYSTEM_FOUND: \"systemFound\",\r\n SYSTEM_NOT_FOUND_WARNING_SHOWN: \"systemNotFoundWarningShown\",\r\n PRECONFIGURED_SYSTEM: \"preconfiguredSystem\",\r\n SYSTEM_VERSION: \"systemVersion\",\r\n\r\n GET_DEFAULT() {\r\n return foundry.utils.deepClone(SETTINGS.DEFAULTS())\r\n },\r\n \r\n GET_SYSTEM_DEFAULTS() {\r\n return Object.fromEntries(Object.entries(SETTINGS.GET_DEFAULT()).filter(entry => {\r\n return entry[1].system;\r\n }));\r\n },\r\n \r\n DEFAULTS: () => ({\r\n \r\n [SETTINGS.CURRENCIES]: {\r\n name: \"ITEM-PILES.Settings.Currencies.Title\",\r\n label: \"ITEM-PILES.Settings.Currencies.Label\",\r\n hint: \"ITEM-PILES.Settings.Currencies.Hint\",\r\n icon: \"fa fa-money-bill-alt\",\r\n application: \"currencies\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.CURRENCIES,\r\n type: Object\r\n },\r\n \r\n [SETTINGS.ITEM_FILTERS]: {\r\n name: \"ITEM-PILES.Settings.ItemFilters.Title\",\r\n label: \"ITEM-PILES.Settings.ItemFilters.Label\",\r\n hint: \"ITEM-PILES.Settings.ItemFilters.Hint\",\r\n icon: \"fa fa-filter\",\r\n application: \"item-filters\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.ITEM_FILTERS,\r\n type: Array\r\n },\r\n \r\n [SETTINGS.ITEM_SIMILARITIES]: {\r\n name: \"ITEM-PILES.Settings.ItemSimilarities.Title\",\r\n label: \"ITEM-PILES.Settings.ItemSimilarities.Label\",\r\n hint: \"ITEM-PILES.Settings.ItemSimilarities.Hint\",\r\n icon: \"fa fa-equals\",\r\n application: \"item-similarities\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.ITEM_SIMILARITIES,\r\n type: Array\r\n },\r\n \r\n [SETTINGS.ACTOR_CLASS_TYPE]: {\r\n name: \"ITEM-PILES.Settings.ActorClass.Title\",\r\n hint: \"ITEM-PILES.Settings.ActorClass.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.ACTOR_CLASS_TYPE,\r\n type: String\r\n },\r\n \r\n [SETTINGS.ITEM_QUANTITY_ATTRIBUTE]: {\r\n name: \"ITEM-PILES.Settings.Quantity.Title\",\r\n hint: \"ITEM-PILES.Settings.Quantity.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.ITEM_QUANTITY_ATTRIBUTE,\r\n type: String\r\n },\r\n \r\n [SETTINGS.ITEM_PRICE_ATTRIBUTE]: {\r\n name: \"ITEM-PILES.Settings.Price.Title\",\r\n hint: \"ITEM-PILES.Settings.Price.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n system: true,\r\n default: SYSTEMS.DATA.ITEM_PRICE_ATTRIBUTE,\r\n type: String\r\n },\r\n\r\n [SETTINGS.SYSTEM_VERSION]: {\r\n scope: \"world\",\r\n config: false,\r\n default: \"0.0.0\",\r\n type: String\r\n },\r\n \r\n [SETTINGS.DEFAULT_ITEM_PILE_ACTOR_ID]: {\r\n scope: \"world\",\r\n config: false,\r\n default: \"\",\r\n type: String\r\n },\r\n \r\n [SETTINGS.DEFAULT_ITEM_PILE_JOURNAL_ID]: {\r\n scope: \"world\",\r\n config: false,\r\n default: \"\",\r\n type: String\r\n },\r\n \r\n [SETTINGS.SYSTEM_FOUND]: {\r\n scope: \"world\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.SYSTEM_NOT_FOUND_WARNING_SHOWN]: {\r\n scope: \"world\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.PRECONFIGURED_SYSTEM]: {\r\n scope: \"world\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.OUTPUT_TO_CHAT]: {\r\n name: \"ITEM-PILES.Settings.OutputToChat.Title\",\r\n hint: \"ITEM-PILES.Settings.OutputToChat.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: 1,\r\n choices: [\r\n \"ITEM-PILES.Settings.OutputToChat.Off\",\r\n \"ITEM-PILES.Settings.OutputToChat.Public\",\r\n \"ITEM-PILES.Settings.OutputToChat.SelfGM\",\r\n \"ITEM-PILES.Settings.OutputToChat.Blind\",\r\n ],\r\n type: Number\r\n },\r\n \r\n [SETTINGS.INSPECT_ITEMS_IN_TRADE]: {\r\n name: \"ITEM-PILES.Settings.InspectItemsTrade.Title\",\r\n hint: \"ITEM-PILES.Settings.InspectItemsTrade.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: true,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.DELETE_EMPTY_PILES]: {\r\n name: \"ITEM-PILES.Settings.DeleteEmptyPiles.Title\",\r\n hint: \"ITEM-PILES.Settings.DeleteEmptyPiles.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.ENABLE_DROPPING_ITEMS]: {\r\n name: \"ITEM-PILES.Settings.EnableDroppingItems.Title\",\r\n hint: \"ITEM-PILES.Settings.EnableDroppingItems.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: true,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.ENABLE_TRADING]: {\r\n name: \"ITEM-PILES.Settings.EnableTrading.Title\",\r\n hint: \"ITEM-PILES.Settings.EnableTrading.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: true,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.SHOW_TRADE_BUTTON]: {\r\n name: \"ITEM-PILES.Settings.ShowTradeButton.Title\",\r\n hint: \"ITEM-PILES.Settings.ShowTradeButton.Hint\",\r\n scope: \"world\",\r\n config: false,\r\n default: true,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.INVERT_SHEET_OPEN]: {\r\n name: \"ITEM-PILES.Settings.InvertSheetOpen.Title\",\r\n hint: \"ITEM-PILES.Settings.InvertSheetOpen.Hint\",\r\n scope: \"client\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.HIDE_ACTOR_HEADER_TEXT]: {\r\n name: \"ITEM-PILES.Settings.HideActorHeaderText.Title\",\r\n hint: \"ITEM-PILES.Settings.HideActorHeaderText.Hint\",\r\n scope: \"client\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.PRELOAD_FILES]: {\r\n name: \"ITEM-PILES.Settings.PreloadFiles.Title\",\r\n hint: \"ITEM-PILES.Settings.PreloadFiles.Hint\",\r\n scope: \"client\",\r\n config: false,\r\n default: true,\r\n type: Boolean\r\n },\r\n \r\n [SETTINGS.DEBUG]: {\r\n name: \"ITEM-PILES.Settings.Debug.Title\",\r\n hint: \"ITEM-PILES.Settings.Debug.Hint\",\r\n scope: \"client\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n \r\n [SETTINGS.DEBUG_HOOKS]: {\r\n name: \"ITEM-PILES.Settings.DebugHooks.Title\",\r\n hint: \"ITEM-PILES.Settings.DebugHooks.Hint\",\r\n scope: \"client\",\r\n config: false,\r\n default: false,\r\n type: Boolean\r\n },\r\n \r\n })\r\n}\r\n\r\nexport default SETTINGS;","const module_name = \"item-piles\";\r\nconst module_path = `modules/${module_name}/`;\r\nconst baseFlag = `flags.${module_name}.`\r\n\r\nconst CONSTANTS = {\r\n \r\n MODULE_NAME: module_name,\r\n PATH: module_path,\r\n \r\n FLAGS: {\r\n PILE: baseFlag + \"data\",\r\n SHARING: baseFlag + \"sharing\",\r\n ITEM: baseFlag + \"item\",\r\n PUBLIC_TRADE_ID: baseFlag + \"publicTradeId\",\r\n TRADE_USERS: baseFlag + \"tradeUsers\",\r\n TEMPORARY_ITEM: baseFlag + \"temporary_item\"\r\n },\r\n \r\n ITEM_DEFAULTS: {\r\n hidden: false,\r\n notForSale: false,\r\n infiniteQuantity: false,\r\n displayQuantity: \"default\",\r\n free: false,\r\n disableNormalCost: false,\r\n prices: []\r\n },\r\n \r\n PILE_DEFAULTS: {\r\n // Core settings\r\n enabled: false,\r\n distance: 1,\r\n macro: \"\",\r\n deleteWhenEmpty: \"default\",\r\n canInspectItems: true,\r\n \r\n // Overrides\r\n overrideItemFilters: false,\r\n overrideCurrencies: false,\r\n \r\n // Token settings\r\n displayOne: false,\r\n showItemName: false,\r\n overrideSingleItemScale: false,\r\n singleItemScale: 1.0,\r\n \r\n // Sharing settings\r\n shareItemsEnabled: false,\r\n shareCurrenciesEnabled: true,\r\n takeAllEnabled: false,\r\n splitAllEnabled: true,\r\n activePlayers: false,\r\n \r\n // Container settings\r\n isContainer: false,\r\n closed: false,\r\n locked: false,\r\n closedImage: \"\",\r\n emptyImage: \"\",\r\n openedImage: \"\",\r\n lockedImage: \"\",\r\n closeSound: \"\",\r\n openSound: \"\",\r\n lockedSound: \"\",\r\n unlockedSound: \"\",\r\n \r\n // Merchant settings\r\n isMerchant: false,\r\n isClosed: false,\r\n infiniteQuantity: false,\r\n infiniteCurrencies: true,\r\n purchaseOnly: false,\r\n hideNewItems: false,\r\n displayQuantity: \"yes\",\r\n buyPriceModifier: 1,\r\n sellPriceModifier: 0.5,\r\n itemTypePriceModifiers: [],\r\n actorPriceModifiers: [],\r\n openTimes: {\r\n enabled: false,\r\n open: {\r\n hour: 9,\r\n minute: 0\r\n },\r\n close: {\r\n hour: 18,\r\n minute: 0\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport default CONSTANTS;","import CONSTANTS from \"../constants/constants.js\";\r\n\r\nexport const debounceManager = {\r\n \r\n debounces: {},\r\n \r\n setDebounce(id, method) {\r\n if (this.debounces[id]) {\r\n return this.debounces[id];\r\n }\r\n this.debounces[id] = debounce(function (...args) {\r\n delete debounceManager.debounces[id];\r\n return method(...args);\r\n }, 50);\r\n return this.debounces[id];\r\n }\r\n};\r\n\r\nexport const hooks = {\r\n run: true,\r\n _hooks: {},\r\n \r\n async runWithout(callback) {\r\n this.run = false;\r\n await callback();\r\n this.run = true;\r\n },\r\n \r\n call(hook, ...args) {\r\n if (!this.run) return;\r\n return Hooks.call(hook, ...args);\r\n },\r\n \r\n callAll(hook, ...args) {\r\n if (!this.run) return;\r\n return Hooks.callAll(hook, ...args);\r\n },\r\n \r\n on(hook, callback) {\r\n Hooks.on(hook, (...args) => {\r\n if (!this.run) return;\r\n callback(...args);\r\n });\r\n }\r\n}\r\n\r\nexport function wait(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n\r\nexport function getSetting(key) {\r\n return game.settings.get(CONSTANTS.MODULE_NAME, key);\r\n}\r\n\r\nexport function setSetting(key, value) {\r\n if (value === undefined) throw new Error(\"setSetting | value must not be undefined!\");\r\n return game.settings.set(CONSTANTS.MODULE_NAME, key, value);\r\n}\r\n\r\nexport function debug(msg, args = \"\") {\r\n if (game.settings.get(CONSTANTS.MODULE_NAME, \"debug\")) {\r\n console.log(`DEBUG | Item Piles | ${msg}`, args)\r\n }\r\n}\r\n\r\nexport function custom_notify(message) {\r\n message = `Item Piles | ${message}`;\r\n ui.notifications.notify(message);\r\n console.log(message.replace(\" \", \"\\n\"));\r\n}\r\n\r\nexport function custom_warning(warning, notify = false) {\r\n warning = `Item Piles | ${warning}`;\r\n if (notify) {\r\n ui.notifications.warn(warning);\r\n }\r\n console.warn(warning.replace(\" \", \"\\n\"));\r\n}\r\n\r\nexport function custom_error(error, notify = true) {\r\n error = `Item Piles | ${error}`;\r\n if (notify) {\r\n ui.notifications.error(error);\r\n }\r\n return new Error(error.replace(\" \", \"\\n\"));\r\n}\r\n\r\nexport function dialogLayout({\r\n title = \"Item Piles\",\r\n message,\r\n icon = \"fas fa-exclamation-triangle\",\r\n extraHtml = \"\"\r\n } = {}) {\r\n return `\r\n
\r\n
\r\n
${title}
\r\n
${message}
\r\n ${extraHtml}\r\n
\r\n `;\r\n}\r\n\r\n\r\nexport function isRealNumber(inNumber) {\r\n return !isNaN(inNumber)\r\n && typeof inNumber === \"number\"\r\n && isFinite(inNumber);\r\n}\r\n\r\nexport function isActiveGM(user) {\r\n return user.active && user.isGM;\r\n}\r\n\r\nexport function getActiveGMs() {\r\n return game.users.filter(isActiveGM);\r\n}\r\n\r\nexport function isResponsibleGM() {\r\n if (!game.user.isGM) {\r\n return false;\r\n }\r\n return !getActiveGMs().some(other => other.data._id < game.user.data._id);\r\n}\r\n\r\nexport function isGMConnected() {\r\n return !!Array.from(game.users).find(user => user.isGM && user.active);\r\n}\r\n\r\nexport function roundToDecimals(num, decimals) {\r\n return Number(num.toFixed(decimals));\r\n}","export function getActor(target) {\r\n if (target instanceof Actor) return target;\r\n if (stringIsUuid(target)) {\r\n target = fromUuidFast(target);\r\n }\r\n target = getDocument(target);\r\n return target?.actor ?? target;\r\n}\r\n\r\nexport function getToken(documentUuid) {\r\n const document = fromUuidFast(documentUuid);\r\n return document?.token || false;\r\n}\r\n\r\nexport function getDocument(target) {\r\n if (stringIsUuid(target)) {\r\n target = fromUuidFast(target);\r\n }\r\n return target?.document ?? target;\r\n}\r\n\r\nexport function stringIsUuid(inId) {\r\n return typeof inId === \"string\"\r\n && (inId.match(/\\./g) || []).length\r\n && !inId.endsWith(\".\");\r\n}\r\n\r\n/**\r\n * Retrieves an object from the scene using its UUID, avoiding compendiums as they would have to be async'd\r\n *\r\n * @param uuid\r\n * @returns {null}\r\n */\r\nexport function fromUuidFast(uuid) {\r\n let parts = uuid.split(\".\");\r\n let doc;\r\n \r\n const [docName, docId] = parts.slice(0, 2);\r\n parts = parts.slice(2);\r\n const collection = CONFIG[docName].collection.instance;\r\n doc = collection.get(docId);\r\n \r\n // Embedded Documents\r\n while (doc && (parts.length > 1)) {\r\n const [embeddedName, embeddedId] = parts.slice(0, 2);\r\n doc = doc.getEmbeddedDocument(embeddedName, embeddedId);\r\n parts = parts.slice(2);\r\n }\r\n return doc || null;\r\n}\r\n\r\nexport function getUuid(target) {\r\n if(stringIsUuid(target)) return target;\r\n const document = getDocument(target);\r\n return document?.uuid ?? false;\r\n}\r\n\r\n/**\r\n * Find and retrieves an item in a list of items\r\n *\r\n * @param {Array} items\r\n * @param {Item|Object} findItem\r\n * @returns {*}\r\n */\r\nexport function findSimilarItem(items, findItem) {\r\n \r\n const itemSimilarities = game.itempiles.ITEM_SIMILARITIES;\r\n \r\n const findItemId = findItem instanceof Item ? findItem.id : findItem._id;\r\n \r\n return items.find(item => {\r\n const itemId = item instanceof Item ? item.id : item._id;\r\n if (itemId && findItemId && itemId === findItemId) {\r\n return true;\r\n }\r\n \r\n const itemData = item instanceof Item ? item.toObject() : item;\r\n for (const path of itemSimilarities) {\r\n if (getProperty(itemData, path) !== getProperty(findItem, path)) {\r\n return false;\r\n }\r\n }\r\n \r\n return true;\r\n });\r\n}\r\n\r\nexport function setSimilarityProperties(obj, item){\r\n const itemData = item instanceof Item ? item.toObject() : item;\r\n setProperty(obj, \"_id\", itemData._id);\r\n game.itempiles.ITEM_SIMILARITIES.forEach(prop => {\r\n setProperty(obj, prop, getProperty(itemData, prop));\r\n })\r\n return obj;\r\n}\r\n\r\n/**\r\n * Returns a given item's quantity\r\n *\r\n * @param {Item/Object} item\r\n * @returns {number}\r\n */\r\nexport function getItemQuantity(item) {\r\n const itemData = item instanceof Item ? item.toObject() : item;\r\n return Number(getProperty(itemData, game.itempiles.ITEM_QUANTITY_ATTRIBUTE) ?? 0);\r\n}\r\n\r\n/**\r\n * Returns a given item's quantity\r\n *\r\n * @param {Object} itemData\r\n * @param {Number} quantity\r\n * @returns {Object}\r\n */\r\nexport function setItemQuantity(itemData, quantity) {\r\n setProperty(itemData, game.itempiles.ITEM_QUANTITY_ATTRIBUTE, quantity)\r\n return itemData;\r\n}\r\n\r\n/**\r\n * Retrieves all visible tokens on a given location\r\n *\r\n * @param position\r\n * @returns {Array}\r\n */\r\nexport function getTokensAtLocation(position) {\r\n const tokens = [...canvas.tokens.placeables].filter(token => token.visible);\r\n return tokens.filter(token => {\r\n return position.x >= token.x && position.x < (token.x + (token.data.width * canvas.grid.size))\r\n && position.y >= token.y && position.y < (token.y + (token.data.height * canvas.grid.size));\r\n });\r\n}\r\n\r\nexport function distance_between_rect(p1, p2) {\r\n \r\n const x1 = p1.x;\r\n const y1 = p1.y;\r\n const x1b = p1.x + p1.w;\r\n const y1b = p1.y + p1.h;\r\n \r\n const x2 = p2.x;\r\n const y2 = p2.y;\r\n const x2b = p2.x + p2.w;\r\n const y2b = p2.y + p2.h;\r\n \r\n const left = x2b < x1;\r\n const right = x1b < x2;\r\n const bottom = y2b < y1;\r\n const top = y1b < y2;\r\n \r\n if (top && left) {\r\n return distance_between({ x: x1, y: y1b }, { x: x2b, y: y2 });\r\n } else if (left && bottom) {\r\n return distance_between({ x: x1, y: y1 }, { x: x2b, y: y2b });\r\n } else if (bottom && right) {\r\n return distance_between({ x: x1b, y: y1 }, { x: x2, y: y2b });\r\n } else if (right && top) {\r\n return distance_between({ x: x1b, y: y1b }, { x: x2, y: y2 });\r\n } else if (left) {\r\n return x1 - x2b;\r\n } else if (right) {\r\n return x2 - x1b;\r\n } else if (bottom) {\r\n return y1 - y2b;\r\n } else if (top) {\r\n return y2 - y1b;\r\n }\r\n \r\n return 0;\r\n \r\n}\r\n\r\nexport function distance_between(a, b) {\r\n return new Ray(a, b).distance;\r\n}\r\n\r\nexport function grids_between_tokens(a, b) {\r\n return Math.floor(distance_between_rect(a, b) / canvas.grid.size) + 1\r\n}\r\n\r\nexport function tokens_close_enough(a, b, maxDistance) {\r\n const distance = grids_between_tokens(a, b);\r\n return maxDistance >= distance;\r\n}\r\n\r\nexport function refreshAppsWithDocument(doc, callback) {\r\n const apps = Object.values(ui.windows).filter(app => app.id.endsWith(doc.id));\r\n for (const app of apps) {\r\n if (app[callback]) {\r\n app[callback]();\r\n }\r\n }\r\n}","import * as Utilities from \"./utilities.js\"\nimport CONSTANTS from \"../constants/constants.js\";\nimport * as Helpers from \"./helpers.js\";\n\nfunction getFlagData(inDocument, flag, defaults) {\n const defaultFlags = foundry.utils.duplicate(defaults);\n const flags = getProperty(inDocument.data, flag) ?? {};\n const data = foundry.utils.duplicate(flags);\n return foundry.utils.mergeObject(defaultFlags, data);\n}\n\nexport function getItemFlagData(item) {\n return getFlagData(Utilities.getDocument(item), CONSTANTS.FLAGS.ITEM, CONSTANTS.ITEM_DEFAULTS);\n}\n\nexport function getActorFlagData(target) {\n return getFlagData(Utilities.getActor(target), CONSTANTS.FLAGS.PILE, CONSTANTS.PILE_DEFAULTS);\n}\n\nexport function isValidItemPile(target, data = false) {\n const targetActor = Utilities.getActor(target);\n const pileData = data || getActorFlagData(targetActor);\n return targetActor && pileData?.enabled;\n}\n\nexport function isItemPileContainer(target) {\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n return pileData?.enabled && pileData?.isContainer;\n}\n\nexport function isItemPileMerchant(target) {\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n return pileData?.enabled && pileData?.isMerchant;\n}\n\nexport function isItemPileClosed(target) {\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n if (!pileData?.enabled || !pileData?.isContainer) return false;\n return pileData.closed;\n}\n\nexport function isItemPileLocked(target) {\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n if (!pileData?.enabled || !pileData?.isContainer) return false;\n return pileData.locked;\n}\n\nexport function isItemPileEmpty(target) {\n \n const targetActor = Utilities.getActor(target);\n if (!targetActor) return false;\n \n const validItemPile = isValidItemPile(targetActor);\n if (!validItemPile) return false;\n \n const hasNoItems = getActorItems(targetActor).length === 0;\n const hasNoAttributes = getActorCurrencies(targetActor).length === 0;\n \n return validItemPile && hasNoItems && hasNoAttributes;\n \n}\n\nexport function shouldItemPileBeDeleted(targetUuid) {\n \n const target = Utilities.fromUuidFast(targetUuid);\n \n if (!(target instanceof TokenDocument)) return false;\n \n if (!isItemPileEmpty(target)) return false;\n \n const pileData = getActorFlagData(target);\n \n return {\n \"default\": Helpers.getSetting(\"deleteEmptyPiles\"),\n \"true\": true,\n \"false\": false\n }[pileData?.deleteWhenEmpty ?? \"default\"];\n \n}\n\nexport function getActorItems(target, { itemFilters = false } = {}) {\n const actor = Utilities.getActor(target);\n const actorItemFilters = itemFilters ? cleanItemFilters(itemFilters) : getActorItemFilters(actor);\n const currencies = getActorCurrencies(actor).map(entry => entry.id);\n return actor.items.filter(item => currencies.indexOf(item.id) === -1 && !isItemInvalid(actor, item, actorItemFilters));\n}\n\nexport function getActorCurrencies(target, { currencyList = false, getAll = false } = {}) {\n const actor = Utilities.getActor(target);\n const actorItems = Array.from(actor.items);\n currencyList = currencyList || getActorCurrencyList(actor);\n let currencies = currencyList.map((currency, index) => {\n if (currency.type === \"attribute\") {\n return {\n ...currency,\n quantity: getProperty(actor.data, currency.data.path) ?? 0,\n path: currency.data.path,\n id: currency.data.path,\n index\n }\n }\n const item = Utilities.findSimilarItem(actorItems, currency.data.item);\n return {\n ...currency,\n quantity: item ? Utilities.getItemQuantity(item) : 0,\n id: item?.id || null,\n item,\n index\n }\n });\n if (!getAll) {\n currencies = currencies.filter(currency => currency.quantity);\n }\n return currencies;\n}\n\nexport function getActorPrimaryCurrency(target) {\n const actor = Utilities.getActor(target);\n return getActorCurrencies(actor).find(currency => currency.primary);\n}\n\nexport function getActorCurrencyList(target) {\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n return (pileData.overrideCurrencies || game.itempiles.CURRENCIES).map(currency => {\n currency.name = game.i18n.localize(currency.name);\n return currency;\n });\n}\n\n\nexport function getActorItemFilters(target) {\n if (!target) return cleanItemFilters(game.itempiles.ITEM_FILTERS);\n const targetActor = Utilities.getActor(target);\n const pileData = getActorFlagData(targetActor);\n return isValidItemPile(targetActor) && pileData?.overrideItemFilters\n ? cleanItemFilters(pileData.overrideItemFilters)\n : cleanItemFilters(game.itempiles.ITEM_FILTERS);\n}\n\nexport function cleanItemFilters(itemFilters) {\n return itemFilters ? foundry.utils.duplicate(itemFilters).map(filter => {\n filter.path = filter.path.trim();\n filter.filters = Array.isArray(filter.filters) ? filter.filters : filter.filters.split(',').map(string => string.trim());\n filter.filters = new Set(filter.filters)\n return filter;\n }) : [];\n}\n\nexport function isItemInvalid(targetActor, item, itemFilters = false) {\n const pileItemFilters = itemFilters ? itemFilters : getActorItemFilters(targetActor)\n const itemData = item instanceof Item ? item.toObject() : item;\n for (const filter of pileItemFilters) {\n if (!hasProperty(itemData, filter.path)) continue;\n const attributeValue = getProperty(itemData, filter.path);\n if (filter.filters.has(attributeValue)) {\n return attributeValue;\n }\n }\n return false;\n}\n\nexport function isItemCurrency(item, { target = false } = {}) {\n const actor = Utilities.getActor(target ? target : item.parent);\n const currencies = getActorCurrencies(actor, { getAll: true })\n .filter(currency => currency.type === \"item\")\n .map(item => item.data.item);\n return !!Utilities.findSimilarItem(currencies, item);\n}\n\n\nexport function getItemPileTokenImage(token, { data = false, items = false, currencies = false } = {}) {\n \n const tokenDocument = Utilities.getDocument(token);\n \n const itemPileData = data || getActorFlagData(tokenDocument);\n \n let originalImg;\n if (tokenDocument instanceof TokenDocument) {\n originalImg = tokenDocument.data.img;\n } else {\n originalImg = tokenDocument.data.token.img;\n }\n \n if (!isValidItemPile(tokenDocument)) return originalImg;\n \n items = items || getActorItems(tokenDocument).map(item => item.toObject());\n currencies = currencies || getActorCurrencies(tokenDocument);\n \n const numItems = items.length + currencies.length;\n \n let img;\n \n if (itemPileData.displayOne && numItems === 1) {\n img = items.length > 0\n ? items[0].img\n : currencies[0].img;\n } else if (itemPileData.displayOne && numItems > 1) {\n img = (tokenDocument.actor ?? tokenDocument).data.token.img;\n }\n \n if (itemPileData.isContainer) {\n \n img = itemPileData.lockedImage || itemPileData.closedImage || itemPileData.openedImage || itemPileData.emptyImage;\n \n if (itemPileData.locked && itemPileData.lockedImage) {\n img = itemPileData.lockedImage;\n } else if (itemPileData.closed && itemPileData.closedImage) {\n img = itemPileData.closedImage;\n } else if (itemPileData.emptyImage && isItemPileEmpty(tokenDocument)) {\n img = itemPileData.emptyImage;\n } else if (itemPileData.openedImage) {\n img = itemPileData.openedImage;\n }\n \n }\n \n return img || originalImg;\n \n}\n\nexport function getItemPileTokenScale(target, { data = false, items = false, currencies = false } = {}) {\n \n const pileDocument = Utilities.getDocument(target);\n \n let itemPileData = data || getActorFlagData(pileDocument);\n \n let baseScale;\n if (pileDocument instanceof TokenDocument) {\n baseScale = pileDocument.data.scale;\n } else {\n baseScale = pileDocument.data.token.scale;\n }\n \n if (!isValidItemPile(pileDocument, itemPileData)) {\n return baseScale;\n }\n \n items = items || getActorItems(pileDocument);\n currencies = currencies || getActorCurrencies(pileDocument);\n \n const numItems = items.length + currencies.length;\n \n if (itemPileData.isContainer || !itemPileData.displayOne || !itemPileData.overrideSingleItemScale || numItems > 1 || numItems === 0) {\n return baseScale;\n }\n \n return itemPileData.singleItemScale;\n \n}\n\nexport function getItemPileName(target, { data = false, items = false, currencies = false } = {}) {\n \n const pileDocument = Utilities.getDocument(target);\n \n const itemPileData = data || getActorFlagData(pileDocument);\n \n let name = pileDocument instanceof TokenDocument\n ? pileDocument.data.name\n : pileDocument.data.token.name;\n \n if (!isValidItemPile(pileDocument, itemPileData)) {\n return name;\n }\n \n items = items || getActorItems(pileDocument);\n currencies = currencies || getActorCurrencies(pileDocument);\n \n const numItems = items.length + currencies.length;\n \n if (itemPileData.isContainer || !itemPileData.displayOne || !itemPileData.showItemName || numItems > 1 || numItems === 0) {\n return name;\n }\n \n const item = items.length > 0\n ? items[0]\n : currencies[0];\n \n return item.name;\n \n}\n\nfunction getRelevantTokensAndActor(target) {\n \n const relevantDocument = Utilities.getDocument(target);\n \n let documentActor;\n let documentTokens = [];\n \n if (relevantDocument instanceof Actor) {\n documentActor = relevantDocument;\n if (relevantDocument.token) {\n documentTokens.push(relevantDocument?.token);\n } else {\n documentTokens = canvas.tokens.placeables.filter(token => token.document.actor === documentActor).map(token => token.document);\n }\n } else {\n documentActor = relevantDocument.actor;\n if (relevantDocument.isLinked) {\n documentTokens = canvas.tokens.placeables.filter(token => token.document.actor === documentActor).map(token => token.document);\n } else {\n documentTokens.push(relevantDocument);\n }\n }\n \n return [documentActor, documentTokens]\n \n}\n\nexport async function updateItemPileData(target, flagData, tokenData) {\n \n if (!flagData) flagData = getActorFlagData(target);\n if (!tokenData) tokenData = {};\n \n const [documentActor, documentTokens] = getRelevantTokensAndActor(target);\n \n const items = getActorItems(documentActor, { itemFilters: flagData.overrideItemFilters });\n const currencies = getActorCurrencies(documentActor, { currencyList: flagData.overrideCurrencies });\n \n const pileData = { data: flagData, items, currencies };\n \n const updates = documentTokens.map(tokenDocument => {\n const newTokenData = foundry.utils.mergeObject(tokenData, {\n \"img\": getItemPileTokenImage(tokenDocument, pileData),\n \"scale\": getItemPileTokenScale(tokenDocument, pileData),\n \"name\": getItemPileName(tokenDocument, pileData),\n });\n return {\n \"_id\": tokenDocument.id,\n ...newTokenData,\n [CONSTANTS.FLAGS.PILE]: flagData\n }\n });\n \n await canvas.scene.updateEmbeddedDocuments(\"Token\", updates);\n \n return documentActor.update({\n [CONSTANTS.FLAGS.PILE]: flagData,\n [`token.${CONSTANTS.FLAGS.PILE}`]: flagData\n });\n \n}\n\nexport async function updateItemData(item, update) {\n const flagData = foundry.utils.mergeObject(getItemFlagData(item), update.flags ?? {});\n return item.update({\n ...update?.data ?? {},\n [CONSTANTS.FLAGS.ITEM]: flagData\n });\n}\n\n/* -------------------------- Merchant Methods ------------------------- */\n\nexport function getMerchantModifiersForActor(merchant, { item = false, actor = false, pileFlagData = false } = {}) {\n \n let {\n buyPriceModifier,\n sellPriceModifier,\n itemTypePriceModifiers,\n actorPriceModifiers\n } = pileFlagData || getActorFlagData(merchant);\n \n if (item) {\n const itemTypePriceModifier = itemTypePriceModifiers.find(priceData => priceData.type === item.type);\n if (itemTypePriceModifier) {\n buyPriceModifier = itemTypePriceModifier.override ? itemTypePriceModifier.buyPriceModifier : buyPriceModifier * itemTypePriceModifier.buyPriceModifier;\n sellPriceModifier = itemTypePriceModifier.override ? itemTypePriceModifier.sellPriceModifier : sellPriceModifier * itemTypePriceModifier.sellPriceModifier;\n }\n }\n \n if (actor && actorPriceModifiers) {\n const actorSpecificModifiers = actorPriceModifiers?.find(data => data.actorUuid === Utilities.getUuid(actor));\n if (actorSpecificModifiers) {\n buyPriceModifier = actorSpecificModifiers.override ? actorSpecificModifiers.buyPriceModifier : buyPriceModifier * actorSpecificModifiers.buyPriceModifier;\n sellPriceModifier = actorSpecificModifiers.override ? actorSpecificModifiers.sellPriceModifier : sellPriceModifier * actorSpecificModifiers.sellPriceModifier;\n }\n }\n \n return {\n buyPriceModifier,\n sellPriceModifier\n }\n}\n\nfunction getPriceArray(totalCost, currencies) {\n \n const smallestExchangeRate = Math.min(...currencies.map(currency => currency.exchangeRate));\n const decimals = smallestExchangeRate.toString().split(\".\")[1].length;\n \n let fraction = Helpers.roundToDecimals(totalCost % 1, decimals);\n let cost = Math.round(totalCost - fraction);\n \n const prices = [];\n \n const primaryCurrency = currencies.find(currency => currency.primary)\n if (cost) {\n prices.push({\n ...primaryCurrency,\n cost: cost,\n baseCost: cost,\n maxCurrencyCost: totalCost,\n string: primaryCurrency.abbreviation.replace('{#}', cost)\n });\n }\n \n for (const currency of currencies) {\n \n if (currency === primaryCurrency) continue;\n \n const numCurrency = Math.floor(Helpers.roundToDecimals(fraction / currency.exchangeRate, decimals));\n \n fraction = Helpers.roundToDecimals(fraction - (numCurrency * currency.exchangeRate), decimals);\n \n prices.push({\n ...currency,\n cost: Math.round(numCurrency),\n baseCost: Math.round(numCurrency),\n maxCurrencyCost: Math.ceil(totalCost / currency.exchangeRate),\n string: currency.abbreviation.replace(\"{#}\", numCurrency)\n });\n }\n \n prices.sort((a, b) => b.exchangeRate - a.exchangeRate);\n \n return prices;\n}\n\nexport function getItemPrices(item, {\n seller = false,\n buyer = false,\n sellerFlagData = false,\n buyerFlagData = false,\n itemFlagData = false,\n quantity = 1\n} = {}) {\n \n let priceData = [];\n \n buyerFlagData = buyerFlagData || getActorFlagData(buyer);\n if (!buyerFlagData?.enabled || !buyerFlagData?.isMerchant) {\n buyerFlagData = false;\n }\n \n sellerFlagData = sellerFlagData || getActorFlagData(seller);\n if (!sellerFlagData?.enabled || !sellerFlagData?.isMerchant) {\n sellerFlagData = false;\n }\n \n itemFlagData = itemFlagData || getItemFlagData(item);\n \n if (itemFlagData?.free) {\n return priceData;\n }\n \n let merchant = sellerFlagData ? seller : buyer;\n \n // Retrieve the item price modifiers\n let modifier = 1;\n if (sellerFlagData) {\n \n modifier = getMerchantModifiersForActor(seller, {\n item,\n actor: buyer,\n pileFlagData: sellerFlagData\n }).buyPriceModifier;\n \n } else if (buyerFlagData) {\n \n modifier = getMerchantModifiersForActor(buyer, {\n item,\n actor: seller,\n pileFlagData: buyerFlagData\n }).sellPriceModifier;\n \n }\n \n if (!modifier) {\n return priceData;\n }\n \n const currencyList = getActorCurrencyList(merchant);\n const currencies = getActorCurrencies(merchant, { currencyList, getAll: true });\n \n // In order to easily calculate an item's total worth, we can use the smallest exchange rate and convert all prices\n // to it, in order have a stable form of exchange calculation\n const smallestExchangeRate = Math.min(...currencies.map(currency => currency.exchangeRate));\n const decimals = smallestExchangeRate.toString().split(\".\")[1].length;\n \n // If the item does include its normal cost, we calculate that here\n if (!itemFlagData.disableNormalCost) {\n \n const overallCost = getProperty(item.toObject(), game.itempiles.ITEM_PRICE_ATTRIBUTE);\n \n // Base prices is the displayed price, without quantity taken into account\n const baseCost = Helpers.roundToDecimals(overallCost * modifier, decimals);\n const basePrices = getPriceArray(baseCost, currencies);\n \n // Prices is the cost with the amount of quantity taken into account, which may change the number of the different\n // types of currencies it costs (eg, an item wouldn't cost 1 gold and 100 silver, it would cost 11 gold\n let totalCost = Helpers.roundToDecimals(overallCost * modifier * quantity, decimals);\n let prices = getPriceArray(totalCost, currencies);\n \n if (baseCost) {\n \n priceData.push({\n basePrices,\n basePriceString: basePrices.filter(price => price.cost).map(price => price.string).join(\" \"),\n prices,\n priceString: prices.filter(price => price.cost).map(price => price.string).join(\" \"),\n totalCost,\n baseCost,\n primary: true,\n maxQuantity: 0,\n quantity\n });\n \n }\n }\n \n // If the item has custom prices, we include them here\n if (itemFlagData.prices.length) {\n \n priceData = priceData.concat(itemFlagData.prices.map(priceGroup => {\n const prices = priceGroup.map(price => {\n const itemModifier = price.fixed ? 1 : modifier;\n const cost = Math.round(price.quantity * itemModifier * quantity);\n const baseCost = Math.round(price.quantity * itemModifier);\n price.name = game.i18n.localize(price.name);\n return {\n ...price,\n cost,\n baseCost,\n priceString: cost ? price.abbreviation.replace(\"{#}\", cost) : \"\",\n basePriceString: baseCost ? price.abbreviation.replace(\"{#}\", baseCost) : \"\"\n };\n });\n \n return {\n prices,\n priceString: prices.filter(price => price.priceString).map(price => price.priceString).join(\" \"),\n basePriceString: prices.filter(price => price.basePriceString).map(price => price.basePriceString).join(\" \"),\n maxQuantity: 0,\n quantity\n }\n }));\n }\n \n const buyerInfiniteCurrencies = buyerFlagData?.infiniteCurrencies;\n const buyerInfiniteQuantity = buyerFlagData?.infiniteQuantity;\n \n // If there's a buyer, we also calculate how many of the item the buyer can afford\n if (!buyer) return priceData;\n \n const recipientCurrencies = getActorCurrencies(buyer, { currencyList });\n const totalCurrencies = recipientCurrencies.map(currency => currency.quantity * currency.exchangeRate).reduce((acc, num) => acc + num, 0);\n \n // For each price group, check for properties and items and make sure that the actor can afford it\n for (const priceGroup of priceData) {\n priceGroup.maxQuantity = Infinity;\n if (priceGroup.baseCost !== undefined) {\n if (buyerInfiniteCurrencies) continue;\n priceGroup.maxQuantity = Math.floor(totalCurrencies / priceGroup.baseCost);\n priceGroup.prices.forEach(price => {\n price.maxQuantity = priceGroup.maxQuantity;\n });\n } else {\n if (buyerInfiniteQuantity) continue;\n for (const price of priceGroup.prices) {\n if (price.type === \"attribute\") {\n const attributeQuantity = Number(getProperty(buyer.data, price.data.path));\n price.buyerQuantity = attributeQuantity;\n price.maxQuantity = Math.floor(attributeQuantity / price.baseCost);\n priceGroup.maxQuantity = Math.min(priceGroup.maxQuantity, price.maxQuantity)\n } else {\n const foundItem = Utilities.findSimilarItem(buyer.items, price.data.item);\n const itemQuantity = foundItem ? Utilities.getItemQuantity(foundItem) : 0;\n price.buyerQuantity = itemQuantity;\n price.maxQuantity = Math.floor(itemQuantity / price.baseCost);\n priceGroup.maxQuantity = Math.min(priceGroup.maxQuantity, price.maxQuantity);\n }\n }\n }\n }\n \n return priceData;\n}\n\nexport function getPricesForItems(itemsToBuy, {\n seller = false,\n buyer = false,\n sellerFlagData = false,\n buyerFlagData = false\n} = {}) {\n \n sellerFlagData = sellerFlagData || getActorFlagData(seller);\n if (!sellerFlagData?.enabled || !sellerFlagData?.isMerchant) {\n sellerFlagData = false;\n }\n \n buyerFlagData = buyerFlagData || getActorFlagData(buyer);\n if (!buyerFlagData?.enabled || !buyerFlagData?.isMerchant) {\n buyerFlagData = false;\n }\n \n const merchant = sellerFlagData ? seller : buyer;\n const currencyList = getActorCurrencyList(merchant);\n const currencies = getActorCurrencies(merchant, { currencyList, getAll: true });\n const smallestExchangeRate = Math.min(...currencies.map(currency => currency.exchangeRate));\n const decimals = smallestExchangeRate.toString().split(\".\")[1].length;\n \n const recipientCurrencies = getActorCurrencies(buyer, { currencyList, getAll: true });\n \n const paymentData = itemsToBuy.map(data => {\n const prices = getItemPrices(data.item, {\n seller,\n buyer,\n sellerFlagData,\n buyerFlagData,\n itemFlagData: data.itemFlagData,\n quantity: data.quantity || 1\n })[data.paymentIndex || 0];\n return {\n ...prices,\n item: data.item\n };\n })\n .reduce((priceData, priceGroup) => {\n \n if (!priceGroup.maxQuantity) return priceData;\n \n if (priceGroup.primary) {\n \n priceData.totalCurrencyCost = Helpers.roundToDecimals(priceData.totalCurrencyCost + priceGroup.totalCost, decimals);\n priceData.primary = true;\n \n } else {\n \n for (const price of priceGroup.prices) {\n \n let existingPrice = priceData.otherPrices.find(otherPrice => {\n return otherPrice.id === price.id || (otherPrice.name === price.name && otherPrice.img === price.img && otherPrice.type === price.type);\n });\n \n if (existingPrice) {\n existingPrice.cost += price.cost;\n } else {\n const index = priceData.otherPrices.push(price);\n existingPrice = priceData.otherPrices[index - 1];\n existingPrice.quantity = 0;\n }\n \n existingPrice.quantity += price.cost;\n existingPrice.buyerQuantity -= price.cost;\n \n if (existingPrice.buyerQuantity < 0) {\n priceData.canBuy = false;\n }\n }\n }\n \n priceData.buyerReceive.push({\n type: \"item\",\n name: priceGroup.item.name,\n img: priceGroup.item.img,\n quantity: priceGroup.quantity,\n item: priceGroup.item,\n \n });\n \n return priceData;\n \n }, {\n totalCurrencyCost: 0,\n canBuy: true,\n primary: false,\n finalPrices: [],\n otherPrices: [],\n \n buyerReceive: [],\n buyerChange: [],\n sellerReceive: []\n });\n \n if (paymentData.totalCurrencyCost) {\n \n // The price array that we need to fill\n const prices = getPriceArray(paymentData.totalCurrencyCost, recipientCurrencies);\n \n // This is the target price amount we need to hit\n let priceLeft = paymentData.totalCurrencyCost;\n \n // Starting from the smallest currency increment in the price\n for (let i = prices.length - 1; i >= 0; i--) {\n \n const price = prices[i];\n \n const buyerPrice = {\n ...price,\n buyerQuantity: price.quantity,\n quantity: 0,\n isCurrency: true\n }\n \n if (price.type === \"item\") {\n buyerPrice.item = price.data.item;\n }\n \n // If we have met the price target (or exceeded it, eg, we need change), populate empty entry\n if (priceLeft <= 0 || !price.cost) {\n paymentData.finalPrices.push(buyerPrice);\n continue;\n }\n \n // If the buyer does not have enough to cover the cost, put what we can into it, otherwise all of it\n buyerPrice.quantity = buyerPrice.buyerQuantity < price.cost ? buyerPrice.buyerQuantity : price.cost;\n \n // If it's the primary currency\n if (price.primary) {\n // And the buyer has enough of the primary currency to cover the rest of the price, use that\n const totalCurrencyValue = Helpers.roundToDecimals(buyerPrice.buyerQuantity * price.exchangeRate, decimals);\n if (totalCurrencyValue > priceLeft) {\n buyerPrice.quantity = Math.ceil(priceLeft);\n }\n }\n \n paymentData.finalPrices.push(buyerPrice);\n \n // Then adjust the remaining price - if this goes below zero, we will need change back\n priceLeft = Helpers.roundToDecimals(priceLeft - (buyerPrice.quantity * price.exchangeRate), decimals);\n \n }\n \n paymentData.finalPrices.reverse();\n \n // If there's STILL some remaining price (eg, we haven't been able to scrounge up enough currency to pay for it)\n // we can start using the larger currencies, such as platinum in D&D 5e\n if (priceLeft > 0) {\n \n // We then need to loop through each price, and check if we have any more left over\n for (const buyerPrice of paymentData.finalPrices) {\n \n // If we don't, look for the next one\n let buyerCurrencyQuantity = buyerPrice.buyerQuantity - buyerPrice.quantity;\n if (!buyerCurrencyQuantity) continue;\n \n // Otherwise, add enough to cover the remaining cost\n const newQuantity = Math.ceil(Math.min(buyerCurrencyQuantity, priceLeft / buyerPrice.exchangeRate));\n buyerPrice.quantity += newQuantity;\n priceLeft = Helpers.roundToDecimals(priceLeft - (newQuantity * buyerPrice.exchangeRate), decimals);\n \n if (priceLeft <= 0) break;\n \n }\n }\n \n // Since the change will be negative, we'll need to flip it, since this is what we'll get back\n let change = Math.abs(priceLeft);\n for (const currency of currencies) {\n \n if (!change) break;\n \n // Get the remaining price, and normalize it to this currency\n let numCurrency = Math.floor(Helpers.roundToDecimals(change / currency.exchangeRate, decimals));\n change = Helpers.roundToDecimals(change - (numCurrency * currency.exchangeRate), decimals);\n \n // If there's some currencies to be gotten back\n if (numCurrency) {\n // We check if we've paid with this currency\n const payment = paymentData.finalPrices.find(payment => {\n return payment.id === currency.id || (payment.name === currency.name && payment.img === currency.img && payment.type === currency.type);\n });\n if (!payment) continue;\n \n // If we have paid with this currency, and we're getting some back, we can do one of two things:\n if ((payment.quantity - numCurrency) >= 0) {\n // Either just subtract it from the total paid if some of our payment will still remain\n // IE, the change we got back didn't cancel out the payment\n payment.quantity -= numCurrency;\n } else {\n // Or if it does cancel out our payment, we add that to the change we'll get back and remove the payment entirely\n paymentData.buyerChange.push({\n ...currency,\n isCurrency: true,\n quantity: numCurrency - payment.quantity\n });\n payment.quantity = 0;\n }\n }\n }\n \n // Copy the final currencies that the seller will get\n paymentData.sellerReceive = paymentData.finalPrices.map(price => {\n return { ...price };\n });\n \n // But, we'll need to make sure they have enough change to _give_ to the buyer\n // We collate the total amount of change needed\n let changeNeeded = paymentData.buyerChange.reduce((acc, change) => {\n const currency = currencies.find(currency => {\n return change.id === currency.id || (change.name === currency.name && change.img === currency.img && change.type === currency.type);\n });\n return acc + currency.quantity >= change.quantity ? 0 : (change.quantity - currency.quantity) * change.exchangeRate;\n }, 0);\n \n // If the seller needs give the buyer some change, we'll modify the payment they'll get to cover for it\n if (changeNeeded) {\n \n // If the seller is being given enough of the primary currency to cover for the cost, we use that\n const primaryCurrency = paymentData.sellerReceive.find(price => price.primary && (price.quantity * price.exchangeRate) > changeNeeded);\n if (primaryCurrency) {\n primaryCurrency.quantity--;\n changeNeeded -= 1 * primaryCurrency.exchangeRate;\n } else {\n // Otherwise, we'll use the biggest currency we can find to cover for it\n const biggestCurrency = paymentData.sellerReceive.find(price => price.quantity && (price.quantity * price.exchangeRate) > changeNeeded);\n biggestCurrency.quantity--;\n changeNeeded -= 1 * biggestCurrency.exchangeRate;\n }\n \n changeNeeded = Math.abs(changeNeeded);\n \n // Then loop through each currency and add enough currency so that the total adds up\n for (const currency of paymentData.sellerReceive) {\n if (!changeNeeded) break;\n let numCurrency = Math.floor(Helpers.roundToDecimals(changeNeeded / currency.exchangeRate, decimals));\n changeNeeded = Helpers.roundToDecimals(changeNeeded - (numCurrency * currency.exchangeRate), decimals);\n currency.quantity += numCurrency;\n }\n }\n }\n \n paymentData.finalPrices = paymentData.finalPrices.concat(paymentData.otherPrices);\n paymentData.sellerReceive = paymentData.sellerReceive.concat(paymentData.otherPrices);\n \n paymentData.basePriceString = paymentData.finalPrices\n .filter(price => price.cost)\n .map(price => {\n return price.abbreviation.replace(\"{#}\", price.cost)\n }).join(\" \");\n \n delete paymentData.otherPrices;\n \n return paymentData;\n \n}","function noop() { }\nconst identity = x => x;\nfunction assign(tar, src) {\n // @ts-ignore\n for (const k in src)\n tar[k] = src[k];\n return tar;\n}\nfunction is_promise(value) {\n return value && typeof value === 'object' && typeof value.then === 'function';\n}\nfunction add_location(element, file, line, column, char) {\n element.__svelte_meta = {\n loc: { file, line, column, char }\n };\n}\nfunction run(fn) {\n return fn();\n}\nfunction blank_object() {\n return Object.create(null);\n}\nfunction run_all(fns) {\n fns.forEach(run);\n}\nfunction is_function(thing) {\n return typeof thing === 'function';\n}\nfunction safe_not_equal(a, b) {\n return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');\n}\nlet src_url_equal_anchor;\nfunction src_url_equal(element_src, url) {\n if (!src_url_equal_anchor) {\n src_url_equal_anchor = document.createElement('a');\n }\n src_url_equal_anchor.href = url;\n return element_src === src_url_equal_anchor.href;\n}\nfunction not_equal(a, b) {\n return a != a ? b == b : a !== b;\n}\nfunction is_empty(obj) {\n return Object.keys(obj).length === 0;\n}\nfunction validate_store(store, name) {\n if (store != null && typeof store.subscribe !== 'function') {\n throw new Error(`'${name}' is not a store with a 'subscribe' method`);\n }\n}\nfunction subscribe(store, ...callbacks) {\n if (store == null) {\n return noop;\n }\n const unsub = store.subscribe(...callbacks);\n return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;\n}\nfunction get_store_value(store) {\n let value;\n subscribe(store, _ => value = _)();\n return value;\n}\nfunction component_subscribe(component, store, callback) {\n component.$$.on_destroy.push(subscribe(store, callback));\n}\nfunction create_slot(definition, ctx, $$scope, fn) {\n if (definition) {\n const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);\n return definition[0](slot_ctx);\n }\n}\nfunction get_slot_context(definition, ctx, $$scope, fn) {\n return definition[1] && fn\n ? assign($$scope.ctx.slice(), definition[1](fn(ctx)))\n : $$scope.ctx;\n}\nfunction get_slot_changes(definition, $$scope, dirty, fn) {\n if (definition[2] && fn) {\n const lets = definition[2](fn(dirty));\n if ($$scope.dirty === undefined) {\n return lets;\n }\n if (typeof lets === 'object') {\n const merged = [];\n const len = Math.max($$scope.dirty.length, lets.length);\n for (let i = 0; i < len; i += 1) {\n merged[i] = $$scope.dirty[i] | lets[i];\n }\n return merged;\n }\n return $$scope.dirty | lets;\n }\n return $$scope.dirty;\n}\nfunction update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {\n if (slot_changes) {\n const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);\n slot.p(slot_context, slot_changes);\n }\n}\nfunction update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {\n const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);\n update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);\n}\nfunction get_all_dirty_from_scope($$scope) {\n if ($$scope.ctx.length > 32) {\n const dirty = [];\n const length = $$scope.ctx.length / 32;\n for (let i = 0; i < length; i++) {\n dirty[i] = -1;\n }\n return dirty;\n }\n return -1;\n}\nfunction exclude_internal_props(props) {\n const result = {};\n for (const k in props)\n if (k[0] !== '$')\n result[k] = props[k];\n return result;\n}\nfunction compute_rest_props(props, keys) {\n const rest = {};\n keys = new Set(keys);\n for (const k in props)\n if (!keys.has(k) && k[0] !== '$')\n rest[k] = props[k];\n return rest;\n}\nfunction compute_slots(slots) {\n const result = {};\n for (const key in slots) {\n result[key] = true;\n }\n return result;\n}\nfunction once(fn) {\n let ran = false;\n return function (...args) {\n if (ran)\n return;\n ran = true;\n fn.call(this, ...args);\n };\n}\nfunction null_to_empty(value) {\n return value == null ? '' : value;\n}\nfunction set_store_value(store, ret, value) {\n store.set(value);\n return ret;\n}\nconst has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);\nfunction action_destroyer(action_result) {\n return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;\n}\n\nconst is_client = typeof window !== 'undefined';\nlet now = is_client\n ? () => window.performance.now()\n : () => Date.now();\nlet raf = is_client ? cb => requestAnimationFrame(cb) : noop;\n// used internally for testing\nfunction set_now(fn) {\n now = fn;\n}\nfunction set_raf(fn) {\n raf = fn;\n}\n\nconst tasks = new Set();\nfunction run_tasks(now) {\n tasks.forEach(task => {\n if (!task.c(now)) {\n tasks.delete(task);\n task.f();\n }\n });\n if (tasks.size !== 0)\n raf(run_tasks);\n}\n/**\n * For testing purposes only!\n */\nfunction clear_loops() {\n tasks.clear();\n}\n/**\n * Creates a new task that runs on each raf frame\n * until it returns a falsy value or is aborted\n */\nfunction loop(callback) {\n let task;\n if (tasks.size === 0)\n raf(run_tasks);\n return {\n promise: new Promise(fulfill => {\n tasks.add(task = { c: callback, f: fulfill });\n }),\n abort() {\n tasks.delete(task);\n }\n };\n}\n\n// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM\n// at the end of hydration without touching the remaining nodes.\nlet is_hydrating = false;\nfunction start_hydrating() {\n is_hydrating = true;\n}\nfunction end_hydrating() {\n is_hydrating = false;\n}\nfunction upper_bound(low, high, key, value) {\n // Return first index of value larger than input value in the range [low, high)\n while (low < high) {\n const mid = low + ((high - low) >> 1);\n if (key(mid) <= value) {\n low = mid + 1;\n }\n else {\n high = mid;\n }\n }\n return low;\n}\nfunction init_hydrate(target) {\n if (target.hydrate_init)\n return;\n target.hydrate_init = true;\n // We know that all children have claim_order values since the unclaimed have been detached if target is not \n let children = target.childNodes;\n // If target is , there may be children without claim_order\n if (target.nodeName === 'HEAD') {\n const myChildren = [];\n for (let i = 0; i < children.length; i++) {\n const node = children[i];\n if (node.claim_order !== undefined) {\n myChildren.push(node);\n }\n }\n children = myChildren;\n }\n /*\n * Reorder claimed children optimally.\n * We can reorder claimed children optimally by finding the longest subsequence of\n * nodes that are already claimed in order and only moving the rest. The longest\n * subsequence subsequence of nodes that are claimed in order can be found by\n * computing the longest increasing subsequence of .claim_order values.\n *\n * This algorithm is optimal in generating the least amount of reorder operations\n * possible.\n *\n * Proof:\n * We know that, given a set of reordering operations, the nodes that do not move\n * always form an increasing subsequence, since they do not move among each other\n * meaning that they must be already ordered among each other. Thus, the maximal\n * set of nodes that do not move form a longest increasing subsequence.\n */\n // Compute longest increasing subsequence\n // m: subsequence length j => index k of smallest value that ends an increasing subsequence of length j\n const m = new Int32Array(children.length + 1);\n // Predecessor indices + 1\n const p = new Int32Array(children.length);\n m[0] = -1;\n let longest = 0;\n for (let i = 0; i < children.length; i++) {\n const current = children[i].claim_order;\n // Find the largest subsequence length such that it ends in a value less than our current value\n // upper_bound returns first greater value, so we subtract one\n // with fast path for when we are on the current longest subsequence\n const seqLen = ((longest > 0 && children[m[longest]].claim_order <= current) ? longest + 1 : upper_bound(1, longest, idx => children[m[idx]].claim_order, current)) - 1;\n p[i] = m[seqLen] + 1;\n const newLen = seqLen + 1;\n // We can guarantee that current is the smallest value. Otherwise, we would have generated a longer sequence.\n m[newLen] = i;\n longest = Math.max(newLen, longest);\n }\n // The longest increasing subsequence of nodes (initially reversed)\n const lis = [];\n // The rest of the nodes, nodes that will be moved\n const toMove = [];\n let last = children.length - 1;\n for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {\n lis.push(children[cur - 1]);\n for (; last >= cur; last--) {\n toMove.push(children[last]);\n }\n last--;\n }\n for (; last >= 0; last--) {\n toMove.push(children[last]);\n }\n lis.reverse();\n // We sort the nodes being moved to guarantee that their insertion order matches the claim order\n toMove.sort((a, b) => a.claim_order - b.claim_order);\n // Finally, we move the nodes\n for (let i = 0, j = 0; i < toMove.length; i++) {\n while (j < lis.length && toMove[i].claim_order >= lis[j].claim_order) {\n j++;\n }\n const anchor = j < lis.length ? lis[j] : null;\n target.insertBefore(toMove[i], anchor);\n }\n}\nfunction append(target, node) {\n target.appendChild(node);\n}\nfunction append_styles(target, style_sheet_id, styles) {\n const append_styles_to = get_root_for_style(target);\n if (!append_styles_to.getElementById(style_sheet_id)) {\n const style = element('style');\n style.id = style_sheet_id;\n style.textContent = styles;\n append_stylesheet(append_styles_to, style);\n }\n}\nfunction get_root_for_style(node) {\n if (!node)\n return document;\n const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;\n if (root && root.host) {\n return root;\n }\n return node.ownerDocument;\n}\nfunction append_empty_stylesheet(node) {\n const style_element = element('style');\n append_stylesheet(get_root_for_style(node), style_element);\n return style_element.sheet;\n}\nfunction append_stylesheet(node, style) {\n append(node.head || node, style);\n}\nfunction append_hydration(target, node) {\n if (is_hydrating) {\n init_hydrate(target);\n if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentElement !== target))) {\n target.actual_end_child = target.firstChild;\n }\n // Skip nodes of undefined ordering\n while ((target.actual_end_child !== null) && (target.actual_end_child.claim_order === undefined)) {\n target.actual_end_child = target.actual_end_child.nextSibling;\n }\n if (node !== target.actual_end_child) {\n // We only insert if the ordering of this node should be modified or the parent node is not target\n if (node.claim_order !== undefined || node.parentNode !== target) {\n target.insertBefore(node, target.actual_end_child);\n }\n }\n else {\n target.actual_end_child = node.nextSibling;\n }\n }\n else if (node.parentNode !== target || node.nextSibling !== null) {\n target.appendChild(node);\n }\n}\nfunction insert(target, node, anchor) {\n target.insertBefore(node, anchor || null);\n}\nfunction insert_hydration(target, node, anchor) {\n if (is_hydrating && !anchor) {\n append_hydration(target, node);\n }\n else if (node.parentNode !== target || node.nextSibling != anchor) {\n target.insertBefore(node, anchor || null);\n }\n}\nfunction detach(node) {\n node.parentNode.removeChild(node);\n}\nfunction destroy_each(iterations, detaching) {\n for (let i = 0; i < iterations.length; i += 1) {\n if (iterations[i])\n iterations[i].d(detaching);\n }\n}\nfunction element(name) {\n return document.createElement(name);\n}\nfunction element_is(name, is) {\n return document.createElement(name, { is });\n}\nfunction object_without_properties(obj, exclude) {\n const target = {};\n for (const k in obj) {\n if (has_prop(obj, k)\n // @ts-ignore\n && exclude.indexOf(k) === -1) {\n // @ts-ignore\n target[k] = obj[k];\n }\n }\n return target;\n}\nfunction svg_element(name) {\n return document.createElementNS('http://www.w3.org/2000/svg', name);\n}\nfunction text(data) {\n return document.createTextNode(data);\n}\nfunction space() {\n return text(' ');\n}\nfunction empty() {\n return text('');\n}\nfunction listen(node, event, handler, options) {\n node.addEventListener(event, handler, options);\n return () => node.removeEventListener(event, handler, options);\n}\nfunction prevent_default(fn) {\n return function (event) {\n event.preventDefault();\n // @ts-ignore\n return fn.call(this, event);\n };\n}\nfunction stop_propagation(fn) {\n return function (event) {\n event.stopPropagation();\n // @ts-ignore\n return fn.call(this, event);\n };\n}\nfunction self(fn) {\n return function (event) {\n // @ts-ignore\n if (event.target === this)\n fn.call(this, event);\n };\n}\nfunction trusted(fn) {\n return function (event) {\n // @ts-ignore\n if (event.isTrusted)\n fn.call(this, event);\n };\n}\nfunction attr(node, attribute, value) {\n if (value == null)\n node.removeAttribute(attribute);\n else if (node.getAttribute(attribute) !== value)\n node.setAttribute(attribute, value);\n}\nfunction set_attributes(node, attributes) {\n // @ts-ignore\n const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);\n for (const key in attributes) {\n if (attributes[key] == null) {\n node.removeAttribute(key);\n }\n else if (key === 'style') {\n node.style.cssText = attributes[key];\n }\n else if (key === '__value') {\n node.value = node[key] = attributes[key];\n }\n else if (descriptors[key] && descriptors[key].set) {\n node[key] = attributes[key];\n }\n else {\n attr(node, key, attributes[key]);\n }\n }\n}\nfunction set_svg_attributes(node, attributes) {\n for (const key in attributes) {\n attr(node, key, attributes[key]);\n }\n}\nfunction set_custom_element_data(node, prop, value) {\n if (prop in node) {\n node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;\n }\n else {\n attr(node, prop, value);\n }\n}\nfunction xlink_attr(node, attribute, value) {\n node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);\n}\nfunction get_binding_group_value(group, __value, checked) {\n const value = new Set();\n for (let i = 0; i < group.length; i += 1) {\n if (group[i].checked)\n value.add(group[i].__value);\n }\n if (!checked) {\n value.delete(__value);\n }\n return Array.from(value);\n}\nfunction to_number(value) {\n return value === '' ? null : +value;\n}\nfunction time_ranges_to_array(ranges) {\n const array = [];\n for (let i = 0; i < ranges.length; i += 1) {\n array.push({ start: ranges.start(i), end: ranges.end(i) });\n }\n return array;\n}\nfunction children(element) {\n return Array.from(element.childNodes);\n}\nfunction init_claim_info(nodes) {\n if (nodes.claim_info === undefined) {\n nodes.claim_info = { last_index: 0, total_claimed: 0 };\n }\n}\nfunction claim_node(nodes, predicate, processNode, createNode, dontUpdateLastIndex = false) {\n // Try to find nodes in an order such that we lengthen the longest increasing subsequence\n init_claim_info(nodes);\n const resultNode = (() => {\n // We first try to find an element after the previous one\n for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {\n const node = nodes[i];\n if (predicate(node)) {\n const replacement = processNode(node);\n if (replacement === undefined) {\n nodes.splice(i, 1);\n }\n else {\n nodes[i] = replacement;\n }\n if (!dontUpdateLastIndex) {\n nodes.claim_info.last_index = i;\n }\n return node;\n }\n }\n // Otherwise, we try to find one before\n // We iterate in reverse so that we don't go too far back\n for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {\n const node = nodes[i];\n if (predicate(node)) {\n const replacement = processNode(node);\n if (replacement === undefined) {\n nodes.splice(i, 1);\n }\n else {\n nodes[i] = replacement;\n }\n if (!dontUpdateLastIndex) {\n nodes.claim_info.last_index = i;\n }\n else if (replacement === undefined) {\n // Since we spliced before the last_index, we decrease it\n nodes.claim_info.last_index--;\n }\n return node;\n }\n }\n // If we can't find any matching node, we create a new one\n return createNode();\n })();\n resultNode.claim_order = nodes.claim_info.total_claimed;\n nodes.claim_info.total_claimed += 1;\n return resultNode;\n}\nfunction claim_element_base(nodes, name, attributes, create_element) {\n return claim_node(nodes, (node) => node.nodeName === name, (node) => {\n const remove = [];\n for (let j = 0; j < node.attributes.length; j++) {\n const attribute = node.attributes[j];\n if (!attributes[attribute.name]) {\n remove.push(attribute.name);\n }\n }\n remove.forEach(v => node.removeAttribute(v));\n return undefined;\n }, () => create_element(name));\n}\nfunction claim_element(nodes, name, attributes) {\n return claim_element_base(nodes, name, attributes, element);\n}\nfunction claim_svg_element(nodes, name, attributes) {\n return claim_element_base(nodes, name, attributes, svg_element);\n}\nfunction claim_text(nodes, data) {\n return claim_node(nodes, (node) => node.nodeType === 3, (node) => {\n const dataStr = '' + data;\n if (node.data.startsWith(dataStr)) {\n if (node.data.length !== dataStr.length) {\n return node.splitText(dataStr.length);\n }\n }\n else {\n node.data = dataStr;\n }\n }, () => text(data), true // Text nodes should not update last index since it is likely not worth it to eliminate an increasing subsequence of actual elements\n );\n}\nfunction claim_space(nodes) {\n return claim_text(nodes, ' ');\n}\nfunction find_comment(nodes, text, start) {\n for (let i = start; i < nodes.length; i += 1) {\n const node = nodes[i];\n if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) {\n return i;\n }\n }\n return nodes.length;\n}\nfunction claim_html_tag(nodes, is_svg) {\n // find html opening tag\n const start_index = find_comment(nodes, 'HTML_TAG_START', 0);\n const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);\n if (start_index === end_index) {\n return new HtmlTagHydration(undefined, is_svg);\n }\n init_claim_info(nodes);\n const html_tag_nodes = nodes.splice(start_index, end_index - start_index + 1);\n detach(html_tag_nodes[0]);\n detach(html_tag_nodes[html_tag_nodes.length - 1]);\n const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);\n for (const n of claimed_nodes) {\n n.claim_order = nodes.claim_info.total_claimed;\n nodes.claim_info.total_claimed += 1;\n }\n return new HtmlTagHydration(claimed_nodes, is_svg);\n}\nfunction set_data(text, data) {\n data = '' + data;\n if (text.wholeText !== data)\n text.data = data;\n}\nfunction set_input_value(input, value) {\n input.value = value == null ? '' : value;\n}\nfunction set_input_type(input, type) {\n try {\n input.type = type;\n }\n catch (e) {\n // do nothing\n }\n}\nfunction set_style(node, key, value, important) {\n if (value === null) {\n node.style.removeProperty(key);\n }\n else {\n node.style.setProperty(key, value, important ? 'important' : '');\n }\n}\nfunction select_option(select, value) {\n for (let i = 0; i < select.options.length; i += 1) {\n const option = select.options[i];\n if (option.__value === value) {\n option.selected = true;\n return;\n }\n }\n select.selectedIndex = -1; // no option should be selected\n}\nfunction select_options(select, value) {\n for (let i = 0; i < select.options.length; i += 1) {\n const option = select.options[i];\n option.selected = ~value.indexOf(option.__value);\n }\n}\nfunction select_value(select) {\n const selected_option = select.querySelector(':checked') || select.options[0];\n return selected_option && selected_option.__value;\n}\nfunction select_multiple_value(select) {\n return [].map.call(select.querySelectorAll(':checked'), option => option.__value);\n}\n// unfortunately this can't be a constant as that wouldn't be tree-shakeable\n// so we cache the result instead\nlet crossorigin;\nfunction is_crossorigin() {\n if (crossorigin === undefined) {\n crossorigin = false;\n try {\n if (typeof window !== 'undefined' && window.parent) {\n void window.parent.document;\n }\n }\n catch (error) {\n crossorigin = true;\n }\n }\n return crossorigin;\n}\nfunction add_resize_listener(node, fn) {\n const computed_style = getComputedStyle(node);\n if (computed_style.position === 'static') {\n node.style.position = 'relative';\n }\n const iframe = element('iframe');\n iframe.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ' +\n 'overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: -1;');\n iframe.setAttribute('aria-hidden', 'true');\n iframe.tabIndex = -1;\n const crossorigin = is_crossorigin();\n let unsubscribe;\n if (crossorigin) {\n iframe.src = \"data:text/html,\";\n unsubscribe = listen(window, 'message', (event) => {\n if (event.source === iframe.contentWindow)\n fn();\n });\n }\n else {\n iframe.src = 'about:blank';\n iframe.onload = () => {\n unsubscribe = listen(iframe.contentWindow, 'resize', fn);\n };\n }\n append(node, iframe);\n return () => {\n if (crossorigin) {\n unsubscribe();\n }\n else if (unsubscribe && iframe.contentWindow) {\n unsubscribe();\n }\n detach(iframe);\n };\n}\nfunction toggle_class(element, name, toggle) {\n element.classList[toggle ? 'add' : 'remove'](name);\n}\nfunction custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {\n const e = document.createEvent('CustomEvent');\n e.initCustomEvent(type, bubbles, cancelable, detail);\n return e;\n}\nfunction query_selector_all(selector, parent = document.body) {\n return Array.from(parent.querySelectorAll(selector));\n}\nclass HtmlTag {\n constructor(is_svg = false) {\n this.is_svg = false;\n this.is_svg = is_svg;\n this.e = this.n = null;\n }\n c(html) {\n this.h(html);\n }\n m(html, target, anchor = null) {\n if (!this.e) {\n if (this.is_svg)\n this.e = svg_element(target.nodeName);\n else\n this.e = element(target.nodeName);\n this.t = target;\n this.c(html);\n }\n this.i(anchor);\n }\n h(html) {\n this.e.innerHTML = html;\n this.n = Array.from(this.e.childNodes);\n }\n i(anchor) {\n for (let i = 0; i < this.n.length; i += 1) {\n insert(this.t, this.n[i], anchor);\n }\n }\n p(html) {\n this.d();\n this.h(html);\n this.i(this.a);\n }\n d() {\n this.n.forEach(detach);\n }\n}\nclass HtmlTagHydration extends HtmlTag {\n constructor(claimed_nodes, is_svg = false) {\n super(is_svg);\n this.e = this.n = null;\n this.l = claimed_nodes;\n }\n c(html) {\n if (this.l) {\n this.n = this.l;\n }\n else {\n super.c(html);\n }\n }\n i(anchor) {\n for (let i = 0; i < this.n.length; i += 1) {\n insert_hydration(this.t, this.n[i], anchor);\n }\n }\n}\nfunction attribute_to_object(attributes) {\n const result = {};\n for (const attribute of attributes) {\n result[attribute.name] = attribute.value;\n }\n return result;\n}\nfunction get_custom_elements_slots(element) {\n const result = {};\n element.childNodes.forEach((node) => {\n result[node.slot || 'default'] = true;\n });\n return result;\n}\n\n// we need to store the information for multiple documents because a Svelte application could also contain iframes\n// https://github.com/sveltejs/svelte/issues/3624\nconst managed_styles = new Map();\nlet active = 0;\n// https://github.com/darkskyapp/string-hash/blob/master/index.js\nfunction hash(str) {\n let hash = 5381;\n let i = str.length;\n while (i--)\n hash = ((hash << 5) - hash) ^ str.charCodeAt(i);\n return hash >>> 0;\n}\nfunction create_style_information(doc, node) {\n const info = { stylesheet: append_empty_stylesheet(node), rules: {} };\n managed_styles.set(doc, info);\n return info;\n}\nfunction create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {\n const step = 16.666 / duration;\n let keyframes = '{\\n';\n for (let p = 0; p <= 1; p += step) {\n const t = a + (b - a) * ease(p);\n keyframes += p * 100 + `%{${fn(t, 1 - t)}}\\n`;\n }\n const rule = keyframes + `100% {${fn(b, 1 - b)}}\\n}`;\n const name = `__svelte_${hash(rule)}_${uid}`;\n const doc = get_root_for_style(node);\n const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);\n if (!rules[name]) {\n rules[name] = true;\n stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);\n }\n const animation = node.style.animation || '';\n node.style.animation = `${animation ? `${animation}, ` : ''}${name} ${duration}ms linear ${delay}ms 1 both`;\n active += 1;\n return name;\n}\nfunction delete_rule(node, name) {\n const previous = (node.style.animation || '').split(', ');\n const next = previous.filter(name\n ? anim => anim.indexOf(name) < 0 // remove specific animation\n : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations\n );\n const deleted = previous.length - next.length;\n if (deleted) {\n node.style.animation = next.join(', ');\n active -= deleted;\n if (!active)\n clear_rules();\n }\n}\nfunction clear_rules() {\n raf(() => {\n if (active)\n return;\n managed_styles.forEach(info => {\n const { stylesheet } = info;\n let i = stylesheet.cssRules.length;\n while (i--)\n stylesheet.deleteRule(i);\n info.rules = {};\n });\n managed_styles.clear();\n });\n}\n\nfunction create_animation(node, from, fn, params) {\n if (!from)\n return noop;\n const to = node.getBoundingClientRect();\n if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom)\n return noop;\n const { delay = 0, duration = 300, easing = identity, \n // @ts-ignore todo: should this be separated from destructuring? Or start/end added to public api and documentation?\n start: start_time = now() + delay, \n // @ts-ignore todo:\n end = start_time + duration, tick = noop, css } = fn(node, { from, to }, params);\n let running = true;\n let started = false;\n let name;\n function start() {\n if (css) {\n name = create_rule(node, 0, 1, duration, delay, easing, css);\n }\n if (!delay) {\n started = true;\n }\n }\n function stop() {\n if (css)\n delete_rule(node, name);\n running = false;\n }\n loop(now => {\n if (!started && now >= start_time) {\n started = true;\n }\n if (started && now >= end) {\n tick(1, 0);\n stop();\n }\n if (!running) {\n return false;\n }\n if (started) {\n const p = now - start_time;\n const t = 0 + 1 * easing(p / duration);\n tick(t, 1 - t);\n }\n return true;\n });\n start();\n tick(0, 1);\n return stop;\n}\nfunction fix_position(node) {\n const style = getComputedStyle(node);\n if (style.position !== 'absolute' && style.position !== 'fixed') {\n const { width, height } = style;\n const a = node.getBoundingClientRect();\n node.style.position = 'absolute';\n node.style.width = width;\n node.style.height = height;\n add_transform(node, a);\n }\n}\nfunction add_transform(node, a) {\n const b = node.getBoundingClientRect();\n if (a.left !== b.left || a.top !== b.top) {\n const style = getComputedStyle(node);\n const transform = style.transform === 'none' ? '' : style.transform;\n node.style.transform = `${transform} translate(${a.left - b.left}px, ${a.top - b.top}px)`;\n }\n}\n\nlet current_component;\nfunction set_current_component(component) {\n current_component = component;\n}\nfunction get_current_component() {\n if (!current_component)\n throw new Error('Function called outside component initialization');\n return current_component;\n}\nfunction beforeUpdate(fn) {\n get_current_component().$$.before_update.push(fn);\n}\nfunction onMount(fn) {\n get_current_component().$$.on_mount.push(fn);\n}\nfunction afterUpdate(fn) {\n get_current_component().$$.after_update.push(fn);\n}\nfunction onDestroy(fn) {\n get_current_component().$$.on_destroy.push(fn);\n}\nfunction createEventDispatcher() {\n const component = get_current_component();\n return (type, detail, { cancelable = false } = {}) => {\n const callbacks = component.$$.callbacks[type];\n if (callbacks) {\n // TODO are there situations where events could be dispatched\n // in a server (non-DOM) environment?\n const event = custom_event(type, detail, { cancelable });\n callbacks.slice().forEach(fn => {\n fn.call(component, event);\n });\n return !event.defaultPrevented;\n }\n return true;\n };\n}\nfunction setContext(key, context) {\n get_current_component().$$.context.set(key, context);\n return context;\n}\nfunction getContext(key) {\n return get_current_component().$$.context.get(key);\n}\nfunction getAllContexts() {\n return get_current_component().$$.context;\n}\nfunction hasContext(key) {\n return get_current_component().$$.context.has(key);\n}\n// TODO figure out if we still want to support\n// shorthand events, or if we want to implement\n// a real bubbling mechanism\nfunction bubble(component, event) {\n const callbacks = component.$$.callbacks[event.type];\n if (callbacks) {\n // @ts-ignore\n callbacks.slice().forEach(fn => fn.call(this, event));\n }\n}\n\nconst dirty_components = [];\nconst intros = { enabled: false };\nconst binding_callbacks = [];\nconst render_callbacks = [];\nconst flush_callbacks = [];\nconst resolved_promise = Promise.resolve();\nlet update_scheduled = false;\nfunction schedule_update() {\n if (!update_scheduled) {\n update_scheduled = true;\n resolved_promise.then(flush);\n }\n}\nfunction tick() {\n schedule_update();\n return resolved_promise;\n}\nfunction add_render_callback(fn) {\n render_callbacks.push(fn);\n}\nfunction add_flush_callback(fn) {\n flush_callbacks.push(fn);\n}\n// flush() calls callbacks in this order:\n// 1. All beforeUpdate callbacks, in order: parents before children\n// 2. All bind:this callbacks, in reverse order: children before parents.\n// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT\n// for afterUpdates called during the initial onMount, which are called in\n// reverse order: children before parents.\n// Since callbacks might update component values, which could trigger another\n// call to flush(), the following steps guard against this:\n// 1. During beforeUpdate, any updated components will be added to the\n// dirty_components array and will cause a reentrant call to flush(). Because\n// the flush index is kept outside the function, the reentrant call will pick\n// up where the earlier call left off and go through all dirty components. The\n// current_component value is saved and restored so that the reentrant call will\n// not interfere with the \"parent\" flush() call.\n// 2. bind:this callbacks cannot trigger new flush() calls.\n// 3. During afterUpdate, any updated components will NOT have their afterUpdate\n// callback called a second time; the seen_callbacks set, outside the flush()\n// function, guarantees this behavior.\nconst seen_callbacks = new Set();\nlet flushidx = 0; // Do *not* move this inside the flush() function\nfunction flush() {\n const saved_component = current_component;\n do {\n // first, call beforeUpdate functions\n // and update components\n while (flushidx < dirty_components.length) {\n const component = dirty_components[flushidx];\n flushidx++;\n set_current_component(component);\n update(component.$$);\n }\n set_current_component(null);\n dirty_components.length = 0;\n flushidx = 0;\n while (binding_callbacks.length)\n binding_callbacks.pop()();\n // then, once components are updated, call\n // afterUpdate functions. This may cause\n // subsequent updates...\n for (let i = 0; i < render_callbacks.length; i += 1) {\n const callback = render_callbacks[i];\n if (!seen_callbacks.has(callback)) {\n // ...so guard against infinite loops\n seen_callbacks.add(callback);\n callback();\n }\n }\n render_callbacks.length = 0;\n } while (dirty_components.length);\n while (flush_callbacks.length) {\n flush_callbacks.pop()();\n }\n update_scheduled = false;\n seen_callbacks.clear();\n set_current_component(saved_component);\n}\nfunction update($$) {\n if ($$.fragment !== null) {\n $$.update();\n run_all($$.before_update);\n const dirty = $$.dirty;\n $$.dirty = [-1];\n $$.fragment && $$.fragment.p($$.ctx, dirty);\n $$.after_update.forEach(add_render_callback);\n }\n}\n\nlet promise;\nfunction wait() {\n if (!promise) {\n promise = Promise.resolve();\n promise.then(() => {\n promise = null;\n });\n }\n return promise;\n}\nfunction dispatch(node, direction, kind) {\n node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));\n}\nconst outroing = new Set();\nlet outros;\nfunction group_outros() {\n outros = {\n r: 0,\n c: [],\n p: outros // parent group\n };\n}\nfunction check_outros() {\n if (!outros.r) {\n run_all(outros.c);\n }\n outros = outros.p;\n}\nfunction transition_in(block, local) {\n if (block && block.i) {\n outroing.delete(block);\n block.i(local);\n }\n}\nfunction transition_out(block, local, detach, callback) {\n if (block && block.o) {\n if (outroing.has(block))\n return;\n outroing.add(block);\n outros.c.push(() => {\n outroing.delete(block);\n if (callback) {\n if (detach)\n block.d(1);\n callback();\n }\n });\n block.o(local);\n }\n else if (callback) {\n callback();\n }\n}\nconst null_transition = { duration: 0 };\nfunction create_in_transition(node, fn, params) {\n let config = fn(node, params);\n let running = false;\n let animation_name;\n let task;\n let uid = 0;\n function cleanup() {\n if (animation_name)\n delete_rule(node, animation_name);\n }\n function go() {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n if (css)\n animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);\n tick(0, 1);\n const start_time = now() + delay;\n const end_time = start_time + duration;\n if (task)\n task.abort();\n running = true;\n add_render_callback(() => dispatch(node, true, 'start'));\n task = loop(now => {\n if (running) {\n if (now >= end_time) {\n tick(1, 0);\n dispatch(node, true, 'end');\n cleanup();\n return running = false;\n }\n if (now >= start_time) {\n const t = easing((now - start_time) / duration);\n tick(t, 1 - t);\n }\n }\n return running;\n });\n }\n let started = false;\n return {\n start() {\n if (started)\n return;\n started = true;\n delete_rule(node);\n if (is_function(config)) {\n config = config();\n wait().then(go);\n }\n else {\n go();\n }\n },\n invalidate() {\n started = false;\n },\n end() {\n if (running) {\n cleanup();\n running = false;\n }\n }\n };\n}\nfunction create_out_transition(node, fn, params) {\n let config = fn(node, params);\n let running = true;\n let animation_name;\n const group = outros;\n group.r += 1;\n function go() {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n if (css)\n animation_name = create_rule(node, 1, 0, duration, delay, easing, css);\n const start_time = now() + delay;\n const end_time = start_time + duration;\n add_render_callback(() => dispatch(node, false, 'start'));\n loop(now => {\n if (running) {\n if (now >= end_time) {\n tick(0, 1);\n dispatch(node, false, 'end');\n if (!--group.r) {\n // this will result in `end()` being called,\n // so we don't need to clean up here\n run_all(group.c);\n }\n return false;\n }\n if (now >= start_time) {\n const t = easing((now - start_time) / duration);\n tick(1 - t, t);\n }\n }\n return running;\n });\n }\n if (is_function(config)) {\n wait().then(() => {\n // @ts-ignore\n config = config();\n go();\n });\n }\n else {\n go();\n }\n return {\n end(reset) {\n if (reset && config.tick) {\n config.tick(1, 0);\n }\n if (running) {\n if (animation_name)\n delete_rule(node, animation_name);\n running = false;\n }\n }\n };\n}\nfunction create_bidirectional_transition(node, fn, params, intro) {\n let config = fn(node, params);\n let t = intro ? 0 : 1;\n let running_program = null;\n let pending_program = null;\n let animation_name = null;\n function clear_animation() {\n if (animation_name)\n delete_rule(node, animation_name);\n }\n function init(program, duration) {\n const d = (program.b - t);\n duration *= Math.abs(d);\n return {\n a: t,\n b: program.b,\n d,\n duration,\n start: program.start,\n end: program.start + duration,\n group: program.group\n };\n }\n function go(b) {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n const program = {\n start: now() + delay,\n b\n };\n if (!b) {\n // @ts-ignore todo: improve typings\n program.group = outros;\n outros.r += 1;\n }\n if (running_program || pending_program) {\n pending_program = program;\n }\n else {\n // if this is an intro, and there's a delay, we need to do\n // an initial tick and/or apply CSS animation immediately\n if (css) {\n clear_animation();\n animation_name = create_rule(node, t, b, duration, delay, easing, css);\n }\n if (b)\n tick(0, 1);\n running_program = init(program, duration);\n add_render_callback(() => dispatch(node, b, 'start'));\n loop(now => {\n if (pending_program && now > pending_program.start) {\n running_program = init(pending_program, duration);\n pending_program = null;\n dispatch(node, running_program.b, 'start');\n if (css) {\n clear_animation();\n animation_name = create_rule(node, t, running_program.b, running_program.duration, 0, easing, config.css);\n }\n }\n if (running_program) {\n if (now >= running_program.end) {\n tick(t = running_program.b, 1 - t);\n dispatch(node, running_program.b, 'end');\n if (!pending_program) {\n // we're done\n if (running_program.b) {\n // intro — we can tidy up immediately\n clear_animation();\n }\n else {\n // outro — needs to be coordinated\n if (!--running_program.group.r)\n run_all(running_program.group.c);\n }\n }\n running_program = null;\n }\n else if (now >= running_program.start) {\n const p = now - running_program.start;\n t = running_program.a + running_program.d * easing(p / running_program.duration);\n tick(t, 1 - t);\n }\n }\n return !!(running_program || pending_program);\n });\n }\n }\n return {\n run(b) {\n if (is_function(config)) {\n wait().then(() => {\n // @ts-ignore\n config = config();\n go(b);\n });\n }\n else {\n go(b);\n }\n },\n end() {\n clear_animation();\n running_program = pending_program = null;\n }\n };\n}\n\nfunction handle_promise(promise, info) {\n const token = info.token = {};\n function update(type, index, key, value) {\n if (info.token !== token)\n return;\n info.resolved = value;\n let child_ctx = info.ctx;\n if (key !== undefined) {\n child_ctx = child_ctx.slice();\n child_ctx[key] = value;\n }\n const block = type && (info.current = type)(child_ctx);\n let needs_flush = false;\n if (info.block) {\n if (info.blocks) {\n info.blocks.forEach((block, i) => {\n if (i !== index && block) {\n group_outros();\n transition_out(block, 1, 1, () => {\n if (info.blocks[i] === block) {\n info.blocks[i] = null;\n }\n });\n check_outros();\n }\n });\n }\n else {\n info.block.d(1);\n }\n block.c();\n transition_in(block, 1);\n block.m(info.mount(), info.anchor);\n needs_flush = true;\n }\n info.block = block;\n if (info.blocks)\n info.blocks[index] = block;\n if (needs_flush) {\n flush();\n }\n }\n if (is_promise(promise)) {\n const current_component = get_current_component();\n promise.then(value => {\n set_current_component(current_component);\n update(info.then, 1, info.value, value);\n set_current_component(null);\n }, error => {\n set_current_component(current_component);\n update(info.catch, 2, info.error, error);\n set_current_component(null);\n if (!info.hasCatch) {\n throw error;\n }\n });\n // if we previously had a then/catch block, destroy it\n if (info.current !== info.pending) {\n update(info.pending, 0);\n return true;\n }\n }\n else {\n if (info.current !== info.then) {\n update(info.then, 1, info.value, promise);\n return true;\n }\n info.resolved = promise;\n }\n}\nfunction update_await_block_branch(info, ctx, dirty) {\n const child_ctx = ctx.slice();\n const { resolved } = info;\n if (info.current === info.then) {\n child_ctx[info.value] = resolved;\n }\n if (info.current === info.catch) {\n child_ctx[info.error] = resolved;\n }\n info.block.p(child_ctx, dirty);\n}\n\nconst globals = (typeof window !== 'undefined'\n ? window\n : typeof globalThis !== 'undefined'\n ? globalThis\n : global);\n\nfunction destroy_block(block, lookup) {\n block.d(1);\n lookup.delete(block.key);\n}\nfunction outro_and_destroy_block(block, lookup) {\n transition_out(block, 1, 1, () => {\n lookup.delete(block.key);\n });\n}\nfunction fix_and_destroy_block(block, lookup) {\n block.f();\n destroy_block(block, lookup);\n}\nfunction fix_and_outro_and_destroy_block(block, lookup) {\n block.f();\n outro_and_destroy_block(block, lookup);\n}\nfunction update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {\n let o = old_blocks.length;\n let n = list.length;\n let i = o;\n const old_indexes = {};\n while (i--)\n old_indexes[old_blocks[i].key] = i;\n const new_blocks = [];\n const new_lookup = new Map();\n const deltas = new Map();\n i = n;\n while (i--) {\n const child_ctx = get_context(ctx, list, i);\n const key = get_key(child_ctx);\n let block = lookup.get(key);\n if (!block) {\n block = create_each_block(key, child_ctx);\n block.c();\n }\n else if (dynamic) {\n block.p(child_ctx, dirty);\n }\n new_lookup.set(key, new_blocks[i] = block);\n if (key in old_indexes)\n deltas.set(key, Math.abs(i - old_indexes[key]));\n }\n const will_move = new Set();\n const did_move = new Set();\n function insert(block) {\n transition_in(block, 1);\n block.m(node, next);\n lookup.set(block.key, block);\n next = block.first;\n n--;\n }\n while (o && n) {\n const new_block = new_blocks[n - 1];\n const old_block = old_blocks[o - 1];\n const new_key = new_block.key;\n const old_key = old_block.key;\n if (new_block === old_block) {\n // do nothing\n next = new_block.first;\n o--;\n n--;\n }\n else if (!new_lookup.has(old_key)) {\n // remove old block\n destroy(old_block, lookup);\n o--;\n }\n else if (!lookup.has(new_key) || will_move.has(new_key)) {\n insert(new_block);\n }\n else if (did_move.has(old_key)) {\n o--;\n }\n else if (deltas.get(new_key) > deltas.get(old_key)) {\n did_move.add(new_key);\n insert(new_block);\n }\n else {\n will_move.add(old_key);\n o--;\n }\n }\n while (o--) {\n const old_block = old_blocks[o];\n if (!new_lookup.has(old_block.key))\n destroy(old_block, lookup);\n }\n while (n)\n insert(new_blocks[n - 1]);\n return new_blocks;\n}\nfunction validate_each_keys(ctx, list, get_context, get_key) {\n const keys = new Set();\n for (let i = 0; i < list.length; i++) {\n const key = get_key(get_context(ctx, list, i));\n if (keys.has(key)) {\n throw new Error('Cannot have duplicate keys in a keyed each');\n }\n keys.add(key);\n }\n}\n\nfunction get_spread_update(levels, updates) {\n const update = {};\n const to_null_out = {};\n const accounted_for = { $$scope: 1 };\n let i = levels.length;\n while (i--) {\n const o = levels[i];\n const n = updates[i];\n if (n) {\n for (const key in o) {\n if (!(key in n))\n to_null_out[key] = 1;\n }\n for (const key in n) {\n if (!accounted_for[key]) {\n update[key] = n[key];\n accounted_for[key] = 1;\n }\n }\n levels[i] = n;\n }\n else {\n for (const key in o) {\n accounted_for[key] = 1;\n }\n }\n }\n for (const key in to_null_out) {\n if (!(key in update))\n update[key] = undefined;\n }\n return update;\n}\nfunction get_spread_object(spread_props) {\n return typeof spread_props === 'object' && spread_props !== null ? spread_props : {};\n}\n\n// source: https://html.spec.whatwg.org/multipage/indices.html\nconst boolean_attributes = new Set([\n 'allowfullscreen',\n 'allowpaymentrequest',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'ismap',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected'\n]);\n\nconst void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;\nfunction is_void(name) {\n return void_element_names.test(name) || name.toLowerCase() === '!doctype';\n}\n\nconst invalid_attribute_name_character = /[\\s'\">/=\\u{FDD0}-\\u{FDEF}\\u{FFFE}\\u{FFFF}\\u{1FFFE}\\u{1FFFF}\\u{2FFFE}\\u{2FFFF}\\u{3FFFE}\\u{3FFFF}\\u{4FFFE}\\u{4FFFF}\\u{5FFFE}\\u{5FFFF}\\u{6FFFE}\\u{6FFFF}\\u{7FFFE}\\u{7FFFF}\\u{8FFFE}\\u{8FFFF}\\u{9FFFE}\\u{9FFFF}\\u{AFFFE}\\u{AFFFF}\\u{BFFFE}\\u{BFFFF}\\u{CFFFE}\\u{CFFFF}\\u{DFFFE}\\u{DFFFF}\\u{EFFFE}\\u{EFFFF}\\u{FFFFE}\\u{FFFFF}\\u{10FFFE}\\u{10FFFF}]/u;\n// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n// https://infra.spec.whatwg.org/#noncharacter\nfunction spread(args, attrs_to_add) {\n const attributes = Object.assign({}, ...args);\n if (attrs_to_add) {\n const classes_to_add = attrs_to_add.classes;\n const styles_to_add = attrs_to_add.styles;\n if (classes_to_add) {\n if (attributes.class == null) {\n attributes.class = classes_to_add;\n }\n else {\n attributes.class += ' ' + classes_to_add;\n }\n }\n if (styles_to_add) {\n if (attributes.style == null) {\n attributes.style = style_object_to_string(styles_to_add);\n }\n else {\n attributes.style = style_object_to_string(merge_ssr_styles(attributes.style, styles_to_add));\n }\n }\n }\n let str = '';\n Object.keys(attributes).forEach(name => {\n if (invalid_attribute_name_character.test(name))\n return;\n const value = attributes[name];\n if (value === true)\n str += ' ' + name;\n else if (boolean_attributes.has(name.toLowerCase())) {\n if (value)\n str += ' ' + name;\n }\n else if (value != null) {\n str += ` ${name}=\"${value}\"`;\n }\n });\n return str;\n}\nfunction merge_ssr_styles(style_attribute, style_directive) {\n const style_object = {};\n for (const individual_style of style_attribute.split(';')) {\n const colon_index = individual_style.indexOf(':');\n const name = individual_style.slice(0, colon_index).trim();\n const value = individual_style.slice(colon_index + 1).trim();\n if (!name)\n continue;\n style_object[name] = value;\n }\n for (const name in style_directive) {\n const value = style_directive[name];\n if (value) {\n style_object[name] = value;\n }\n else {\n delete style_object[name];\n }\n }\n return style_object;\n}\nconst ATTR_REGEX = /[&\"]/g;\nconst CONTENT_REGEX = /[&<]/g;\n/**\n * Note: this method is performance sensitive and has been optimized\n * https://github.com/sveltejs/svelte/pull/5701\n */\nfunction escape(value, is_attr = false) {\n const str = String(value);\n const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;\n pattern.lastIndex = 0;\n let escaped = '';\n let last = 0;\n while (pattern.test(str)) {\n const i = pattern.lastIndex - 1;\n const ch = str[i];\n escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '\"' ? '"' : '<'));\n last = i + 1;\n }\n return escaped + str.substring(last);\n}\nfunction escape_attribute_value(value) {\n // keep booleans, null, and undefined for the sake of `spread`\n const should_escape = typeof value === 'string' || (value && typeof value === 'object');\n return should_escape ? escape(value, true) : value;\n}\nfunction escape_object(obj) {\n const result = {};\n for (const key in obj) {\n result[key] = escape_attribute_value(obj[key]);\n }\n return result;\n}\nfunction each(items, fn) {\n let str = '';\n for (let i = 0; i < items.length; i += 1) {\n str += fn(items[i], i);\n }\n return str;\n}\nconst missing_component = {\n $$render: () => ''\n};\nfunction validate_component(component, name) {\n if (!component || !component.$$render) {\n if (name === 'svelte:component')\n name += ' this={...}';\n throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules`);\n }\n return component;\n}\nfunction debug(file, line, column, values) {\n console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`); // eslint-disable-line no-console\n console.log(values); // eslint-disable-line no-console\n return '';\n}\nlet on_destroy;\nfunction create_ssr_component(fn) {\n function $$render(result, props, bindings, slots, context) {\n const parent_component = current_component;\n const $$ = {\n on_destroy,\n context: new Map(context || (parent_component ? parent_component.$$.context : [])),\n // these will be immediately discarded\n on_mount: [],\n before_update: [],\n after_update: [],\n callbacks: blank_object()\n };\n set_current_component({ $$ });\n const html = fn(result, props, bindings, slots);\n set_current_component(parent_component);\n return html;\n }\n return {\n render: (props = {}, { $$slots = {}, context = new Map() } = {}) => {\n on_destroy = [];\n const result = { title: '', head: '', css: new Set() };\n const html = $$render(result, props, {}, $$slots, context);\n run_all(on_destroy);\n return {\n html,\n css: {\n code: Array.from(result.css).map(css => css.code).join('\\n'),\n map: null // TODO\n },\n head: result.title + result.head\n };\n },\n $$render\n };\n}\nfunction add_attribute(name, value, boolean) {\n if (value == null || (boolean && !value))\n return '';\n const assignment = (boolean && value === true) ? '' : `=\"${escape(value, true)}\"`;\n return ` ${name}${assignment}`;\n}\nfunction add_classes(classes) {\n return classes ? ` class=\"${classes}\"` : '';\n}\nfunction style_object_to_string(style_object) {\n return Object.keys(style_object)\n .filter(key => style_object[key])\n .map(key => `${key}: ${style_object[key]};`)\n .join(' ');\n}\nfunction add_styles(style_object) {\n const styles = style_object_to_string(style_object);\n return styles ? ` style=\"${styles}\"` : '';\n}\n\nfunction bind(component, name, callback) {\n const index = component.$$.props[name];\n if (index !== undefined) {\n component.$$.bound[index] = callback;\n callback(component.$$.ctx[index]);\n }\n}\nfunction create_component(block) {\n block && block.c();\n}\nfunction claim_component(block, parent_nodes) {\n block && block.l(parent_nodes);\n}\nfunction mount_component(component, target, anchor, customElement) {\n const { fragment, on_mount, on_destroy, after_update } = component.$$;\n fragment && fragment.m(target, anchor);\n if (!customElement) {\n // onMount happens before the initial afterUpdate\n add_render_callback(() => {\n const new_on_destroy = on_mount.map(run).filter(is_function);\n if (on_destroy) {\n on_destroy.push(...new_on_destroy);\n }\n else {\n // Edge case - component was destroyed immediately,\n // most likely as a result of a binding initialising\n run_all(new_on_destroy);\n }\n component.$$.on_mount = [];\n });\n }\n after_update.forEach(add_render_callback);\n}\nfunction destroy_component(component, detaching) {\n const $$ = component.$$;\n if ($$.fragment !== null) {\n run_all($$.on_destroy);\n $$.fragment && $$.fragment.d(detaching);\n // TODO null out other refs, including component.$$ (but need to\n // preserve final state?)\n $$.on_destroy = $$.fragment = null;\n $$.ctx = [];\n }\n}\nfunction make_dirty(component, i) {\n if (component.$$.dirty[0] === -1) {\n dirty_components.push(component);\n schedule_update();\n component.$$.dirty.fill(0);\n }\n component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));\n}\nfunction init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {\n const parent_component = current_component;\n set_current_component(component);\n const $$ = component.$$ = {\n fragment: null,\n ctx: null,\n // state\n props,\n update: noop,\n not_equal,\n bound: blank_object(),\n // lifecycle\n on_mount: [],\n on_destroy: [],\n on_disconnect: [],\n before_update: [],\n after_update: [],\n context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),\n // everything else\n callbacks: blank_object(),\n dirty,\n skip_bound: false,\n root: options.target || parent_component.$$.root\n };\n append_styles && append_styles($$.root);\n let ready = false;\n $$.ctx = instance\n ? instance(component, options.props || {}, (i, ret, ...rest) => {\n const value = rest.length ? rest[0] : ret;\n if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {\n if (!$$.skip_bound && $$.bound[i])\n $$.bound[i](value);\n if (ready)\n make_dirty(component, i);\n }\n return ret;\n })\n : [];\n $$.update();\n ready = true;\n run_all($$.before_update);\n // `false` as a special case of no DOM component\n $$.fragment = create_fragment ? create_fragment($$.ctx) : false;\n if (options.target) {\n if (options.hydrate) {\n start_hydrating();\n const nodes = children(options.target);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n $$.fragment && $$.fragment.l(nodes);\n nodes.forEach(detach);\n }\n else {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n $$.fragment && $$.fragment.c();\n }\n if (options.intro)\n transition_in(component.$$.fragment);\n mount_component(component, options.target, options.anchor, options.customElement);\n end_hydrating();\n flush();\n }\n set_current_component(parent_component);\n}\nlet SvelteElement;\nif (typeof HTMLElement === 'function') {\n SvelteElement = class extends HTMLElement {\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n connectedCallback() {\n const { on_mount } = this.$$;\n this.$$.on_disconnect = on_mount.map(run).filter(is_function);\n // @ts-ignore todo: improve typings\n for (const key in this.$$.slotted) {\n // @ts-ignore todo: improve typings\n this.appendChild(this.$$.slotted[key]);\n }\n }\n attributeChangedCallback(attr, _oldValue, newValue) {\n this[attr] = newValue;\n }\n disconnectedCallback() {\n run_all(this.$$.on_disconnect);\n }\n $destroy() {\n destroy_component(this, 1);\n this.$destroy = noop;\n }\n $on(type, callback) {\n // TODO should this delegate to addEventListener?\n const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));\n callbacks.push(callback);\n return () => {\n const index = callbacks.indexOf(callback);\n if (index !== -1)\n callbacks.splice(index, 1);\n };\n }\n $set($$props) {\n if (this.$$set && !is_empty($$props)) {\n this.$$.skip_bound = true;\n this.$$set($$props);\n this.$$.skip_bound = false;\n }\n }\n };\n}\n/**\n * Base class for Svelte components. Used when dev=false.\n */\nclass SvelteComponent {\n $destroy() {\n destroy_component(this, 1);\n this.$destroy = noop;\n }\n $on(type, callback) {\n const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));\n callbacks.push(callback);\n return () => {\n const index = callbacks.indexOf(callback);\n if (index !== -1)\n callbacks.splice(index, 1);\n };\n }\n $set($$props) {\n if (this.$$set && !is_empty($$props)) {\n this.$$.skip_bound = true;\n this.$$set($$props);\n this.$$.skip_bound = false;\n }\n }\n}\n\nfunction dispatch_dev(type, detail) {\n document.dispatchEvent(custom_event(type, Object.assign({ version: '3.49.0' }, detail), { bubbles: true }));\n}\nfunction append_dev(target, node) {\n dispatch_dev('SvelteDOMInsert', { target, node });\n append(target, node);\n}\nfunction append_hydration_dev(target, node) {\n dispatch_dev('SvelteDOMInsert', { target, node });\n append_hydration(target, node);\n}\nfunction insert_dev(target, node, anchor) {\n dispatch_dev('SvelteDOMInsert', { target, node, anchor });\n insert(target, node, anchor);\n}\nfunction insert_hydration_dev(target, node, anchor) {\n dispatch_dev('SvelteDOMInsert', { target, node, anchor });\n insert_hydration(target, node, anchor);\n}\nfunction detach_dev(node) {\n dispatch_dev('SvelteDOMRemove', { node });\n detach(node);\n}\nfunction detach_between_dev(before, after) {\n while (before.nextSibling && before.nextSibling !== after) {\n detach_dev(before.nextSibling);\n }\n}\nfunction detach_before_dev(after) {\n while (after.previousSibling) {\n detach_dev(after.previousSibling);\n }\n}\nfunction detach_after_dev(before) {\n while (before.nextSibling) {\n detach_dev(before.nextSibling);\n }\n}\nfunction listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {\n const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];\n if (has_prevent_default)\n modifiers.push('preventDefault');\n if (has_stop_propagation)\n modifiers.push('stopPropagation');\n dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });\n const dispose = listen(node, event, handler, options);\n return () => {\n dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });\n dispose();\n };\n}\nfunction attr_dev(node, attribute, value) {\n attr(node, attribute, value);\n if (value == null)\n dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });\n else\n dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });\n}\nfunction prop_dev(node, property, value) {\n node[property] = value;\n dispatch_dev('SvelteDOMSetProperty', { node, property, value });\n}\nfunction dataset_dev(node, property, value) {\n node.dataset[property] = value;\n dispatch_dev('SvelteDOMSetDataset', { node, property, value });\n}\nfunction set_data_dev(text, data) {\n data = '' + data;\n if (text.wholeText === data)\n return;\n dispatch_dev('SvelteDOMSetData', { node: text, data });\n text.data = data;\n}\nfunction validate_each_argument(arg) {\n if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {\n let msg = '{#each} only iterates over array-like objects.';\n if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {\n msg += ' You can use a spread to convert this iterable into an array.';\n }\n throw new Error(msg);\n }\n}\nfunction validate_slots(name, slot, keys) {\n for (const slot_key of Object.keys(slot)) {\n if (!~keys.indexOf(slot_key)) {\n console.warn(`<${name}> received an unexpected slot \"${slot_key}\".`);\n }\n }\n}\nfunction validate_dynamic_element(tag) {\n const is_string = typeof tag === 'string';\n if (tag && !is_string) {\n throw new Error(' expects \"this\" attribute to be a string.');\n }\n}\nfunction validate_void_dynamic_element(tag) {\n if (tag && is_void(tag)) {\n throw new Error(` is self-closing and cannot have content.`);\n }\n}\n/**\n * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.\n */\nclass SvelteComponentDev extends SvelteComponent {\n constructor(options) {\n if (!options || (!options.target && !options.$$inline)) {\n throw new Error(\"'target' is a required option\");\n }\n super();\n }\n $destroy() {\n super.$destroy();\n this.$destroy = () => {\n console.warn('Component was already destroyed'); // eslint-disable-line no-console\n };\n }\n $capture_state() { }\n $inject_state() { }\n}\n/**\n * Base class to create strongly typed Svelte components.\n * This only exists for typing purposes and should be used in `.d.ts` files.\n *\n * ### Example:\n *\n * You have component library on npm called `component-library`, from which\n * you export a component called `MyComponent`. For Svelte+TypeScript users,\n * you want to provide typings. Therefore you create a `index.d.ts`:\n * ```ts\n * import { SvelteComponentTyped } from \"svelte\";\n * export class MyComponent extends SvelteComponentTyped<{foo: string}> {}\n * ```\n * Typing this makes it possible for IDEs like VS Code with the Svelte extension\n * to provide intellisense and to use the component like this in a Svelte file\n * with TypeScript:\n * ```svelte\n * \n * \n * ```\n *\n * #### Why not make this part of `SvelteComponent(Dev)`?\n * Because\n * ```ts\n * class ASubclassOfSvelteComponent extends SvelteComponent<{foo: string}> {}\n * const component: typeof SvelteComponent = ASubclassOfSvelteComponent;\n * ```\n * will throw a type error, so we need to separate the more strictly typed class.\n */\nclass SvelteComponentTyped extends SvelteComponentDev {\n constructor(options) {\n super(options);\n }\n}\nfunction loop_guard(timeout) {\n const start = Date.now();\n return () => {\n if (Date.now() - start > timeout) {\n throw new Error('Infinite loop detected');\n }\n };\n}\n\nexport { HtmlTag, HtmlTagHydration, SvelteComponent, SvelteComponentDev, SvelteComponentTyped, SvelteElement, action_destroyer, add_attribute, add_classes, add_flush_callback, add_location, add_render_callback, add_resize_listener, add_styles, add_transform, afterUpdate, append, append_dev, append_empty_stylesheet, append_hydration, append_hydration_dev, append_styles, assign, attr, attr_dev, attribute_to_object, beforeUpdate, bind, binding_callbacks, blank_object, bubble, check_outros, children, claim_component, claim_element, claim_html_tag, claim_space, claim_svg_element, claim_text, clear_loops, component_subscribe, compute_rest_props, compute_slots, createEventDispatcher, create_animation, create_bidirectional_transition, create_component, create_in_transition, create_out_transition, create_slot, create_ssr_component, current_component, custom_event, dataset_dev, debug, destroy_block, destroy_component, destroy_each, detach, detach_after_dev, detach_before_dev, detach_between_dev, detach_dev, dirty_components, dispatch_dev, each, element, element_is, empty, end_hydrating, escape, escape_attribute_value, escape_object, exclude_internal_props, fix_and_destroy_block, fix_and_outro_and_destroy_block, fix_position, flush, getAllContexts, getContext, get_all_dirty_from_scope, get_binding_group_value, get_current_component, get_custom_elements_slots, get_root_for_style, get_slot_changes, get_spread_object, get_spread_update, get_store_value, globals, group_outros, handle_promise, hasContext, has_prop, identity, init, insert, insert_dev, insert_hydration, insert_hydration_dev, intros, invalid_attribute_name_character, is_client, is_crossorigin, is_empty, is_function, is_promise, is_void, listen, listen_dev, loop, loop_guard, merge_ssr_styles, missing_component, mount_component, noop, not_equal, now, null_to_empty, object_without_properties, onDestroy, onMount, once, outro_and_destroy_block, prevent_default, prop_dev, query_selector_all, raf, run, run_all, safe_not_equal, schedule_update, select_multiple_value, select_option, select_options, select_value, self, setContext, set_attributes, set_current_component, set_custom_element_data, set_data, set_data_dev, set_input_type, set_input_value, set_now, set_raf, set_store_value, set_style, set_svg_attributes, space, spread, src_url_equal, start_hydrating, stop_propagation, subscribe, svg_element, text, tick, time_ranges_to_array, to_number, toggle_class, transition_in, transition_out, trusted, update_await_block_branch, update_keyed_each, update_slot, update_slot_base, validate_component, validate_dynamic_element, validate_each_argument, validate_each_keys, validate_slots, validate_store, validate_void_dynamic_element, xlink_attr };\n","import { noop, safe_not_equal, subscribe, run_all, is_function } from '../internal/index.mjs';\nexport { get_store_value as get } from '../internal/index.mjs';\n\nconst subscriber_queue = [];\n/**\n * Creates a `Readable` store that allows reading by subscription.\n * @param value initial value\n * @param {StartStopNotifier}start start and stop notifications for subscriptions\n */\nfunction readable(value, start) {\n return {\n subscribe: writable(value, start).subscribe\n };\n}\n/**\n * Create a `Writable` store that allows both updating and reading by subscription.\n * @param {*=}value initial value\n * @param {StartStopNotifier=}start start and stop notifications for subscriptions\n */\nfunction writable(value, start = noop) {\n let stop;\n const subscribers = new Set();\n function set(new_value) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) { // store is ready\n const run_queue = !subscriber_queue.length;\n for (const subscriber of subscribers) {\n subscriber[1]();\n subscriber_queue.push(subscriber, value);\n }\n if (run_queue) {\n for (let i = 0; i < subscriber_queue.length; i += 2) {\n subscriber_queue[i][0](subscriber_queue[i + 1]);\n }\n subscriber_queue.length = 0;\n }\n }\n }\n }\n function update(fn) {\n set(fn(value));\n }\n function subscribe(run, invalidate = noop) {\n const subscriber = [run, invalidate];\n subscribers.add(subscriber);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(subscriber);\n if (subscribers.size === 0) {\n stop();\n stop = null;\n }\n };\n }\n return { set, update, subscribe };\n}\nfunction derived(stores, fn, initial_value) {\n const single = !Array.isArray(stores);\n const stores_array = single\n ? [stores]\n : stores;\n const auto = fn.length < 2;\n return readable(initial_value, (set) => {\n let inited = false;\n const values = [];\n let pending = 0;\n let cleanup = noop;\n const sync = () => {\n if (pending) {\n return;\n }\n cleanup();\n const result = fn(single ? values[0] : values, set);\n if (auto) {\n set(result);\n }\n else {\n cleanup = is_function(result) ? result : noop;\n }\n };\n const unsubscribers = stores_array.map((store, i) => subscribe(store, (value) => {\n values[i] = value;\n pending &= ~(1 << i);\n if (inited) {\n sync();\n }\n }, () => {\n pending |= (1 << i);\n }));\n inited = true;\n sync();\n return function stop() {\n run_all(unsubscribers);\n cleanup();\n };\n });\n}\n\nexport { derived, readable, writable };\n","import { group_outros, transition_out, check_outros } from 'svelte/internal';\n\n/**\n * Provides a solid string hashing algorithm.\n *\n * Sourced from: https://stackoverflow.com/a/52171480\n *\n * @param {string} str - String to hash.\n *\n * @param {number} seed - A seed value altering the hash.\n *\n * @returns {number} Hash code.\n */\nfunction hashCode(str, seed = 0)\n{\n if (typeof str !== 'string') { return 0; }\n\n let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n\n for (let ch, i = 0; i < str.length; i++)\n {\n ch = str.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\n return 4294967296 * (2097151 & h2) + (h1 >>> 0);\n}\n\nconst s_UUIDV4_REGEX = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;\n\n/**\n * Generates a UUID v4 compliant ID. Please use a complete UUID generation package for guaranteed compliance.\n *\n * This code is an evolution of the following Gist.\n * https://gist.github.com/jed/982883\n *\n * There is a public domain / free copy license attached to it that is not a standard OSS license...\n * https://gist.github.com/jed/982883#file-license-txt\n *\n * @returns {string} UUIDv4\n */\nfunction uuidv4()\n{\n return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>\n (c ^ (globalThis.crypto || globalThis.msCrypto).getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));\n}\n\n/**\n * Validates that the given string is formatted as a UUIDv4 string.\n *\n * @param {string} uuid - UUID string to test.\n *\n * @returns {boolean} Is UUIDv4 string.\n */\nuuidv4.isValid = (uuid) => s_UUIDV4_REGEX.test(uuid);\n\n/**\n * Normalizes a string.\n *\n * @param {string} query - A string to normalize for comparisons.\n *\n * @returns {string} Cleaned string.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize\n */\nfunction normalizeString(query)\n{\n return query.trim().normalize('NFD').replace(/[\\x00-\\x1F]/gm, '');\n}\n\n/**\n * Recursive function that finds the closest parent stacking context.\n * See also https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context\n *\n * Original author: Kerry Liu / https://github.com/gwwar\n * @see: https://github.com/gwwar/z-context/blob/master/content-script.js\n * @see: https://github.com/gwwar/z-context/blob/master/LICENSE\n *\n * @param {Element} node -\n *\n * @returns {StackingContext} The closest parent stacking context\n */\nfunction getStackingContext(node)\n{\n // the root element (HTML).\n if (!node || node.nodeName === 'HTML')\n {\n return { node: document.documentElement, reason: 'root' };\n }\n\n // handle shadow root elements.\n if (node.nodeName === '#document-fragment')\n {\n return getStackingContext(node.host);\n }\n\n const computedStyle = globalThis.getComputedStyle(node);\n\n // position: fixed or sticky.\n if (computedStyle.position === 'fixed' || computedStyle.position === 'sticky')\n {\n return { node: node, reason: `position: ${computedStyle.position}` };\n }\n\n // positioned (absolutely or relatively) with a z-index value other than \"auto\".\n if (computedStyle.zIndex !== 'auto' && computedStyle.position !== 'static')\n {\n return { node: node, reason: `position: ${computedStyle.position}; z-index: ${computedStyle.zIndex}` };\n }\n\n // elements with an opacity value less than 1.\n if (computedStyle.opacity !== '1')\n {\n return { node: node, reason: `opacity: ${computedStyle.opacity}` };\n }\n\n // elements with a transform value other than \"none\".\n if (computedStyle.transform !== 'none')\n {\n return { node: node, reason: `transform: ${computedStyle.transform}` };\n }\n\n // elements with a mix-blend-mode value other than \"normal\".\n if (computedStyle.mixBlendMode !== 'normal')\n {\n return { node: node, reason: `mixBlendMode: ${computedStyle.mixBlendMode}` };\n }\n\n // elements with a filter value other than \"none\".\n if (computedStyle.filter !== 'none')\n {\n return { node: node, reason: `filter: ${computedStyle.filter}` };\n }\n\n // elements with a perspective value other than \"none\".\n if (computedStyle.perspective !== 'none')\n {\n return { node: node, reason: `perspective: ${computedStyle.perspective}` };\n }\n\n // elements with a clip-path value other than \"none\".\n if (computedStyle.clipPath !== 'none')\n {\n return { node: node, reason: `clip-path: ${computedStyle.clipPath} ` };\n }\n\n // elements with a mask value other than \"none\".\n const mask = computedStyle.mask || computedStyle.webkitMask;\n if (mask !== 'none' && mask !== undefined)\n {\n return { node: node, reason: `mask: ${mask}` };\n }\n\n // elements with a mask-image value other than \"none\".\n const maskImage = computedStyle.maskImage || computedStyle.webkitMaskImage;\n if (maskImage !== 'none' && maskImage !== undefined)\n {\n return { node: node, reason: `mask-image: ${maskImage}` };\n }\n\n // elements with a mask-border value other than \"none\".\n const maskBorder = computedStyle.maskBorder || computedStyle.webkitMaskBorder;\n if (maskBorder !== 'none' && maskBorder !== undefined)\n {\n return { node: node, reason: `mask-border: ${maskBorder}` };\n }\n\n // elements with isolation set to \"isolate\".\n if (computedStyle.isolation === 'isolate')\n {\n return { node: node, reason: `isolation: ${computedStyle.isolation}` };\n }\n\n // transform or opacity in will-change even if you don't specify values for these attributes directly.\n if (computedStyle.willChange === 'transform' || computedStyle.willChange === 'opacity')\n {\n return { node: node, reason: `willChange: ${computedStyle.willChange}` };\n }\n\n // elements with -webkit-overflow-scrolling set to \"touch\".\n if (computedStyle.webkitOverflowScrolling === 'touch')\n {\n return { node: node, reason: '-webkit-overflow-scrolling: touch' };\n }\n\n // an item with a z-index value other than \"auto\".\n if (computedStyle.zIndex !== 'auto')\n {\n const parentStyle = globalThis.getComputedStyle(node.parentNode);\n // with a flex|inline-flex parent.\n if (parentStyle.display === 'flex' || parentStyle.display === 'inline-flex')\n {\n return {\n node: node,\n reason: `flex-item; z-index: ${computedStyle.zIndex}`,\n };\n // with a grid parent.\n }\n else if (parentStyle.grid !== 'none / none / none / row / auto / auto')\n {\n return {\n node: node,\n reason: `child of grid container; z-index: ${computedStyle.zIndex}`,\n };\n }\n }\n\n // contain with a value of layout, or paint, or a composite value that includes either of them\n const contain = computedStyle.contain;\n if (['layout', 'paint', 'strict', 'content'].indexOf(contain) > -1 ||\n contain.indexOf('paint') > -1 ||\n contain.indexOf('layout') > -1\n )\n {\n return {\n node: node,\n reason: `contain: ${contain}`,\n };\n }\n\n return getStackingContext(node.parentNode);\n}\n\n/**\n * @typedef {Object} StackingContext\n *\n * @property {Element} node A DOM Element\n * @property {string} reason Reason for why a stacking context was created\n */\n\nconst s_REGEX = /(\\d+)\\s*px/;\n\n/**\n * Parses a pixel string / computed styles. Ex. `100px` returns `100`.\n *\n * @param {string} value - Value to parse.\n *\n * @returns {number|undefined} The integer component of a pixel string.\n */\nfunction styleParsePixels(value)\n{\n if (typeof value !== 'string') { return void 0; }\n\n const isPixels = s_REGEX.test(value);\n const number = parseInt(value);\n\n return isPixels && Number.isFinite(number) ? number : void 0;\n}\n\n/**\n * Defines the application shell contract. If Svelte components export getter / setters for the following properties\n * then that component is considered an application shell.\n *\n * @type {string[]}\n */\nconst applicationShellContract = ['elementRoot'];\n\nObject.freeze(applicationShellContract);\n\n/**\n * Provides a method to determine if the passed in object / Svelte component follows the application shell contract.\n * This involves ensuring that the accessors defined in `applicationShellContract`.\n *\n * Note: A caveat is that when using Vite in a developer build components are wrapped in a proxy / ProxyComponent that\n * defines instance accessors versus on the prototype, so the check below ensures that all accessors in the contract are\n * either available on the prototype or directly on the instance.\n *\n * @param {*} component - Object / component to test.\n *\n * @returns {boolean} Whether the component is a ApplicationShell or TJSApplicationShell.\n */\nfunction isApplicationShell(component)\n{\n if (component === null || component === void 0) { return false; }\n\n let compHasContract = true;\n let protoHasContract = true;\n\n // Check for accessors on the instance.\n for (const accessor of applicationShellContract)\n {\n const descriptor = Object.getOwnPropertyDescriptor(component, accessor);\n if (descriptor === void 0 || descriptor.get === void 0 || descriptor.set === void 0) { compHasContract = false; }\n }\n\n // Get the prototype which is the parent SvelteComponent that has any getter / setters.\n const prototype = Object.getPrototypeOf(component);\n\n // Verify the application shell contract. If the accessors (getters / setters) are defined for\n // `applicationShellContract`.\n for (const accessor of applicationShellContract)\n {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, accessor);\n if (descriptor === void 0 || descriptor.get === void 0 || descriptor.set === void 0) { protoHasContract = false; }\n }\n\n return compHasContract || protoHasContract;\n}\n\n/**\n * Provides basic duck typing to determine if the provided object is a HMR ProxyComponent instance or class.\n *\n * @param {*} comp - Data to check as a HMR proxy component.\n *\n * @returns {boolean} Whether basic duck typing succeeds.\n */\nfunction isHMRProxy(comp)\n{\n const instanceName = comp?.constructor?.name;\n if (typeof instanceName === 'string' && (instanceName.startsWith('Proxy<') || instanceName === 'ProxyComponent'))\n {\n return true;\n }\n\n const prototypeName = comp?.prototype?.constructor?.name;\n return typeof prototypeName === 'string' && (prototypeName.startsWith('Proxy<') ||\n prototypeName === 'ProxyComponent');\n}\n\n/**\n * Provides basic duck typing to determine if the provided function is a constructor function for a Svelte component.\n *\n * @param {*} comp - Data to check as a Svelte component.\n *\n * @returns {boolean} Whether basic duck typing succeeds.\n */\nfunction isSvelteComponent(comp)\n{\n if (comp === null || comp === void 0 || typeof comp !== 'function') { return false; }\n\n // When using Vite in a developer build the SvelteComponent is wrapped in a ProxyComponent class.\n // This class doesn't define methods on the prototype, so we must check if the constructor name\n // starts with `Proxy<` as it provides the wrapped component as `Proxy<_wrapped component name_>`.\n const prototypeName = comp?.prototype?.constructor?.name;\n if (typeof prototypeName === 'string' && (prototypeName.startsWith('Proxy<') || prototypeName === 'ProxyComponent'))\n {\n return true;\n }\n\n return typeof window !== void 0 ?\n typeof comp.prototype.$destroy === 'function' && typeof comp.prototype.$on === 'function' : // client-side\n typeof comp.render === 'function'; // server-side\n}\n\n/**\n * Runs outro transition then destroys Svelte component.\n *\n * Workaround for https://github.com/sveltejs/svelte/issues/4056\n *\n * @param {*} instance - A Svelte component.\n */\nasync function outroAndDestroy(instance)\n{\n return new Promise((resolve) =>\n {\n if (instance.$$.fragment && instance.$$.fragment.o)\n {\n group_outros();\n transition_out(instance.$$.fragment, 0, 0, () =>\n {\n instance.$destroy();\n resolve();\n });\n check_outros();\n }\n else\n {\n instance.$destroy();\n resolve();\n }\n });\n}\n\n/**\n * Parses a TyphonJS Svelte config object ensuring that classes specified are Svelte components and props are set\n * correctly.\n *\n * @param {object} config - Svelte config object.\n *\n * @param {*} [thisArg] - `This` reference to set for invoking any props function.\n *\n * @returns {object} The processed Svelte config object.\n */\nfunction parseSvelteConfig(config, thisArg = void 0)\n{\n if (typeof config !== 'object')\n {\n throw new TypeError(`parseSvelteConfig - 'config' is not an object:\\n${JSON.stringify(config)}.`);\n }\n\n if (!isSvelteComponent(config.class))\n {\n throw new TypeError(\n `parseSvelteConfig - 'class' is not a Svelte component constructor for config:\\n${JSON.stringify(config)}.`);\n }\n\n if (config.hydrate !== void 0 && typeof config.hydrate !== 'boolean')\n {\n throw new TypeError(\n `parseSvelteConfig - 'hydrate' is not a boolean for config:\\n${JSON.stringify(config)}.`);\n }\n\n if (config.intro !== void 0 && typeof config.intro !== 'boolean')\n {\n throw new TypeError(\n `parseSvelteConfig - 'intro' is not a boolean for config:\\n${JSON.stringify(config)}.`);\n }\n\n if (config.target !== void 0 && typeof config.target !== 'string' && !(config.target instanceof HTMLElement) &&\n !(config.target instanceof ShadowRoot) && !(config.target instanceof DocumentFragment))\n {\n throw new TypeError(\n `parseSvelteConfig - 'target' is not a string, HTMLElement, ShadowRoot, or DocumentFragment for config:\\n${\n JSON.stringify(config)}.`);\n }\n\n if (config.anchor !== void 0 && typeof config.anchor !== 'string' && !(config.anchor instanceof HTMLElement) &&\n !(config.anchor instanceof ShadowRoot) && !(config.anchor instanceof DocumentFragment))\n {\n throw new TypeError(\n `parseSvelteConfig - 'anchor' is not a string, HTMLElement, ShadowRoot, or DocumentFragment for config:\\n${\n JSON.stringify(config)}.`);\n }\n\n if (config.context !== void 0 && typeof config.context !== 'function' && !(config.context instanceof Map) &&\n typeof config.context !== 'object')\n {\n throw new TypeError(\n `parseSvelteConfig - 'context' is not a Map, function or object for config:\\n${JSON.stringify(config)}.`);\n }\n\n // Validate extra TyphonJS options --------------------------------------------------------------------------------\n\n // `selectorTarget` optionally stores a target element found in main element.\n if (config.selectorTarget !== void 0 && typeof config.selectorTarget !== 'string')\n {\n throw new TypeError(\n `parseSvelteConfig - 'selectorTarget' is not a string for config:\\n${JSON.stringify(config)}.`);\n }\n\n // `options` stores `injectApp`, `injectEventbus`, and `selectorElement`.\n if (config.options !== void 0 && typeof config.options !== 'object')\n {\n throw new TypeError(\n `parseSvelteConfig - 'options' is not an object for config:\\n${JSON.stringify(config)}.`);\n }\n\n // Validate TyphonJS standard options.\n if (config.options !== void 0)\n {\n if (config.options.injectApp !== void 0 && typeof config.options.injectApp !== 'boolean')\n {\n throw new TypeError(\n `parseSvelteConfig - 'options.injectApp' is not a boolean for config:\\n${JSON.stringify(config)}.`);\n }\n\n if (config.options.injectEventbus !== void 0 && typeof config.options.injectEventbus !== 'boolean')\n {\n throw new TypeError(\n `parseSvelteConfig - 'options.injectEventbus' is not a boolean for config:\\n${JSON.stringify(config)}.`);\n }\n\n // `selectorElement` optionally stores a main element selector to be found in a HTMLElement target.\n if (config.options.selectorElement !== void 0 && typeof config.options.selectorElement !== 'string')\n {\n throw new TypeError(\n `parseSvelteConfig - 'selectorElement' is not a string for config:\\n${JSON.stringify(config)}.`);\n }\n }\n\n const svelteConfig = { ...config };\n\n // Delete extra Svelte options.\n delete svelteConfig.options;\n\n let externalContext = {};\n\n // If a context callback function is provided then invoke it with `this` being the Foundry app.\n // If an object is returned it adds the entries to external context.\n if (typeof svelteConfig.context === 'function')\n {\n const contextFunc = svelteConfig.context;\n delete svelteConfig.context;\n\n const result = contextFunc.call(thisArg);\n if (typeof result === 'object')\n {\n externalContext = { ...result };\n }\n else\n {\n throw new Error(`parseSvelteConfig - 'context' is a function that did not return an object for config:\\n${\n JSON.stringify(config)}`);\n }\n }\n else if (svelteConfig.context instanceof Map)\n {\n externalContext = Object.fromEntries(svelteConfig.context);\n delete svelteConfig.context;\n }\n else if (typeof svelteConfig.context === 'object')\n {\n externalContext = svelteConfig.context;\n delete svelteConfig.context;\n }\n\n // If a props is a function then invoke it with `this` being the Foundry app.\n // If an object is returned set it as the props.\n svelteConfig.props = s_PROCESS_PROPS(svelteConfig.props, thisArg, config);\n\n // Process children components attaching to external context.\n if (Array.isArray(svelteConfig.children))\n {\n const children = [];\n\n for (let cntr = 0; cntr < svelteConfig.children.length; cntr++)\n {\n const child = svelteConfig.children[cntr];\n\n if (!isSvelteComponent(child.class))\n {\n throw new Error(`parseSvelteConfig - 'class' is not a Svelte component for child[${cntr}] for config:\\n${\n JSON.stringify(config)}`);\n }\n\n child.props = s_PROCESS_PROPS(child.props, thisArg, config);\n\n children.push(child);\n }\n\n if (children.length > 0)\n {\n externalContext.children = children;\n }\n\n delete svelteConfig.children;\n }\n else if (typeof svelteConfig.children === 'object')\n {\n if (!isSvelteComponent(svelteConfig.children.class))\n {\n throw new Error(`parseSvelteConfig - 'class' is not a Svelte component for children object for config:\\n${\n JSON.stringify(config)}`);\n }\n\n svelteConfig.children.props = s_PROCESS_PROPS(svelteConfig.children.props, thisArg, config);\n\n externalContext.children = [svelteConfig.children];\n delete svelteConfig.children;\n }\n\n if (!(svelteConfig.context instanceof Map))\n {\n svelteConfig.context = new Map();\n }\n\n svelteConfig.context.set('external', externalContext);\n\n return svelteConfig;\n}\n\n/**\n * Processes Svelte props. Potentially props can be a function to invoke with `thisArg`.\n *\n * @param {object|Function} props - Svelte props.\n *\n * @param {*} thisArg - `This` reference to set for invoking any props function.\n *\n * @param {object} config - Svelte config\n *\n * @returns {object|void} Svelte props.\n */\nfunction s_PROCESS_PROPS(props, thisArg, config)\n{\n // If a props is a function then invoke it with `this` being the Foundry app.\n // If an object is returned set it as the props.\n if (typeof props === 'function')\n {\n const result = props.call(thisArg);\n if (typeof result === 'object')\n {\n return result;\n }\n else\n {\n throw new Error(`parseSvelteConfig - 'props' is a function that did not return an object for config:\\n${\n JSON.stringify(config)}`);\n }\n }\n else if (typeof props === 'object')\n {\n return props;\n }\n else if (props !== void 0)\n {\n throw new Error(\n `parseSvelteConfig - 'props' is not a function or an object for config:\\n${JSON.stringify(config)}`);\n }\n\n return {};\n}\n\n/**\n * Wraps a callback in a debounced timeout.\n *\n * Delay execution of the callback function until the function has not been called for the given delay in milliseconds.\n *\n * @param {Function} callback - A function to execute once the debounced threshold has been passed.\n *\n * @param {number} delay - An amount of time in milliseconds to delay.\n *\n * @return {Function} A wrapped function that can be called to debounce execution.\n */\nfunction debounce(callback, delay)\n{\n let timeoutId;\n\n return function(...args)\n {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => { callback.apply(this, args); }, delay);\n }\n}\n\n/**\n * Provides a method to determine if the passed in Svelte component has a getter accessor.\n *\n * @param {*} object - An object.\n *\n * @param {string} accessor - Accessor to test.\n *\n * @returns {boolean} Whether the component has the getter for accessor.\n */\nfunction hasGetter(object, accessor)\n{\n if (object === null || object === void 0) { return false; }\n\n // Check for instance accessor.\n const iDescriptor = Object.getOwnPropertyDescriptor(object, accessor);\n if (iDescriptor !== void 0 && iDescriptor.get !== void 0) { return true; }\n\n // Walk parent prototype chain. Check for descriptor at each prototype level.\n for (let o = Object.getPrototypeOf(object); o; o = Object.getPrototypeOf(o))\n {\n const descriptor = Object.getOwnPropertyDescriptor(o, accessor);\n if (descriptor !== void 0 && descriptor.get !== void 0) { return true; }\n }\n\n return false;\n}\n\n/**\n * Provides a method to determine if the passed in Svelte component has a getter & setter accessor.\n *\n * @param {*} object - An object.\n *\n * @param {string} accessor - Accessor to test.\n *\n * @returns {boolean} Whether the component has the getter and setter for accessor.\n */\nfunction hasAccessor(object, accessor)\n{\n if (object === null || object === void 0) { return false; }\n\n // Check for instance accessor.\n const iDescriptor = Object.getOwnPropertyDescriptor(object, accessor);\n if (iDescriptor !== void 0 && iDescriptor.get !== void 0 && iDescriptor.set !== void 0) { return true; }\n\n // Walk parent prototype chain. Check for descriptor at each prototype level.\n for (let o = Object.getPrototypeOf(object); o; o = Object.getPrototypeOf(o))\n {\n const descriptor = Object.getOwnPropertyDescriptor(o, accessor);\n if (descriptor !== void 0 && descriptor.get !== void 0 && descriptor.set !== void 0) { return true; }\n }\n\n return false;\n}\n\n/**\n * Provides a method to determine if the passed in Svelte component has a setter accessor.\n *\n * @param {*} object - An object.\n *\n * @param {string} accessor - Accessor to test.\n *\n * @returns {boolean} Whether the component has the setter for accessor.\n */\nfunction hasSetter(object, accessor)\n{\n if (object === null || object === void 0) { return false; }\n\n // Check for instance accessor.\n const iDescriptor = Object.getOwnPropertyDescriptor(object, accessor);\n if (iDescriptor !== void 0 && iDescriptor.set !== void 0) { return true; }\n\n // Walk parent prototype chain. Check for descriptor at each prototype level.\n for (let o = Object.getPrototypeOf(object); o; o = Object.getPrototypeOf(o))\n {\n const descriptor = Object.getOwnPropertyDescriptor(o, accessor);\n if (descriptor !== void 0 && descriptor.set !== void 0) { return true; }\n }\n\n return false;\n}\n\nfunction set(obj, key, val) {\n\tif (typeof val.value === 'object') val.value = klona(val.value);\n\tif (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {\n\t\tObject.defineProperty(obj, key, val);\n\t} else obj[key] = val.value;\n}\n\nfunction klona(x) {\n\tif (typeof x !== 'object') return x;\n\n\tvar i=0, k, list, tmp, str=Object.prototype.toString.call(x);\n\n\tif (str === '[object Object]') {\n\t\ttmp = Object.create(x.__proto__ || null);\n\t} else if (str === '[object Array]') {\n\t\ttmp = Array(x.length);\n\t} else if (str === '[object Set]') {\n\t\ttmp = new Set;\n\t\tx.forEach(function (val) {\n\t\t\ttmp.add(klona(val));\n\t\t});\n\t} else if (str === '[object Map]') {\n\t\ttmp = new Map;\n\t\tx.forEach(function (val, key) {\n\t\t\ttmp.set(klona(key), klona(val));\n\t\t});\n\t} else if (str === '[object Date]') {\n\t\ttmp = new Date(+x);\n\t} else if (str === '[object RegExp]') {\n\t\ttmp = new RegExp(x.source, x.flags);\n\t} else if (str === '[object DataView]') {\n\t\ttmp = new x.constructor( klona(x.buffer) );\n\t} else if (str === '[object ArrayBuffer]') {\n\t\ttmp = x.slice(0);\n\t} else if (str.slice(-6) === 'Array]') {\n\t\t// ArrayBuffer.isView(x)\n\t\t// ~> `new` bcuz `Buffer.slice` => ref\n\t\ttmp = new x.constructor(x);\n\t}\n\n\tif (tmp) {\n\t\tfor (list=Object.getOwnPropertySymbols(x); i < list.length; i++) {\n\t\t\tset(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));\n\t\t}\n\n\t\tfor (i=0, list=Object.getOwnPropertyNames(x); i < list.length; i++) {\n\t\t\tif (Object.hasOwnProperty.call(tmp, k=list[i]) && tmp[k] === x[k]) continue;\n\t\t\tset(tmp, k, Object.getOwnPropertyDescriptor(x, k));\n\t\t}\n\t}\n\n\treturn tmp || x;\n}\n\n/**\n * Provides common object manipulation utilities including depth traversal, obtaining accessors, safely setting values /\n * equality tests, and validation.\n */\n\nconst s_TAG_OBJECT = '[object Object]';\n\n/**\n * Recursively deep merges all source objects into the target object in place. Like `Object.assign` if you provide `{}`\n * as the target a copy is produced. If the target and source property are object literals they are merged.\n * Deleting keys is supported by specifying a property starting with `-=`.\n *\n * @param {object} target - Target object.\n *\n * @param {...object} sourceObj - One or more source objects.\n *\n * @returns {object} Target object.\n */\nfunction deepMerge(target = {}, ...sourceObj)\n{\n if (Object.prototype.toString.call(target) !== s_TAG_OBJECT)\n {\n throw new TypeError(`deepMerge error: 'target' is not an 'object'.`);\n }\n\n for (let cntr = 0; cntr < sourceObj.length; cntr++)\n {\n if (Object.prototype.toString.call(sourceObj[cntr]) !== s_TAG_OBJECT)\n {\n throw new TypeError(`deepMerge error: 'sourceObj[${cntr}]' is not an 'object'.`);\n }\n }\n\n return _deepMerge(target, ...sourceObj);\n}\n\n/**\n * Tests for whether an object is iterable.\n *\n * @param {*} value - Any value.\n *\n * @returns {boolean} Whether object is iterable.\n */\nfunction isIterable(value)\n{\n if (value === null || value === void 0 || typeof value !== 'object') { return false; }\n\n return typeof value[Symbol.iterator] === 'function';\n}\n\n/**\n * Tests for whether an object is async iterable.\n *\n * @param {*} value - Any value.\n *\n * @returns {boolean} Whether value is async iterable.\n */\nfunction isIterableAsync(value)\n{\n if (value === null || value === void 0 || typeof value !== 'object') { return false; }\n\n return typeof value[Symbol.asyncIterator] === 'function';\n}\n\n/**\n * Tests for whether object is not null and a typeof object.\n *\n * @param {*} value - Any value.\n *\n * @returns {boolean} Is it an object.\n */\nfunction isObject(value)\n{\n return value !== null && typeof value === 'object';\n}\n\n/**\n * Tests for whether the given value is a plain object.\n *\n * An object is plain if it is created by either: {}, new Object() or Object.create(null).\n *\n * @param {*} value - Any value\n *\n * @returns {boolean} Is it a plain object.\n */\nfunction isPlainObject(value)\n{\n if (Object.prototype.toString.call(value) !== s_TAG_OBJECT) { return false; }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || prototype === Object.prototype;\n}\n\n/**\n * Provides a way to safely access an objects data / entries given an accessor string which describes the\n * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries\n * to walk.\n *\n * @param {object} data - An object to access entry data.\n *\n * @param {string} accessor - A string describing the entries to access.\n *\n * @param {*} defaultValue - (Optional) A default value to return if an entry for accessor is not found.\n *\n * @returns {object} The data object.\n */\nfunction safeAccess(data, accessor, defaultValue = void 0)\n{\n if (typeof data !== 'object') { return defaultValue; }\n if (typeof accessor !== 'string') { return defaultValue; }\n\n const access = accessor.split('.');\n\n // Walk through the given object by the accessor indexes.\n for (let cntr = 0; cntr < access.length; cntr++)\n {\n // If the next level of object access is undefined or null then return the empty string.\n if (typeof data[access[cntr]] === 'undefined' || data[access[cntr]] === null) { return defaultValue; }\n\n data = data[access[cntr]];\n }\n\n return data;\n}\n\n/**\n * Provides a way to safely set an objects data / entries given an accessor string which describes the\n * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries\n * to walk.\n *\n * @param {object} data - An object to access entry data.\n *\n * @param {string} accessor - A string describing the entries to access.\n *\n * @param {*} value - A new value to set if an entry for accessor is found.\n *\n * @param {string} [operation='set'] - Operation to perform including: 'add', 'div', 'mult', 'set',\n * 'set-undefined', 'sub'.\n *\n * @param {boolean} [createMissing=true] - If true missing accessor entries will be created as objects\n * automatically.\n *\n * @returns {boolean} True if successful.\n */\nfunction safeSet(data, accessor, value, operation = 'set', createMissing = true)\n{\n if (typeof data !== 'object') { throw new TypeError(`safeSet Error: 'data' is not an 'object'.`); }\n if (typeof accessor !== 'string') { throw new TypeError(`safeSet Error: 'accessor' is not a 'string'.`); }\n\n const access = accessor.split('.');\n\n // Walk through the given object by the accessor indexes.\n for (let cntr = 0; cntr < access.length; cntr++)\n {\n // If data is an array perform validation that the accessor is a positive integer otherwise quit.\n if (Array.isArray(data))\n {\n const number = (+access[cntr]);\n\n if (!Number.isInteger(number) || number < 0) { return false; }\n }\n\n if (cntr === access.length - 1)\n {\n switch (operation)\n {\n case 'add':\n data[access[cntr]] += value;\n break;\n\n case 'div':\n data[access[cntr]] /= value;\n break;\n\n case 'mult':\n data[access[cntr]] *= value;\n break;\n\n case 'set':\n data[access[cntr]] = value;\n break;\n\n case 'set-undefined':\n if (typeof data[access[cntr]] === 'undefined') { data[access[cntr]] = value; }\n break;\n\n case 'sub':\n data[access[cntr]] -= value;\n break;\n }\n }\n else\n {\n // If createMissing is true and the next level of object access is undefined then create a new object entry.\n if (createMissing && typeof data[access[cntr]] === 'undefined') { data[access[cntr]] = {}; }\n\n // Abort if the next level is null or not an object and containing a value.\n if (data[access[cntr]] === null || typeof data[access[cntr]] !== 'object') { return false; }\n\n data = data[access[cntr]];\n }\n }\n\n return true;\n}\n\n/**\n * Internal implementation for `deepMerge`.\n *\n * @param {object} target - Target object.\n *\n * @param {...object} sourceObj - One or more source objects.\n *\n * @returns {object} Target object.\n */\nfunction _deepMerge(target = {}, ...sourceObj)\n{\n // Iterate and merge all source objects into target.\n for (let cntr = 0; cntr < sourceObj.length; cntr++)\n {\n const obj = sourceObj[cntr];\n\n for (const prop in obj)\n {\n if (Object.prototype.hasOwnProperty.call(obj, prop))\n {\n // Handle the special property starting with '-=' to delete keys.\n if (prop.startsWith('-='))\n {\n delete target[prop.slice(2)];\n continue;\n }\n\n // If target already has prop and both target[prop] and obj[prop] are object literals then merge them\n // otherwise assign obj[prop] to target[prop].\n target[prop] = Object.prototype.hasOwnProperty.call(target, prop) && target[prop]?.constructor === Object &&\n obj[prop]?.constructor === Object ? _deepMerge({}, target[prop], obj[prop]) : obj[prop];\n }\n }\n }\n\n return target;\n}\n\n/**\n * Attempts to create a Foundry UUID from standard drop data. This may not work for all systems.\n *\n * @param {object} data - Drop transfer data.\n *\n * @param {ParseDataTransferOptions} opts - Optional parameters.\n *\n * @returns {string|undefined} Foundry UUID for drop data.\n */\nfunction getUUIDFromDataTransfer(data, { actor = true, compendium = true, world = true, types = void 0 } = {})\n{\n if (typeof data !== 'object') { return void 0; }\n if (Array.isArray(types) && !types.includes(data.type)) { return void 0; }\n\n let uuid = void 0;\n\n // TODO: v10 will change the `data.data._id` relationship possibly.\n if (actor && world && data.actorId && data.type)\n {\n uuid = `Actor.${data.actorId}.${data.type}.${data.data._id}`;\n }\n else if (data.id)\n {\n if (compendium && typeof data.pack === 'string')\n {\n uuid = `Compendium.${data.pack}.${data.id}`;\n }\n else if (world)\n {\n uuid = `${data.type}.${data.id}`;\n }\n }\n\n return uuid;\n}\n\nexport { debounce, deepMerge, getStackingContext, getUUIDFromDataTransfer, hasAccessor, hasGetter, hasSetter, hashCode, isApplicationShell, isHMRProxy, isIterable, isIterableAsync, isObject, isPlainObject, isSvelteComponent, klona, normalizeString, outroAndDestroy, parseSvelteConfig, safeAccess, safeSet, styleParsePixels, uuidv4 };\n//# sourceMappingURL=index.js.map\n","import { writable as writable$2, derived, get } from 'svelte/store';\nimport { noop, run_all, is_function } from 'svelte/internal';\nimport { uuidv4, isPlainObject, getUUIDFromDataTransfer, isObject, isIterable } from '@typhonjs-fvtt/runtime/svelte/util';\n\n/**\n * Provides the storage and sequencing of managed filters. Each filter added may be a bespoke function or a\n * {@link FilterData} object containing an `id`, `filter`, and `weight` attributes; `filter` is the only required\n * attribute.\n *\n * The `id` attribute can be anything that creates a unique ID for the filter; recommended strings or numbers. This\n * allows filters to be removed by ID easily.\n *\n * The `weight` attribute is a number between 0 and 1 inclusive that allows filters to be added in a\n * predictable order which is especially handy if they are manipulated at runtime. A lower weighted filter always runs\n * before a higher weighted filter. For speed and efficiency always set the heavier / more inclusive filter with a\n * lower weight; an example of this is a keyword / name that will filter out many entries making any further filtering\n * faster. If no weight is specified the default of '1' is assigned and it is appended to the end of the filters list.\n *\n * This class forms the public API which is accessible from the `.filters` getter in the main DynArrayReducer instance.\n * ```\n * const dynArray = new DynArrayReducer([...]);\n * dynArray.filters.add(...);\n * dynArray.filters.clear();\n * dynArray.filters.length;\n * dynArray.filters.remove(...);\n * dynArray.filters.removeBy(...);\n * dynArray.filters.removeById(...);\n * ```\n *\n * @template T\n */\nclass AdapterFilters\n{\n #filtersAdapter;\n #indexUpdate;\n #mapUnsubscribe = new Map();\n\n /**\n * @param {Function} indexUpdate - update function for the indexer.\n *\n * @returns {[AdapterFilters, {filters: FilterData[]}]} Returns this and internal storage for filter adapters.\n */\n constructor(indexUpdate)\n {\n this.#indexUpdate = indexUpdate;\n\n this.#filtersAdapter = { filters: [] };\n\n Object.seal(this);\n\n return [this, this.#filtersAdapter];\n }\n\n /**\n * @returns {number} Returns the length of the\n */\n get length() { return this.#filtersAdapter.filters.length; }\n\n /**\n * Provides an iterator for filters.\n *\n * @returns {Generator, *>} Generator / iterator of filters.\n * @yields {FilterData}\n */\n *[Symbol.iterator]()\n {\n if (this.#filtersAdapter.filters.length === 0) { return; }\n\n for (const entry of this.#filtersAdapter.filters)\n {\n yield { ...entry };\n }\n }\n\n /**\n * @param {...(FilterFn|FilterData)} filters -\n */\n add(...filters)\n {\n /**\n * Tracks the number of filters added that have subscriber functionality.\n *\n * @type {number}\n */\n let subscribeCount = 0;\n\n for (const filter of filters)\n {\n const filterType = typeof filter;\n\n if (filterType !== 'function' && filterType !== 'object' || filter === null)\n {\n throw new TypeError(`DynArrayReducer error: 'filter' is not a function or object.`);\n }\n\n let data = void 0;\n let subscribeFn = void 0;\n\n switch (filterType)\n {\n case 'function':\n data = {\n id: void 0,\n filter,\n weight: 1\n };\n\n subscribeFn = filter.subscribe;\n break;\n\n case 'object':\n if (typeof filter.filter !== 'function')\n {\n throw new TypeError(`DynArrayReducer error: 'filter' attribute is not a function.`);\n }\n\n if (filter.weight !== void 0 && typeof filter.weight !== 'number' ||\n (filter.weight < 0 || filter.weight > 1))\n {\n throw new TypeError(\n `DynArrayReducer error: 'weight' attribute is not a number between '0 - 1' inclusive.`);\n }\n\n data = {\n id: filter.id !== void 0 ? filter.id : void 0,\n filter: filter.filter,\n weight: filter.weight || 1\n };\n\n subscribeFn = filter.filter.subscribe ?? filter.subscribe;\n break;\n }\n\n // Find the index to insert where data.weight is less than existing values weight.\n const index = this.#filtersAdapter.filters.findIndex((value) =>\n {\n return data.weight < value.weight;\n });\n\n // If an index was found insert at that location.\n if (index >= 0)\n {\n this.#filtersAdapter.filters.splice(index, 0, data);\n }\n else // push to end of filters.\n {\n this.#filtersAdapter.filters.push(data);\n }\n\n if (typeof subscribeFn === 'function')\n {\n const unsubscribe = subscribeFn(this.#indexUpdate);\n\n // Ensure that unsubscribe is a function.\n if (typeof unsubscribe !== 'function')\n {\n throw new TypeError(\n 'DynArrayReducer error: Filter has subscribe function, but no unsubscribe function is returned.');\n }\n\n // Ensure that the same filter is not subscribed to multiple times.\n if (this.#mapUnsubscribe.has(data.filter))\n {\n throw new Error(\n 'DynArrayReducer error: Filter added already has an unsubscribe function registered.');\n }\n\n this.#mapUnsubscribe.set(data.filter, unsubscribe);\n subscribeCount++;\n }\n }\n\n // Filters with subscriber functionality are assumed to immediately invoke the `subscribe` callback. If the\n // subscriber count is less than the amount of filters added then automatically trigger an index update manually.\n if (subscribeCount < filters.length) { this.#indexUpdate(); }\n }\n\n clear()\n {\n this.#filtersAdapter.filters.length = 0;\n\n // Unsubscribe from all filters with subscription support.\n for (const unsubscribe of this.#mapUnsubscribe.values())\n {\n unsubscribe();\n }\n\n this.#mapUnsubscribe.clear();\n\n this.#indexUpdate();\n }\n\n /**\n * @param {...(FilterFn|FilterData)} filters -\n */\n remove(...filters)\n {\n const length = this.#filtersAdapter.filters.length;\n\n if (length === 0) { return; }\n\n for (const data of filters)\n {\n // Handle the case that the filter may either be a function or a filter entry / object.\n const actualFilter = typeof data === 'function' ? data : data !== null && typeof data === 'object' ?\n data.filter : void 0;\n\n if (!actualFilter) { continue; }\n\n for (let cntr = this.#filtersAdapter.filters.length; --cntr >= 0;)\n {\n if (this.#filtersAdapter.filters[cntr].filter === actualFilter)\n {\n this.#filtersAdapter.filters.splice(cntr, 1);\n\n // Invoke any unsubscribe function for given filter then remove from tracking.\n let unsubscribe = void 0;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(actualFilter)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(actualFilter);\n }\n }\n }\n }\n\n // Update the index a filter was removed.\n if (length !== this.#filtersAdapter.filters.length) { this.#indexUpdate(); }\n }\n\n /**\n * Remove filters by the provided callback. The callback takes 3 parameters: `id`, `filter`, and `weight`.\n * Any truthy value returned will remove that filter.\n *\n * @param {function(*, FilterFn, number): boolean} callback - Callback function to evaluate each filter entry.\n */\n removeBy(callback)\n {\n const length = this.#filtersAdapter.filters.length;\n\n if (length === 0) { return; }\n\n if (typeof callback !== 'function')\n {\n throw new TypeError(`DynArrayReducer error: 'callback' is not a function.`);\n }\n\n this.#filtersAdapter.filters = this.#filtersAdapter.filters.filter((data) =>\n {\n const remove = callback.call(callback, { ...data });\n\n if (remove)\n {\n let unsubscribe;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(data.filter)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(data.filter);\n }\n }\n\n // Reverse remove boolean to properly filter / remove this filter.\n return !remove;\n });\n\n if (length !== this.#filtersAdapter.filters.length) { this.#indexUpdate(); }\n }\n\n removeById(...ids)\n {\n const length = this.#filtersAdapter.filters.length;\n\n if (length === 0) { return; }\n\n this.#filtersAdapter.filters = this.#filtersAdapter.filters.filter((data) =>\n {\n let remove = false;\n\n for (const id of ids) { remove |= data.id === id; }\n\n // If not keeping invoke any unsubscribe function for given filter then remove from tracking.\n if (remove)\n {\n let unsubscribe;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(data.filter)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(data.filter);\n }\n }\n\n return !remove; // Swap here to actually remove the item via array filter method.\n });\n\n if (length !== this.#filtersAdapter.filters.length) { this.#indexUpdate(); }\n }\n}\n\n/**\n * @template T\n */\nclass AdapterSort\n{\n #sortAdapter;\n #indexUpdate;\n #unsubscribe;\n\n /**\n * @param {Function} indexUpdate - Function to update indexer.\n *\n * @returns {[AdapterSort, {compareFn: CompareFn}]} This and the internal sort adapter data.\n */\n constructor(indexUpdate)\n {\n this.#indexUpdate = indexUpdate;\n\n this.#sortAdapter = { compareFn: null };\n\n Object.seal(this);\n\n return [this, this.#sortAdapter];\n }\n\n /**\n * @param {CompareFn|SortData} data -\n *\n * A callback function that compares two values. Return > 0 to sort b before a;\n * < 0 to sort a before b; or 0 to keep original order of a & b.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#parameters\n */\n set(data)\n {\n if (typeof this.#unsubscribe === 'function')\n {\n this.#unsubscribe();\n this.#unsubscribe = void 0;\n }\n\n let compareFn = void 0;\n let subscribeFn = void 0;\n\n switch (typeof data)\n {\n case 'function':\n compareFn = data;\n subscribeFn = data.subscribe;\n break;\n\n case 'object':\n // Early out if data is null / noop.\n if (data === null) { break; }\n\n if (typeof data.compare !== 'function')\n {\n throw new TypeError(`DynArrayReducer error: 'compare' attribute is not a function.`);\n }\n\n compareFn = data.compare;\n subscribeFn = data.compare.subscribe ?? data.subscribe;\n break;\n }\n\n if (typeof compareFn === 'function')\n {\n this.#sortAdapter.compareFn = compareFn;\n }\n else\n {\n const oldCompareFn = this.#sortAdapter.compareFn;\n this.#sortAdapter.compareFn = null;\n\n // Update index if the old compare function exists.\n if (typeof oldCompareFn === 'function') { this.#indexUpdate(); }\n return;\n }\n\n if (typeof subscribeFn === 'function')\n {\n this.#unsubscribe = subscribeFn(this.#indexUpdate);\n\n // Ensure that unsubscribe is a function.\n if (typeof this.#unsubscribe !== 'function')\n {\n throw new Error(\n `DynArrayReducer error: sort has 'subscribe' function, but no 'unsubscribe' function is returned.`);\n }\n }\n else\n {\n // A sort function with subscriber functionality are assumed to immediately invoke the `subscribe` callback.\n // Only manually update the index if there is no subscriber functionality.\n this.#indexUpdate();\n }\n }\n\n reset()\n {\n const oldCompareFn = this.#sortAdapter.compareFn;\n\n this.#sortAdapter.compareFn = null;\n\n if (typeof this.#unsubscribe === 'function')\n {\n this.#unsubscribe();\n this.#unsubscribe = void 0;\n }\n\n // Only update index if an old compare function is set.\n if (typeof oldCompareFn === 'function') { this.#indexUpdate(); }\n }\n}\n\nclass Indexer\n{\n constructor(host, hostItems, hostUpdate)\n {\n this.hostItems = hostItems;\n this.hostUpdate = hostUpdate;\n\n const indexAdapter = { index: null, hash: null };\n\n const publicAPI = {\n update: this.update.bind(this),\n\n /**\n * Provides an iterator over the index array.\n *\n * @returns {Generator} Iterator.\n * @yields\n */\n [Symbol.iterator]: function *()\n {\n if (!indexAdapter.index) { return; }\n\n const reversed = host.reversed;\n const length = indexAdapter.index.length;\n\n if (reversed)\n {\n for (let cntr = length; --cntr >= 0;) { yield indexAdapter.index[cntr]; }\n }\n else\n {\n for (let cntr = 0; cntr < length; cntr++) { yield indexAdapter.index[cntr]; }\n }\n }\n };\n\n // Define a getter on the public API to get the length / count of index array.\n Object.defineProperties(publicAPI, {\n hash: { get: () => indexAdapter.hash },\n isActive: { get: () => this.isActive() },\n length: { get: () => Array.isArray(indexAdapter.index) ? indexAdapter.index.length : 0 }\n });\n\n Object.freeze(publicAPI);\n\n indexAdapter.publicAPI = publicAPI;\n\n this.indexAdapter = indexAdapter;\n\n return [this, indexAdapter];\n }\n\n /**\n * Calculates a new hash value for the new index array if any. If the new index array is null then the hash value\n * is set to null. Set calculated new hash value to the index adapter hash value.\n *\n * After hash generation compare old and new hash values and perform an update if they are different. If they are\n * equal check for array equality between the old and new index array and perform an update if they are not equal.\n *\n * @param {number[]} oldIndex - Old index array.\n *\n * @param {number|null} oldHash - Old index hash value.\n *\n * @param {boolean} [force=false] - When true forces an update to subscribers.\n */\n calcHashUpdate(oldIndex, oldHash, force = false)\n {\n // Use force if a boolean otherwise default to false.\n const actualForce = typeof force === 'boolean' ? force : /* c8 ignore next */ false;\n\n let newHash = null;\n const newIndex = this.indexAdapter.index;\n\n if (newIndex)\n {\n for (let cntr = newIndex.length; --cntr >= 0;)\n {\n newHash ^= newIndex[cntr] + 0x9e3779b9 + (newHash << 6) + (newHash >> 2);\n }\n }\n\n this.indexAdapter.hash = newHash;\n\n if (actualForce || (oldHash === newHash ? !s_ARRAY_EQUALS(oldIndex, newIndex) : true)) { this.hostUpdate(); }\n }\n\n initAdapters(filtersAdapter, sortAdapter)\n {\n this.filtersAdapter = filtersAdapter;\n this.sortAdapter = sortAdapter;\n\n this.sortFn = (a, b) =>\n {\n return this.sortAdapter.compareFn(this.hostItems[a], this.hostItems[b]);\n };\n }\n\n isActive()\n {\n return this.filtersAdapter.filters.length > 0 || this.sortAdapter.compareFn !== null;\n }\n\n /**\n * Provides the custom filter / reduce step that is ~25-40% faster than implementing with `Array.reduce`.\n *\n * Note: Other loop unrolling techniques like Duff's Device gave a slight faster lower bound on large data sets,\n * but the maintenance factor is not worth the extra complication.\n *\n * @returns {number[]} New filtered index array.\n */\n reduceImpl()\n {\n const data = [];\n\n const filters = this.filtersAdapter.filters;\n\n let include = true;\n\n for (let cntr = 0, length = this.hostItems.length; cntr < length; cntr++)\n {\n include = true;\n\n for (let filCntr = 0, filLength = filters.length; filCntr < filLength; filCntr++)\n {\n if (!filters[filCntr].filter(this.hostItems[cntr]))\n {\n include = false;\n break;\n }\n }\n\n if (include) { data.push(cntr); }\n }\n\n return data;\n }\n\n /**\n * Update the reducer indexes. If there are changes subscribers are notified. If data order is changed externally\n * pass in true to force an update to subscribers.\n *\n * @param {boolean} [force=false] - When true forces an update to subscribers.\n */\n update(force = false)\n {\n const oldIndex = this.indexAdapter.index;\n const oldHash = this.indexAdapter.hash;\n\n // Clear index if there are no filters and no sort function or the index length doesn't match the item length.\n if ((this.filtersAdapter.filters.length === 0 && !this.sortAdapter.compareFn) ||\n (this.indexAdapter.index && this.hostItems.length !== this.indexAdapter.index.length))\n {\n this.indexAdapter.index = null;\n }\n\n // If there are filters build new index.\n if (this.filtersAdapter.filters.length > 0) { this.indexAdapter.index = this.reduceImpl(); }\n\n if (this.sortAdapter.compareFn)\n {\n // If there is no index then create one with keys matching host item length.\n if (!this.indexAdapter.index) { this.indexAdapter.index = [...Array(this.hostItems.length).keys()]; }\n\n this.indexAdapter.index.sort(this.sortFn);\n }\n\n this.calcHashUpdate(oldIndex, oldHash, force);\n }\n}\n\n/**\n * Checks for array equality between two arrays of numbers.\n *\n * @param {number[]} a - Array A\n *\n * @param {number[]} b - Array B\n *\n * @returns {boolean} Arrays equal\n */\nfunction s_ARRAY_EQUALS(a, b)\n{\n if (a === b) { return true; }\n if (a === null || b === null) { return false; }\n\n /* c8 ignore next */\n if (a.length !== b.length) { return false; }\n\n for (let cntr = a.length; --cntr >= 0;)\n {\n /* c8 ignore next */\n if (a[cntr] !== b[cntr]) { return false; }\n }\n\n return true;\n}\n\n/**\n * Provides a managed array with non-destructive reducing / filtering / sorting capabilities with subscription /\n * Svelte store support.\n *\n * @template T\n */\nclass DynArrayReducer\n{\n #items;\n\n #index;\n #indexAdapter;\n\n /**\n * @type {AdapterFilters}\n */\n #filters;\n\n /**\n * @type {{filters: FilterFn[]}}\n */\n #filtersAdapter;\n\n /**\n * @type {boolean}\n */\n #reversed = false;\n\n /**\n * @type {AdapterSort}\n */\n #sort;\n\n /**\n * @type {{compareFn: CompareFn}}\n */\n #sortAdapter;\n\n #subscriptions = [];\n\n /**\n * Initializes DynArrayReducer. Any iterable is supported for initial data. Take note that if `data` is an array it\n * will be used as the host array and not copied. All non-array iterables otherwise create a new array / copy.\n *\n * @param {Iterable|DynData} [data=[]] - Data iterable to store if array or copy otherwise.\n */\n constructor(data = [])\n {\n let dataIterable = void 0;\n let filters = void 0;\n let sort = void 0;\n\n // Potentially working with DynData.\n if (!DynArrayReducer.#isIterable(data) && data !== null && typeof data === 'object')\n {\n if (!DynArrayReducer.#isIterable(data.data))\n {\n throw new TypeError(`DynArrayReducer error (DynData): 'data' attribute is not iterable.`);\n }\n\n dataIterable = data.data;\n\n if (data.filters !== void 0)\n {\n if (DynArrayReducer.#isIterable(data.filters))\n {\n filters = data.filters;\n }\n else\n {\n throw new TypeError(`DynArrayReducer error (DynData): 'filters' attribute is not iterable.`);\n }\n }\n\n if (data.sort !== void 0)\n {\n if (typeof data.sort === 'function')\n {\n sort = data.sort;\n }\n else\n {\n throw new TypeError(`DynArrayReducer error (DynData): 'sort' attribute is not a function.`);\n }\n }\n }\n else\n {\n if (!DynArrayReducer.#isIterable(data)) { throw new TypeError(`DynArrayReducer error: 'data' is not iterable.`); }\n\n dataIterable = data;\n }\n\n // In the case of the main data being an array directly use the array otherwise create a copy.\n this.#items = Array.isArray(dataIterable) ? dataIterable : [...dataIterable];\n\n [this.#index, this.#indexAdapter] = new Indexer(this, this.#items, this.#notify.bind(this));\n\n [this.#filters, this.#filtersAdapter] = new AdapterFilters(this.#indexAdapter.publicAPI.update);\n [this.#sort, this.#sortAdapter] = new AdapterSort(this.#indexAdapter.publicAPI.update);\n\n this.#index.initAdapters(this.#filtersAdapter, this.#sortAdapter);\n\n // Add any filters and sort function defined by DynData.\n if (filters) { this.filters.add(...filters); }\n if (sort) { this.sort.set(sort); }\n }\n\n /**\n * Provides a utility method to determine if the given data is iterable / implements iterator protocol.\n *\n * @param {*} data - Data to verify as iterable.\n *\n * @returns {boolean} Is data iterable.\n */\n static #isIterable(data)\n {\n return data !== null && data !== void 0 && typeof data === 'object' && typeof data[Symbol.iterator] === 'function';\n }\n\n /**\n * Returns the internal data of this instance. Be careful!\n *\n * Note: if an array is set as initial data then that array is used as the internal data. If any changes are\n * performed to the data externally do invoke {@link index.update} with `true` to recalculate the index and notify\n * all subscribers.\n *\n * @returns {T[]} The internal data.\n */\n get data() { return this.#items; }\n\n /**\n * @returns {AdapterFilters} The filters adapter.\n */\n get filters() { return this.#filters; }\n\n /**\n * Returns the Indexer public API.\n *\n * @returns {IndexerAPI & Iterable} Indexer API - is also iterable.\n */\n get index() { return this.#indexAdapter.publicAPI; }\n\n /**\n * Gets the main data / items length.\n *\n * @returns {number} Main data / items length.\n */\n get length() { return this.#items.length; }\n\n /**\n * Gets current reversed state.\n *\n * @returns {boolean} Reversed state.\n */\n get reversed() { return this.#reversed; }\n\n /**\n * @returns {AdapterSort} The sort adapter.\n */\n get sort() { return this.#sort; }\n\n /**\n * Sets reversed state and notifies subscribers.\n *\n * @param {boolean} reversed - New reversed state.\n */\n set reversed(reversed)\n {\n if (typeof reversed !== 'boolean')\n {\n throw new TypeError(`DynArrayReducer.reversed error: 'reversed' is not a boolean.`);\n }\n\n this.#reversed = reversed;\n\n // Recalculate index and force an update to any subscribers.\n this.index.update(true);\n }\n\n /**\n * Removes internal data and pushes new data. This does not destroy any initial array set to internal data unless\n * `replace` is set to true.\n *\n * @param {T[] | Iterable} data - New data to set to internal data.\n *\n * @param {boolean} [replace=false] - New data to set to internal data.\n */\n setData(data, replace = false)\n {\n if (!DynArrayReducer.#isIterable(data))\n {\n throw new TypeError(`DynArrayReducer.setData error: 'data' is not iterable.`);\n }\n\n if (typeof replace !== 'boolean')\n {\n throw new TypeError(`DynArrayReducer.setData error: 'replace' is not a boolean.`);\n }\n\n // Replace internal data with new array or create an array from an iterable.\n if (replace)\n {\n this.#items = Array.isArray(data) ? data : [...data];\n }\n else\n {\n // Remove all entries in internal data. This will not replace any initially set array.\n this.#items.length = 0;\n\n // Add all new data.\n this.#items.push(...data);\n }\n\n // Recalculate index and force an update to any subscribers.\n this.index.update(true);\n }\n\n /**\n *\n * @param {function(DynArrayReducer): void} handler - Callback function that is invoked on update / changes.\n * Receives `this` reference.\n *\n * @returns {(function(): void)} Unsubscribe function.\n */\n subscribe(handler)\n {\n this.#subscriptions.push(handler); // add handler to the array of subscribers\n\n handler(this); // call handler with current value\n\n // Return unsubscribe function.\n return () =>\n {\n const index = this.#subscriptions.findIndex((sub) => sub === handler);\n if (index >= 0) { this.#subscriptions.splice(index, 1); }\n };\n }\n\n /**\n *\n */\n #notify()\n {\n // Subscriptions are stored locally as on the browser Babel is still used for private class fields / Babel\n // support until 2023. IE not doing this will require several extra method calls otherwise.\n const subscriptions = this.#subscriptions;\n for (let cntr = 0; cntr < subscriptions.length; cntr++) { subscriptions[cntr](this); }\n }\n\n /**\n * Provides an iterator for data stored in DynArrayReducer.\n *\n * @returns {Generator<*, T, *>} Generator / iterator of all data.\n * @yields {T}\n */\n *[Symbol.iterator]()\n {\n const items = this.#items;\n\n if (items.length === 0) { return; }\n\n if (this.#index.isActive())\n {\n for (const entry of this.index) { yield items[entry]; }\n }\n else\n {\n if (this.reversed)\n {\n for (let cntr = items.length; --cntr >= 0;) { yield items[cntr]; }\n }\n else\n {\n for (let cntr = 0; cntr < items.length; cntr++) { yield items[cntr]; }\n }\n }\n }\n}\n\n/**\n * Provides a basic test for a given variable to test if it has the shape of a readable store by having a `subscribe`\n * function.\n *\n * Note: functions are also objects, so test that the variable might be a function w/ a `subscribe` function.\n *\n * @param {*} store - variable to test that might be a store.\n *\n * @returns {boolean} Whether the variable tested has the shape of a store.\n */\nfunction isReadableStore(store)\n{\n if (store === null || store === void 0) { return false; }\n\n switch (typeof store)\n {\n case 'function':\n case 'object':\n return typeof store.subscribe === 'function';\n }\n\n return false;\n}\n\n/**\n * Provides a basic test for a given variable to test if it has the shape of a writable store by having a `subscribe`\n * function and an `update` function.\n *\n * Note: functions are also objects, so test that the variable might be a function w/ a `subscribe` function.\n *\n * @param {*} store - variable to test that might be a store.\n *\n * @returns {boolean} Whether the variable tested has the shape of a store.\n */\nfunction isUpdatableStore(store)\n{\n if (store === null || store === void 0) { return false; }\n\n switch (typeof store)\n {\n case 'function':\n case 'object':\n return typeof store.subscribe === 'function' && typeof store.update === 'function';\n }\n\n return false;\n}\n\n/**\n * Provides a basic test for a given variable to test if it has the shape of a writable store by having a `subscribe`\n * `set`, and `update` functions.\n *\n * Note: functions are also objects, so test that the variable might be a function w/ `subscribe` & `set` functions.\n *\n * @param {*} store - variable to test that might be a store.\n *\n * @returns {boolean} Whether the variable tested has the shape of a store.\n */\nfunction isWritableStore(store)\n{\n if (store === null || store === void 0) { return false; }\n\n switch (typeof store)\n {\n case 'function':\n case 'object':\n return typeof store.subscribe === 'function' && typeof store.set === 'function';\n }\n\n return false;\n}\n\n/**\n * Subscribes to the given store with the update function provided and ignores the first automatic\n * update. All future updates are dispatched to the update function.\n *\n * @param {import('svelte/store').Readable | import('svelte/store').Writable} store -\n * Store to subscribe to...\n *\n * @param {import('svelte/store').Updater} update - function to receive future updates.\n *\n * @returns {import('svelte/store').Unsubscriber} Store unsubscribe function.\n */\nfunction subscribeIgnoreFirst(store, update)\n{\n let firedFirst = false;\n\n return store.subscribe((value) => {\n if (!firedFirst)\n {\n firedFirst = true;\n }\n else {\n update(value);\n }\n })\n}\n\n/**\n * Subscribes to the given store with two update functions provided. The first function is invoked on the initial\n * subscription. All future updates are dispatched to the update function.\n *\n * @param {import('svelte/store').Readable | import('svelte/store').Writable} store -\n * Store to subscribe to...\n *\n * @param {import('svelte/store').Updater} first - Function to receive first update.\n *\n * @param {import('svelte/store').Updater} update - Function to receive future updates.\n *\n * @returns {import('svelte/store').Unsubscriber} Store unsubscribe function.\n */\nfunction subscribeFirstRest(store, first, update)\n{\n let firedFirst = false;\n\n return store.subscribe((value) => {\n if (!firedFirst)\n {\n firedFirst = true;\n first(value);\n }\n else {\n update(value);\n }\n })\n}\n\n// src/generator.ts\nfunction isSimpleDeriver(deriver) {\n return deriver.length < 2;\n}\nfunction generator(storage) {\n function readable(key, value, start) {\n return {\n subscribe: writable(key, value, start).subscribe\n };\n }\n function writable(key, value, start = noop) {\n function wrap_start(ogSet) {\n return start(function wrap_set(new_value) {\n if (storage) {\n storage.setItem(key, JSON.stringify(new_value));\n }\n return ogSet(new_value);\n });\n }\n if (storage) {\n const storageValue = storage.getItem(key);\n try {\n if (storageValue) {\n value = JSON.parse(storageValue);\n }\n } catch (err) {\n }\n storage.setItem(key, JSON.stringify(value));\n }\n const ogStore = writable$2(value, start ? wrap_start : void 0);\n function set(new_value) {\n if (storage) {\n storage.setItem(key, JSON.stringify(new_value));\n }\n ogStore.set(new_value);\n }\n function update(fn) {\n set(fn(get(ogStore)));\n }\n function subscribe(run, invalidate = noop) {\n return ogStore.subscribe(run, invalidate);\n }\n return {set, update, subscribe};\n }\n function derived(key, stores, fn, initial_value) {\n const single = !Array.isArray(stores);\n const stores_array = single ? [stores] : stores;\n if (storage && storage.getItem(key)) {\n try {\n initial_value = JSON.parse(storage.getItem(key));\n } catch (err) {\n }\n }\n return readable(key, initial_value, (set) => {\n let inited = false;\n const values = [];\n let pending = 0;\n let cleanup = noop;\n const sync = () => {\n if (pending) {\n return;\n }\n cleanup();\n const input = single ? values[0] : values;\n if (isSimpleDeriver(fn)) {\n set(fn(input));\n } else {\n const result = fn(input, set);\n cleanup = is_function(result) ? result : noop;\n }\n };\n const unsubscribers = stores_array.map((store, i) => store.subscribe((value) => {\n values[i] = value;\n pending &= ~(1 << i);\n if (inited) {\n sync();\n }\n }, () => {\n pending |= 1 << i;\n }));\n inited = true;\n sync();\n return function stop() {\n run_all(unsubscribers);\n cleanup();\n };\n });\n }\n return {\n readable,\n writable,\n derived,\n get: get\n };\n}\n\n// src/local.ts\nvar storage$1 = typeof window !== \"undefined\" ? window.localStorage : void 0;\nvar g$1 = generator(storage$1);\nvar writable$1 = g$1.writable;\n\n/**\n * @typedef {import('svelte/store').Writable} LSStore - The backing Svelte store; a writable w/ get method attached.\n */\n\nclass LocalStorage\n{\n /**\n * @type {Map}\n */\n #stores = new Map();\n\n /**\n * Creates a new LSStore for the given key.\n *\n * @param {string} key - Key to lookup in stores map.\n *\n * @param {boolean} [defaultValue] - A default value to set for the store.\n *\n * @returns {LSStore} The new LSStore.\n */\n static #createStore(key, defaultValue = void 0)\n {\n try\n {\n const value = localStorage.getItem(key);\n if (value !== null) { defaultValue = value === 'undefined' ? void 0 : JSON.parse(value); }\n }\n catch (err) { /**/ }\n\n return writable$1(key, defaultValue);\n }\n\n /**\n * Gets a store from the LSStore Map or creates a new store for the key and a given default value.\n *\n * @param {string} key - Key to lookup in stores map.\n *\n * @param {boolean} [defaultValue] - A default value to set for the store.\n *\n * @returns {LSStore} The store for the given key.\n */\n #getStore(key, defaultValue = void 0)\n {\n let store = this.#stores.get(key);\n if (store === void 0)\n {\n store = LocalStorage.#createStore(key, defaultValue);\n this.#stores.set(key, store);\n }\n\n return store;\n }\n\n /**\n * Get value from the localStorage.\n *\n * @param {string} key - Key to lookup in localStorage.\n *\n * @param {*} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {*} Value from session storage or if not defined any default value provided.\n */\n getItem(key, defaultValue)\n {\n let value = defaultValue;\n\n const storageValue = localStorage.getItem(key);\n\n if (storageValue !== null)\n {\n try\n {\n value = storageValue === 'undefined' ? void 0 : JSON.parse(storageValue);\n } catch (err)\n {\n value = defaultValue;\n }\n }\n else if (defaultValue !== void 0)\n {\n try\n {\n const newValue = JSON.stringify(defaultValue);\n\n // If there is no existing storage value and defaultValue is defined the storage value needs to be set.\n localStorage.setItem(key, newValue === 'undefined' ? void 0 : newValue);\n }\n catch (err) { /* */ }\n }\n\n return value;\n }\n\n /**\n * Returns the backing Svelte store for the given key; potentially sets a default value if the key\n * is not already set.\n *\n * @param {string} key - Key to lookup in localStorage.\n *\n * @param {*} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {LSStore} The Svelte store for this key.\n */\n getStore(key, defaultValue)\n {\n return this.#getStore(key, defaultValue);\n }\n\n /**\n * Sets the value for the given key in localStorage.\n *\n * @param {string} key - Key to lookup in localStorage.\n *\n * @param {*} value - A value to set for this key.\n */\n setItem(key, value)\n {\n const store = this.#getStore(key);\n store.set(value);\n }\n\n /**\n * Convenience method to swap a boolean value stored in session storage.\n *\n * @param {string} key - Key to lookup in localStorage.\n *\n * @param {boolean} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {boolean} The boolean swap for the given key.\n */\n swapItemBoolean(key, defaultValue)\n {\n const store = this.#getStore(key, defaultValue);\n\n let currentValue = false;\n\n try\n {\n currentValue = !!JSON.parse(localStorage.getItem(key));\n }\n catch (err) { /**/ }\n\n const newValue = typeof currentValue === 'boolean' ? !currentValue : false;\n\n store.set(newValue);\n return newValue;\n }\n}\n\n// src/session.ts\nvar storage = typeof window !== \"undefined\" ? window.sessionStorage : void 0;\nvar g = generator(storage);\nvar writable = g.writable;\n\n/**\n * @typedef {import('svelte/store').Writable} SSStore - The backing Svelte store; a writable w/ get method attached.\n */\n\nclass SessionStorage\n{\n /**\n * @type {Map}\n */\n #stores = new Map();\n\n /**\n * Creates a new SSStore for the given key.\n *\n * @param {string} key - Key to lookup in stores map.\n *\n * @param {boolean} [defaultValue] - A default value to set for the store.\n *\n * @returns {LSStore} The new LSStore.\n */\n static #createStore(key, defaultValue = void 0)\n {\n try\n {\n const value = sessionStorage.getItem(key);\n if (value !== null) { defaultValue = value === 'undefined' ? void 0 : JSON.parse(value); }\n }\n catch (err) { /**/ }\n\n return writable(key, defaultValue);\n }\n\n /**\n * Gets a store from the SSStore Map or creates a new store for the key and a given default value.\n *\n * @param {string} key - Key to lookup in stores map.\n *\n * @param {boolean} [defaultValue] - A default value to set for the store.\n *\n * @returns {LSStore} The store for the given key.\n */\n #getStore(key, defaultValue = void 0)\n {\n let store = this.#stores.get(key);\n if (store === void 0)\n {\n store = SessionStorage.#createStore(key, defaultValue);\n this.#stores.set(key, store);\n }\n\n return store;\n }\n\n /**\n * Get value from the sessionStorage.\n *\n * @param {string} key - Key to lookup in sessionStorage.\n *\n * @param {*} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {*} Value from session storage or if not defined any default value provided.\n */\n getItem(key, defaultValue)\n {\n let value = defaultValue;\n\n const storageValue = sessionStorage.getItem(key);\n\n if (storageValue !== null)\n {\n try\n {\n value = storageValue === 'undefined' ? void 0 : JSON.parse(storageValue);\n } catch (err)\n {\n value = defaultValue;\n }\n }\n else if (defaultValue !== void 0)\n {\n try\n {\n const newValue = JSON.stringify(defaultValue);\n\n // If there is no existing storage value and defaultValue is defined the storage value needs to be set.\n sessionStorage.setItem(key, newValue === 'undefined' ? void 0 : newValue);\n }\n catch (err) { /* */ }\n }\n\n return value;\n }\n\n /**\n * Returns the backing Svelte store for the given key; potentially sets a default value if the key\n * is not already set.\n *\n * @param {string} key - Key to lookup in sessionStorage.\n *\n * @param {*} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {LSStore} The Svelte store for this key.\n */\n getStore(key, defaultValue)\n {\n return this.#getStore(key, defaultValue);\n }\n\n /**\n * Sets the value for the given key in sessionStorage.\n *\n * @param {string} key - Key to lookup in sessionStorage.\n *\n * @param {*} value - A value to set for this key.\n */\n setItem(key, value)\n {\n const store = this.#getStore(key);\n store.set(value);\n }\n\n /**\n * Convenience method to swap a boolean value stored in session storage.\n *\n * @param {string} key - Key to lookup in sessionStorage.\n *\n * @param {boolean} [defaultValue] - A default value to return if key not present in session storage.\n *\n * @returns {boolean} The boolean swap for the given key.\n */\n swapItemBoolean(key, defaultValue)\n {\n const store = this.#getStore(key, defaultValue);\n\n let currentValue = false;\n\n try\n {\n currentValue = !!JSON.parse(sessionStorage.getItem(key));\n }\n catch (err) { /**/ }\n\n const newValue = typeof currentValue === 'boolean' ? !currentValue : false;\n\n store.set(newValue);\n return newValue;\n }\n}\n\n/**\n * @external Store\n * @see [Svelte stores](https://svelte.dev/docs#component-format-script-4-prefix-stores-with-$-to-access-their-values-store-contract)\n */\n\n/**\n * Create a store similar to [Svelte's `derived`](https://svelte.dev/docs#run-time-svelte-store-writable),\n * but which has its own `set` and `update` methods and can send values back to the origin stores.\n * [Read more...](https://github.com/PixievoltNo1/svelte-writable-derived#default-export-writablederived)\n * \n * @param {Store|Store[]} origins One or more stores to derive from. Same as\n * [`derived`](https://svelte.dev/docs#run-time-svelte-store-writable)'s 1st parameter.\n * @param {!Function} derive The callback to determine the derived value. Same as\n * [`derived`](https://svelte.dev/docs#run-time-svelte-store-writable)'s 2nd parameter.\n * @param {!Function|{withOld: !Function}} reflect Called when the\n * derived store gets a new value via its `set` or `update` methods, and determines new values for\n * the origin stores. [Read more...](https://github.com/PixievoltNo1/svelte-writable-derived#new-parameter-reflect)\n * @param [initial] The new store's initial value. Same as\n * [`derived`](https://svelte.dev/docs#run-time-svelte-store-writable)'s 3rd parameter.\n * \n * @returns {Store} A writable store.\n */\nfunction writableDerived(origins, derive, reflect, initial) {\n\tvar childDerivedSetter, originValues, blockNextDerive = false;\n\tvar reflectOldValues = \"withOld\" in reflect;\n\tvar wrappedDerive = (got, set) => {\n\t\tchildDerivedSetter = set;\n\t\tif (reflectOldValues) {\n\t\t\toriginValues = got;\n\t\t}\n\t\tif (!blockNextDerive) {\n\t\t\tlet returned = derive(got, set);\n\t\t\tif (derive.length < 2) {\n\t\t\t\tset(returned);\n\t\t\t} else {\n\t\t\t\treturn returned;\n\t\t\t}\n\t\t}\n\t\tblockNextDerive = false;\n\t};\n\tvar childDerived = derived(origins, wrappedDerive, initial);\n\t\n\tvar singleOrigin = !Array.isArray(origins);\n\tvar sendUpstream = (setWith) => {\n\t\tif (singleOrigin) {\n\t\t\tblockNextDerive = true;\n\t\t\torigins.set(setWith);\n\t\t} else {\n\t\t\tsetWith.forEach( (value, i) => {\n\t\t\t\tblockNextDerive = true;\n\t\t\t\torigins[i].set(value);\n\t\t\t} );\n\t\t}\n\t\tblockNextDerive = false;\n\t};\n\tif (reflectOldValues) {\n\t\treflect = reflect.withOld;\n\t}\n\tvar reflectIsAsync = reflect.length >= (reflectOldValues ? 3 : 2);\n\tvar cleanup = null;\n\tfunction doReflect(reflecting) {\n\t\tif (cleanup) {\n\t\t\tcleanup();\n\t\t\tcleanup = null;\n\t\t}\n\n\t\tif (reflectOldValues) {\n\t\t\tvar returned = reflect(reflecting, originValues, sendUpstream);\n\t\t} else {\n\t\t\tvar returned = reflect(reflecting, sendUpstream);\n\t\t}\n\t\tif (reflectIsAsync) {\n\t\t\tif (typeof returned == \"function\") {\n\t\t\t\tcleanup = returned;\n\t\t\t}\n\t\t} else {\n\t\t\tsendUpstream(returned);\n\t\t}\n\t}\n\t\n\tvar tryingSet = false;\n\tfunction update(fn) {\n\t\tvar isUpdated, mutatedBySubscriptions, oldValue, newValue;\n\t\tif (tryingSet) {\n\t\t\tnewValue = fn( get(childDerived) );\n\t\t\tchildDerivedSetter(newValue);\n\t\t\treturn;\n\t\t}\n\t\tvar unsubscribe = childDerived.subscribe( (value) => {\n\t\t\tif (!tryingSet) {\n\t\t\t\toldValue = value;\n\t\t\t} else if (!isUpdated) {\n\t\t\t\tisUpdated = true;\n\t\t\t} else {\n\t\t\t\tmutatedBySubscriptions = true;\n\t\t\t}\n\t\t} );\n\t\tnewValue = fn(oldValue);\n\t\ttryingSet = true;\n\t\tchildDerivedSetter(newValue);\n\t\tunsubscribe();\n\t\ttryingSet = false;\n\t\tif (mutatedBySubscriptions) {\n\t\t\tnewValue = get(childDerived);\n\t\t}\n\t\tif (isUpdated) {\n\t\t\tdoReflect(newValue);\n\t\t}\n\t}\n\treturn {\n\t\tsubscribe: childDerived.subscribe,\n\t\tset(value) { update( () => value ); },\n\t\tupdate,\n\t};\n}\n\n/**\n * Create a store for a property value in an object contained in another store.\n * [Read more...](https://github.com/PixievoltNo1/svelte-writable-derived#named-export-propertystore)\n * \n * @param {Store} origin The store containing the object to get/set from.\n * @param {string|number|symbol|Array} propName The property to get/set, or a path of\n * properties in nested objects.\n *\n * @returns {Store} A writable store.\n */\nfunction propertyStore(origin, propName) {\n\tif (!Array.isArray(propName)) {\n\t\treturn writableDerived(\n\t\t\torigin,\n\t\t\t(object) => object[propName],\n\t\t\t{ withOld(reflecting, object) {\n\t\t\t\tobject[propName] = reflecting;\n\t\t\t\treturn object;\n\t\t\t} }\n\t\t);\n\t} else {\n\t\tlet props = propName.concat();\n\t\treturn writableDerived(\n\t\t\torigin,\n\t\t\t(value) => {\n\t\t\t\tfor (let i = 0; i < props.length; ++i) {\n\t\t\t\t\tvalue = value[ props[i] ];\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\t{ withOld(reflecting, object) {\n\t\t\t\tlet target = object;\n\t\t\t\tfor (let i = 0; i < props.length - 1; ++i) {\n\t\t\t\t\ttarget = target[ props[i] ];\n\t\t\t\t}\n\t\t\t\ttarget[ props[props.length - 1] ] = reflecting;\n\t\t\t\treturn object;\n\t\t\t} }\n\t\t);\n\t}\n}\n\n/**\n * Provides a wrapper implementing the Svelte store / subscriber protocol around any Document / ClientMixinDocument.\n * This makes documents reactive in a Svelte component, but otherwise provides subscriber functionality external to\n * Svelte.\n *\n * @template {foundry.abstract.Document} T\n */\nclass TJSDocument\n{\n #document;\n #uuidv4;\n\n /**\n * @type {TJSDocumentOptions}\n */\n #options = { delete: void 0 };\n\n #subscriptions = [];\n #updateOptions;\n\n /**\n * @param {T|TJSDocumentOptions} [document] - Document to wrap or TJSDocumentOptions.\n *\n * @param {TJSDocumentOptions} [options] - TJSDocument options.\n */\n constructor(document, options = {})\n {\n this.#uuidv4 = `tjs-document-${uuidv4()}`;\n\n if (isPlainObject(document)) // Handle case when only options are passed into ctor.\n {\n this.setOptions(document);\n }\n else\n {\n this.setOptions(options);\n this.set(document);\n }\n }\n\n /**\n * Returns the options passed on last update.\n *\n * @returns {object} Last update options.\n */\n get updateOptions() { return this.#updateOptions ?? {}; }\n\n /**\n * Returns the UUID assigned to this store.\n *\n * @returns {*} UUID\n */\n get uuidv4() { return this.#uuidv4; }\n\n /**\n * Handles cleanup when the document is deleted. Invoking any optional delete function set in the constructor.\n *\n * @returns {Promise}\n */\n async #deleted()\n {\n const doc = this.#document;\n\n // Check to see if the document is still in the associated collection to determine if actually deleted.\n if (doc instanceof foundry.abstract.Document && !doc?.collection?.has(doc.id))\n {\n delete doc?.apps[this.#uuidv4];\n this.#document = void 0;\n\n this.#notify(false, { action: 'delete', data: void 0 });\n\n if (typeof this.#options.delete === 'function') { await this.#options.delete(); }\n\n this.#updateOptions = void 0;\n }\n }\n\n /**\n * Completely removes all internal subscribers, any optional delete callback, and unregisters from the\n * ClientDocumentMixin `apps` tracking object.\n */\n destroy()\n {\n const doc = this.#document;\n\n if (doc instanceof foundry.abstract.Document)\n {\n delete doc?.apps[this.#uuidv4];\n this.#document = void 0;\n }\n\n this.#options.delete = void 0;\n this.#subscriptions.length = 0;\n }\n\n /**\n * @param {boolean} [force] - unused - signature from Foundry render function.\n *\n * @param {object} [options] - Options from render call; will have document update context.\n */\n #notify(force = false, options = {}) // eslint-disable-line no-unused-vars\n {\n this.#updateOptions = options;\n\n // Subscriptions are stored locally as on the browser Babel is still used for private class fields / Babel\n // support until 2023. IE not doing this will require several extra method calls otherwise.\n const subscriptions = this.#subscriptions;\n const document = this.#document;\n\n for (let cntr = 0; cntr < subscriptions.length; cntr++) { subscriptions[cntr](document, options); }\n }\n\n /**\n * @returns {T | undefined} Current document\n */\n get() { return this.#document; }\n\n /**\n * @param {T | undefined} document - New document to set.\n *\n * @param {object} [options] - New document update options to set.\n */\n set(document, options = {})\n {\n if (this.#document)\n {\n delete this.#document.apps[this.#uuidv4];\n }\n\n if (document !== void 0 && !(document instanceof foundry.abstract.Document))\n {\n throw new TypeError(`TJSDocument set error: 'document' is not a valid Document or undefined.`);\n }\n\n if (options === null || typeof options !== 'object')\n {\n throw new TypeError(`TJSDocument set error: 'options' is not an object.`);\n }\n\n if (document instanceof foundry.abstract.Document)\n {\n document.apps[this.#uuidv4] = {\n close: this.#deleted.bind(this),\n render: this.#notify.bind(this)\n };\n }\n\n this.#document = document;\n this.#updateOptions = options;\n this.#notify();\n }\n\n /**\n * Potentially sets new document from data transfer object.\n *\n * @param {object} data - Document transfer data.\n *\n * @param {ParseDataTransferOptions & TJSDocumentOptions} [options] - Optional parameters.\n *\n * @returns {Promise} Returns true if new document set from data transfer blob.\n */\n async setFromDataTransfer(data, options)\n {\n return this.setFromUUID(getUUIDFromDataTransfer(data, options), options);\n }\n\n /**\n * Sets the document by Foundry UUID performing a lookup and setting the document if found.\n *\n * @param {string} uuid - A Foundry UUID to lookup.\n *\n * @param {TJSDocumentOptions} [options] - New document update options to set.\n *\n * @returns {Promise} True if successfully set document from UUID.\n */\n async setFromUUID(uuid, options = {})\n {\n if (typeof uuid !== 'string' || uuid.length === 0) { return false; }\n\n try\n {\n const doc = await globalThis.fromUuid(uuid);\n\n if (doc)\n {\n this.set(doc, options);\n return true;\n }\n }\n catch (err) { /**/ }\n\n return false;\n }\n\n /**\n * Sets options for this document wrapper / store.\n *\n * @param {TJSDocumentOptions} options - Options for TJSDocument.\n */\n setOptions(options)\n {\n if (!isObject(options))\n {\n throw new TypeError(`TJSDocument error: 'options' is not a plain object.`);\n }\n\n if (options.delete !== void 0 && typeof options.delete !== 'function')\n {\n throw new TypeError(`TJSDocument error: 'delete' attribute in options is not a function.`);\n }\n\n if (options.delete === void 0 || typeof options.delete === 'function')\n {\n this.#options.delete = options.delete;\n }\n }\n\n /**\n * @param {function(T, object): void} handler - Callback function that is invoked on update / changes.\n *\n * @returns {(function(): void)} Unsubscribe function.\n */\n subscribe(handler)\n {\n this.#subscriptions.push(handler); // Add handler to the array of subscribers.\n\n const updateOptions = { action: 'subscribe', data: void 0 };\n\n handler(this.#document, updateOptions); // Call handler with current value and update options.\n\n // Return unsubscribe function.\n return () =>\n {\n const index = this.#subscriptions.findIndex((sub) => sub === handler);\n if (index >= 0) { this.#subscriptions.splice(index, 1); }\n };\n }\n}\n\n/**\n * @typedef {object} TJSDocumentOptions\n *\n * @property {Function} [delete] - Optional delete function to invoke when document is deleted.\n */\n\n/**\n * Provides a wrapper implementing the Svelte store / subscriber protocol around any DocumentCollection. This makes\n * document collections reactive in a Svelte component, but otherwise provides subscriber functionality external to\n * Svelte.\n *\n * @template {DocumentCollection} T\n */\nclass TJSDocumentCollection\n{\n #collection;\n #collectionCallback;\n #uuid;\n\n /**\n * @type {TJSDocumentCollectionOptions}\n */\n #options = { delete: void 0 };\n\n #subscriptions = [];\n #updateOptions;\n\n /**\n * @param {T|TJSDocumentCollectionOptions} [collection] - Collection to wrap or TJSDocumentCollectionOptions.\n *\n * @param {TJSDocumentCollectionOptions} [options] - TJSDocumentCollection options.\n */\n constructor(collection, options = {})\n {\n this.#uuid = `tjs-collection-${uuidv4()}`;\n\n if (isPlainObject(collection)) // Handle case when only options are passed into ctor.\n {\n this.setOptions(collection);\n }\n else\n {\n this.setOptions(options);\n this.set(collection);\n }\n }\n\n /**\n * Returns the options passed on last update.\n *\n * @returns {object} Last update options.\n */\n get updateOptions() { return this.#updateOptions ?? {}; }\n\n /**\n * Returns the UUID assigned to this store.\n *\n * @returns {*} UUID\n */\n get uuid() { return this.#uuid; }\n\n /**\n * Handles cleanup when the collection is deleted. Invoking any optional delete function set in the constructor.\n *\n * @returns {Promise}\n */\n async #deleted()\n {\n const collection = this.#collection;\n\n if (collection instanceof DocumentCollection)\n {\n const index = collection?.apps?.findIndex((sub) => sub === this.#collectionCallback);\n if (index >= 0) { collection?.apps?.splice(index, 1); }\n\n this.#collection = void 0;\n }\n\n this.#notify(false, { action: 'delete', documentType: collection.documentName, documents: [], data: [] });\n\n if (typeof this.#options.delete === 'function') { await this.#options.delete(); }\n\n this.#updateOptions = void 0;\n }\n\n /**\n * Completely removes all internal subscribers, any optional delete callback, and unregisters from the\n * DocumentCollection `apps` tracking array.\n */\n destroy()\n {\n const collection = this.#collection;\n\n if (collection instanceof DocumentCollection)\n {\n const index = collection?.apps?.findIndex((sub) => sub === this.#collectionCallback);\n if (index >= 0) { collection?.apps?.splice(index, 1); }\n\n this.#collection = void 0;\n }\n\n this.#options.delete = void 0;\n this.#subscriptions.length = 0;\n }\n\n /**\n * @param {boolean} [force] - unused - signature from Foundry render function.\n *\n * @param {object} [options] - Options from render call; will have collection update context.\n */\n #notify(force = false, options = {}) // eslint-disable-line no-unused-vars\n {\n this.#updateOptions = options;\n\n // Subscriptions are stored locally as on the browser Babel is still used for private class fields / Babel\n // support until 2023. IE not doing this will require several extra method calls otherwise.\n const subscriptions = this.#subscriptions;\n const collection = this.#collection;\n\n for (let cntr = 0; cntr < subscriptions.length; cntr++) { subscriptions[cntr](collection, options); }\n }\n\n /**\n * @returns {T | undefined} Current collection\n */\n get() { return this.#collection; }\n\n /**\n * @param {T | undefined} collection - New collection to set.\n *\n * @param {object} [options] - New collection update options to set.\n */\n set(collection, options = {})\n {\n if (this.#collection)\n {\n const index = this.#collection.apps.findIndex((sub) => sub === this.#collectionCallback);\n if (index >= 0) { this.#collection.apps.splice(index, 1); }\n\n this.#collectionCallback = void 0;\n }\n\n if (collection !== void 0 && !(collection instanceof DocumentCollection))\n {\n throw new TypeError(\n `TJSDocumentCollection set error: 'collection' is not a valid DocumentCollection or undefined.`);\n }\n\n if (!isObject(options))\n {\n throw new TypeError(`TJSDocument set error: 'options' is not an object.`);\n }\n\n if (collection instanceof DocumentCollection)\n {\n this.#collectionCallback = {\n close: this.#deleted.bind(this),\n render: this.#notify.bind(this)\n };\n\n collection?.apps?.push(this.#collectionCallback);\n }\n\n this.#collection = collection;\n this.#updateOptions = options;\n this.#notify();\n }\n\n /**\n * Sets options for this collection wrapper / store.\n *\n * @param {TJSDocumentCollectionOptions} options - Options for TJSDocumentCollection.\n */\n setOptions(options)\n {\n if (!isObject(options))\n {\n throw new TypeError(`TJSDocumentCollection error: 'options' is not an object.`);\n }\n\n if (options.delete !== void 0 && typeof options.delete !== 'function')\n {\n throw new TypeError(`TJSDocumentCollection error: 'delete' attribute in options is not a function.`);\n }\n\n if (options.delete === void 0 || typeof options.delete === 'function')\n {\n this.#options.delete = options.delete;\n }\n }\n\n /**\n * @param {function(T, object): void} handler - Callback function that is invoked on update / changes.\n *\n * @returns {(function(): void)} Unsubscribe function.\n */\n subscribe(handler)\n {\n this.#subscriptions.push(handler); // Add handler to the array of subscribers.\n\n const collection = this.#collection;\n\n const documentType = collection?.documentName ?? void 0;\n\n const updateOptions = { action: 'subscribe', documentType, documents: [], data: [] };\n\n handler(collection, updateOptions); // Call handler with current value and update options.\n\n // Return unsubscribe function.\n return () =>\n {\n const index = this.#subscriptions.findIndex((sub) => sub === handler);\n if (index >= 0) { this.#subscriptions.splice(index, 1); }\n };\n }\n}\n\n/**\n * @typedef TJSDocumentCollectionOptions\n *\n * @property {Function} [delete] - Optional delete function to invoke when document is deleted.\n */\n\nconst storeState = writable$2(void 0);\n\n/**\n * @type {GameState} Provides a Svelte store wrapping the Foundry runtime / global game state.\n */\nconst gameState = {\n subscribe: storeState.subscribe,\n get: () => game\n};\n\nObject.freeze(gameState);\n\nHooks.once('ready', () => storeState.set(game));\n\n/**\n * @typedef {import('svelte/store').Readable} GameState - Provides a Svelte store wrapping the Foundry `game` global variable. It is initialized\n * on the `ready` hook. You may use this store to access the global game state from a Svelte template. It is a read only\n * store and will receive no reactive updates during runtime.\n *\n * @property {import('svelte/store').Readable.subscribe} subscribe - Provides the Svelte store subscribe function.\n *\n * @property {Function} get - Provides a mechanism to directly access the Foundry game state without subscribing.\n */\n\n/**\n * Registers game settings and creates a backing Svelte store for each setting. It is possible to add multiple\n * `onChange` callbacks on registration.\n */\nclass TJSGameSettings\n{\n /**\n * @type {Map}\n */\n #stores = new Map();\n\n /**\n * Creates a new GSWritableStore for the given key.\n *\n * @param {string} initialValue - An initial value to set to new stores.\n *\n * @returns {GSWritableStore} The new GSWritableStore.\n */\n static #createStore(initialValue)\n {\n return writable$2(initialValue);\n }\n\n /**\n * Gets a store from the GSWritableStore Map or creates a new store for the key.\n *\n * @param {string} key - Key to lookup in stores map.\n *\n * @param {string} [initialValue] - An initial value to set to new stores.\n *\n * @returns {GSWritableStore} The store for the given key.\n */\n #getStore(key, initialValue)\n {\n let store = this.#stores.get(key);\n if (store === void 0)\n {\n store = TJSGameSettings.#createStore(initialValue);\n this.#stores.set(key, store);\n }\n\n return store;\n }\n\n /**\n * Returns a readable Game Settings store for the associated key.\n *\n * @param {string} key - Game setting key.\n *\n * @returns {GSReadableStore|undefined} The associated store for the given game setting key.\n */\n getReadableStore(key)\n {\n if (!this.#stores.has(key))\n {\n console.warn(`TJSGameSettings - getReadableStore: '${key}' is not a registered setting.`);\n return;\n }\n\n const store = this.#getStore(key);\n\n return { subscribe: store.subscribe, get: store.get };\n }\n\n /**\n * Returns a writable Game Settings store for the associated key.\n *\n * @param {string} key - Game setting key.\n *\n * @returns {GSWritableStore|undefined} The associated store for the given game setting key.\n */\n getStore(key)\n {\n return this.getWritableStore(key);\n }\n\n /**\n * Returns a writable Game Settings store for the associated key.\n *\n * @param {string} key - Game setting key.\n *\n * @returns {GSWritableStore|undefined} The associated store for the given game setting key.\n */\n getWritableStore(key)\n {\n if (!this.#stores.has(key))\n {\n console.warn(`TJSGameSettings - getWritableStore: '${key}' is not a registered setting.`);\n return;\n }\n\n return this.#getStore(key);\n }\n\n /**\n * @param {GameSetting} setting - A GameSetting instance to set to Foundry game settings.\n */\n register(setting)\n {\n if (typeof setting !== 'object')\n {\n throw new TypeError(`TJSGameSettings - register: setting is not an object.`);\n }\n\n if (typeof setting.options !== 'object')\n {\n throw new TypeError(`TJSGameSettings - register: 'options' attribute is not an object.`);\n }\n\n if (setting.store !== void 0 && !isWritableStore(setting.store))\n {\n throw new TypeError(\n `TJSGameSettings - register: 'setting.store' attribute is not a writable store.`);\n }\n\n // TODO: Remove deprecation warning and fully remove support for `moduleId` in a future TRL release.\n if (typeof setting.moduleId === 'string')\n {\n console.warn(\n `TJSGameSettings - register deprecation warning: 'moduleId' should be replaced with 'namespace'.`);\n console.warn(`'moduleId' will cease to work in a future update of TRL / TJSGameSettings.`);\n }\n\n // TODO: Remove nullish coalescing operator in a future TRL release.\n const namespace = setting.namespace ?? setting.moduleId;\n const key = setting.key;\n\n if (typeof namespace !== 'string')\n {\n throw new TypeError(`TJSGameSettings - register: 'namespace' attribute is not a string.`);\n }\n\n if (typeof key !== 'string')\n {\n throw new TypeError(`TJSGameSettings - register: 'key' attribute is not a string.`);\n }\n\n const store = setting.store;\n\n /**\n * @type {GameSettingOptions}\n */\n const options = setting.options;\n\n const onchangeFunctions = [];\n\n // When true prevents local store subscription from a loop when values are object data.\n let gateSet = false;\n\n // Provides an `onChange` callback to update the associated store.\n onchangeFunctions.push((value) =>\n {\n const callbackStore = this.#getStore(key);\n if (callbackStore && !gateSet)\n {\n gateSet = true;\n callbackStore.set(value);\n gateSet = false;\n }\n });\n\n // Handle loading any existing `onChange` callbacks.\n if (isIterable(options?.onChange))\n {\n for (const entry of options.onChange)\n {\n if (typeof entry === 'function') { onchangeFunctions.push(entry); }\n }\n }\n else if (typeof options.onChange === 'function')\n {\n onchangeFunctions.push(options.onChange);\n }\n\n // Provides the final onChange callback that iterates over all the stored onChange callbacks.\n const onChange = (value) =>\n {\n for (const entry of onchangeFunctions) { entry(value); }\n };\n\n game.settings.register(namespace, key, { ...options, onChange });\n\n // Set new store value with existing setting or default value.\n const targetStore = store ? store : this.#getStore(key, game.settings.get(namespace, key));\n\n // If a store instance is passed into register then initialize it with game settings data.\n if (store)\n {\n this.#stores.set(key, targetStore);\n store.set(game.settings.get(namespace, key));\n }\n\n // Subscribe to self to set associated game setting on updates after verifying that the new value does not match\n // existing game setting.\n subscribeIgnoreFirst(targetStore, async (value) =>\n {\n if (!gateSet && game.settings.get(namespace, key) !== value)\n {\n gateSet = true;\n await game.settings.set(namespace, key, value);\n }\n\n gateSet = false;\n });\n }\n\n /**\n * Registers multiple settings.\n *\n * @param {Iterable} settings - An iterable list of game setting configurations to register.\n */\n registerAll(settings)\n {\n if (!isIterable(settings)) { throw new TypeError(`TJSGameSettings - registerAll: settings is not iterable.`); }\n\n for (const entry of settings)\n {\n if (typeof entry !== 'object')\n {\n throw new TypeError(`TJSGameSettings - registerAll: entry in settings is not an object.`);\n }\n\n // TODO: Uncomment when deprecation for 'moduleId' is removed in future TRL release.\n // if (typeof entry.namespace !== 'string')\n // {\n // throw new TypeError(`TJSGameSettings - registerAll: entry in settings missing 'namespace' attribute.`);\n // }\n\n if (typeof entry.key !== 'string')\n {\n throw new TypeError(`TJSGameSettings - registerAll: entry in settings missing 'key' attribute.`);\n }\n\n if (typeof entry.options !== 'object')\n {\n throw new TypeError(`TJSGameSettings - registerAll: entry in settings missing 'options' attribute.`);\n }\n\n this.register(entry);\n }\n }\n}\n\nexport { DynArrayReducer, LocalStorage, SessionStorage, TJSDocument, TJSDocumentCollection, TJSGameSettings, gameState, isReadableStore, isUpdatableStore, isWritableStore, propertyStore, subscribeFirstRest, subscribeIgnoreFirst, writableDerived };\n//# sourceMappingURL=index.js.map\n","export { identity as linear } from '../internal/index.mjs';\n\n/*\nAdapted from https://github.com/mattdesl\nDistributed under MIT License https://github.com/mattdesl/eases/blob/master/LICENSE.md\n*/\nfunction backInOut(t) {\n const s = 1.70158 * 1.525;\n if ((t *= 2) < 1)\n return 0.5 * (t * t * ((s + 1) * t - s));\n return 0.5 * ((t -= 2) * t * ((s + 1) * t + s) + 2);\n}\nfunction backIn(t) {\n const s = 1.70158;\n return t * t * ((s + 1) * t - s);\n}\nfunction backOut(t) {\n const s = 1.70158;\n return --t * t * ((s + 1) * t + s) + 1;\n}\nfunction bounceOut(t) {\n const a = 4.0 / 11.0;\n const b = 8.0 / 11.0;\n const c = 9.0 / 10.0;\n const ca = 4356.0 / 361.0;\n const cb = 35442.0 / 1805.0;\n const cc = 16061.0 / 1805.0;\n const t2 = t * t;\n return t < a\n ? 7.5625 * t2\n : t < b\n ? 9.075 * t2 - 9.9 * t + 3.4\n : t < c\n ? ca * t2 - cb * t + cc\n : 10.8 * t * t - 20.52 * t + 10.72;\n}\nfunction bounceInOut(t) {\n return t < 0.5\n ? 0.5 * (1.0 - bounceOut(1.0 - t * 2.0))\n : 0.5 * bounceOut(t * 2.0 - 1.0) + 0.5;\n}\nfunction bounceIn(t) {\n return 1.0 - bounceOut(1.0 - t);\n}\nfunction circInOut(t) {\n if ((t *= 2) < 1)\n return -0.5 * (Math.sqrt(1 - t * t) - 1);\n return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);\n}\nfunction circIn(t) {\n return 1.0 - Math.sqrt(1.0 - t * t);\n}\nfunction circOut(t) {\n return Math.sqrt(1 - --t * t);\n}\nfunction cubicInOut(t) {\n return t < 0.5 ? 4.0 * t * t * t : 0.5 * Math.pow(2.0 * t - 2.0, 3.0) + 1.0;\n}\nfunction cubicIn(t) {\n return t * t * t;\n}\nfunction cubicOut(t) {\n const f = t - 1.0;\n return f * f * f + 1.0;\n}\nfunction elasticInOut(t) {\n return t < 0.5\n ? 0.5 *\n Math.sin(((+13.0 * Math.PI) / 2) * 2.0 * t) *\n Math.pow(2.0, 10.0 * (2.0 * t - 1.0))\n : 0.5 *\n Math.sin(((-13.0 * Math.PI) / 2) * (2.0 * t - 1.0 + 1.0)) *\n Math.pow(2.0, -10.0 * (2.0 * t - 1.0)) +\n 1.0;\n}\nfunction elasticIn(t) {\n return Math.sin((13.0 * t * Math.PI) / 2) * Math.pow(2.0, 10.0 * (t - 1.0));\n}\nfunction elasticOut(t) {\n return (Math.sin((-13.0 * (t + 1.0) * Math.PI) / 2) * Math.pow(2.0, -10.0 * t) + 1.0);\n}\nfunction expoInOut(t) {\n return t === 0.0 || t === 1.0\n ? t\n : t < 0.5\n ? +0.5 * Math.pow(2.0, 20.0 * t - 10.0)\n : -0.5 * Math.pow(2.0, 10.0 - t * 20.0) + 1.0;\n}\nfunction expoIn(t) {\n return t === 0.0 ? t : Math.pow(2.0, 10.0 * (t - 1.0));\n}\nfunction expoOut(t) {\n return t === 1.0 ? t : 1.0 - Math.pow(2.0, -10.0 * t);\n}\nfunction quadInOut(t) {\n t /= 0.5;\n if (t < 1)\n return 0.5 * t * t;\n t--;\n return -0.5 * (t * (t - 2) - 1);\n}\nfunction quadIn(t) {\n return t * t;\n}\nfunction quadOut(t) {\n return -t * (t - 2.0);\n}\nfunction quartInOut(t) {\n return t < 0.5\n ? +8.0 * Math.pow(t, 4.0)\n : -8.0 * Math.pow(t - 1.0, 4.0) + 1.0;\n}\nfunction quartIn(t) {\n return Math.pow(t, 4.0);\n}\nfunction quartOut(t) {\n return Math.pow(t - 1.0, 3.0) * (1.0 - t) + 1.0;\n}\nfunction quintInOut(t) {\n if ((t *= 2) < 1)\n return 0.5 * t * t * t * t * t;\n return 0.5 * ((t -= 2) * t * t * t * t + 2);\n}\nfunction quintIn(t) {\n return t * t * t * t * t;\n}\nfunction quintOut(t) {\n return --t * t * t * t * t + 1;\n}\nfunction sineInOut(t) {\n return -0.5 * (Math.cos(Math.PI * t) - 1);\n}\nfunction sineIn(t) {\n const v = Math.cos(t * Math.PI * 0.5);\n if (Math.abs(v) < 1e-14)\n return 1;\n else\n return 1 - v;\n}\nfunction sineOut(t) {\n return Math.sin((t * Math.PI) / 2);\n}\n\nexport { backIn, backInOut, backOut, bounceIn, bounceInOut, bounceOut, circIn, circInOut, circOut, cubicIn, cubicInOut, cubicOut, elasticIn, elasticInOut, elasticOut, expoIn, expoInOut, expoOut, quadIn, quadInOut, quadOut, quartIn, quartInOut, quartOut, quintIn, quintInOut, quintOut, sineIn, sineInOut, sineOut };\n","/**\n * Performs linear interpolation between a start & end value by given amount between 0 - 1 inclusive.\n *\n * @param {number} start - Start value.\n *\n * @param {number} end - End value.\n *\n * @param {number} amount - Current amount between 0 - 1 inclusive.\n *\n * @returns {number} Linear interpolated value between start & end.\n */\nfunction lerp$5(start, end, amount)\n{\n return (1 - amount) * start + amount * end;\n}\n\n/**\n * Converts the given number from degrees to radians.\n *\n * @param {number} deg - Degree number to convert\n *\n * @returns {number} Degree as radians.\n */\nfunction degToRad(deg)\n{\n return deg * (Math.PI / 180.0);\n}\n\n/**\n * Converts the given number from radians to degrees.\n *\n * @param {number} rad - Radian number to convert.\n *\n * @returns {number} Degree as radians.\n */\nfunction radToDeg(rad)\n{\n return rad * (180.0 / Math.PI);\n}\n\n/**\n * Common utilities\n * @module glMatrix\n */\n// Configuration Constants\nvar EPSILON = 0.000001;\nvar ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;\nvar RANDOM = Math.random;\n/**\n * Sets the type of array used when creating new vectors and matrices\n *\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\n */\n\nfunction setMatrixArrayType(type) {\n ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\n/**\n * Convert Degree To Radian\n *\n * @param {Number} a Angle in Degrees\n */\n\nfunction toRadian(a) {\n return a * degree;\n}\n/**\n * Tests whether or not the arguments have approximately the same value, within an absolute\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\n * than or equal to 1.0, and a relative tolerance is used for larger values)\n *\n * @param {Number} a The first number to test.\n * @param {Number} b The second number to test.\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\n */\n\nfunction equals$9(a, b) {\n return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));\n}\nif (!Math.hypot) Math.hypot = function () {\n var y = 0,\n i = arguments.length;\n\n while (i--) {\n y += arguments[i] * arguments[i];\n }\n\n return Math.sqrt(y);\n};\n\nvar common = /*#__PURE__*/Object.freeze({\n __proto__: null,\n EPSILON: EPSILON,\n get ARRAY_TYPE () { return ARRAY_TYPE; },\n RANDOM: RANDOM,\n setMatrixArrayType: setMatrixArrayType,\n toRadian: toRadian,\n equals: equals$9\n});\n\n/**\n * 2x2 Matrix\n * @module mat2\n */\n\n/**\n * Creates a new identity mat2\n *\n * @returns {mat2} a new 2x2 matrix\n */\n\nfunction create$8() {\n var out = new ARRAY_TYPE(4);\n\n if (ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n }\n\n out[0] = 1;\n out[3] = 1;\n return out;\n}\n/**\n * Creates a new mat2 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat2} a matrix to clone\n * @returns {mat2} a new 2x2 matrix\n */\n\nfunction clone$8(a) {\n var out = new ARRAY_TYPE(4);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n}\n/**\n * Copy the values from one mat2 to another\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the source matrix\n * @returns {mat2} out\n */\n\nfunction copy$8(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n}\n/**\n * Set a mat2 to the identity matrix\n *\n * @param {mat2} out the receiving matrix\n * @returns {mat2} out\n */\n\nfunction identity$5(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n}\n/**\n * Create a new mat2 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m10 Component in column 1, row 0 position (index 2)\n * @param {Number} m11 Component in column 1, row 1 position (index 3)\n * @returns {mat2} out A new 2x2 matrix\n */\n\nfunction fromValues$8(m00, m01, m10, m11) {\n var out = new ARRAY_TYPE(4);\n out[0] = m00;\n out[1] = m01;\n out[2] = m10;\n out[3] = m11;\n return out;\n}\n/**\n * Set the components of a mat2 to the given values\n *\n * @param {mat2} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m10 Component in column 1, row 0 position (index 2)\n * @param {Number} m11 Component in column 1, row 1 position (index 3)\n * @returns {mat2} out\n */\n\nfunction set$8(out, m00, m01, m10, m11) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m10;\n out[3] = m11;\n return out;\n}\n/**\n * Transpose the values of a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the source matrix\n * @returns {mat2} out\n */\n\nfunction transpose$2(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache\n // some values\n if (out === a) {\n var a1 = a[1];\n out[1] = a[2];\n out[2] = a1;\n } else {\n out[0] = a[0];\n out[1] = a[2];\n out[2] = a[1];\n out[3] = a[3];\n }\n\n return out;\n}\n/**\n * Inverts a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the source matrix\n * @returns {mat2} out\n */\n\nfunction invert$5(out, a) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3]; // Calculate the determinant\n\n var det = a0 * a3 - a2 * a1;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = a3 * det;\n out[1] = -a1 * det;\n out[2] = -a2 * det;\n out[3] = a0 * det;\n return out;\n}\n/**\n * Calculates the adjugate of a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the source matrix\n * @returns {mat2} out\n */\n\nfunction adjoint$2(out, a) {\n // Caching this value is nessecary if out == a\n var a0 = a[0];\n out[0] = a[3];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = a0;\n return out;\n}\n/**\n * Calculates the determinant of a mat2\n *\n * @param {ReadonlyMat2} a the source matrix\n * @returns {Number} determinant of a\n */\n\nfunction determinant$3(a) {\n return a[0] * a[3] - a[2] * a[1];\n}\n/**\n * Multiplies two mat2's\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the first operand\n * @param {ReadonlyMat2} b the second operand\n * @returns {mat2} out\n */\n\nfunction multiply$8(out, a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = a0 * b0 + a2 * b1;\n out[1] = a1 * b0 + a3 * b1;\n out[2] = a0 * b2 + a2 * b3;\n out[3] = a1 * b2 + a3 * b3;\n return out;\n}\n/**\n * Rotates a mat2 by the given angle\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2} out\n */\n\nfunction rotate$4(out, a, rad) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n out[0] = a0 * c + a2 * s;\n out[1] = a1 * c + a3 * s;\n out[2] = a0 * -s + a2 * c;\n out[3] = a1 * -s + a3 * c;\n return out;\n}\n/**\n * Scales the mat2 by the dimensions in the given vec2\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the matrix to rotate\n * @param {ReadonlyVec2} v the vec2 to scale the matrix by\n * @returns {mat2} out\n **/\n\nfunction scale$8(out, a, v) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var v0 = v[0],\n v1 = v[1];\n out[0] = a0 * v0;\n out[1] = a1 * v0;\n out[2] = a2 * v1;\n out[3] = a3 * v1;\n return out;\n}\n/**\n * Creates a matrix from a given angle\n * This is equivalent to (but much faster than):\n *\n * mat2.identity(dest);\n * mat2.rotate(dest, dest, rad);\n *\n * @param {mat2} out mat2 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2} out\n */\n\nfunction fromRotation$4(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n out[0] = c;\n out[1] = s;\n out[2] = -s;\n out[3] = c;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat2.identity(dest);\n * mat2.scale(dest, dest, vec);\n *\n * @param {mat2} out mat2 receiving operation result\n * @param {ReadonlyVec2} v Scaling vector\n * @returns {mat2} out\n */\n\nfunction fromScaling$3(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = v[1];\n return out;\n}\n/**\n * Returns a string representation of a mat2\n *\n * @param {ReadonlyMat2} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nfunction str$8(a) {\n return \"mat2(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat2\n *\n * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nfunction frob$3(a) {\n return Math.hypot(a[0], a[1], a[2], a[3]);\n}\n/**\n * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix\n * @param {ReadonlyMat2} L the lower triangular matrix\n * @param {ReadonlyMat2} D the diagonal matrix\n * @param {ReadonlyMat2} U the upper triangular matrix\n * @param {ReadonlyMat2} a the input matrix to factorize\n */\n\nfunction LDU(L, D, U, a) {\n L[2] = a[2] / a[0];\n U[0] = a[0];\n U[1] = a[1];\n U[3] = a[3] - L[2] * U[1];\n return [L, D, U];\n}\n/**\n * Adds two mat2's\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the first operand\n * @param {ReadonlyMat2} b the second operand\n * @returns {mat2} out\n */\n\nfunction add$8(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the first operand\n * @param {ReadonlyMat2} b the second operand\n * @returns {mat2} out\n */\n\nfunction subtract$6(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat2} a The first matrix.\n * @param {ReadonlyMat2} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction exactEquals$8(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat2} a The first matrix.\n * @param {ReadonlyMat2} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction equals$8(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat2} out the receiving matrix\n * @param {ReadonlyMat2} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat2} out\n */\n\nfunction multiplyScalar$3(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n return out;\n}\n/**\n * Adds two mat2's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat2} out the receiving vector\n * @param {ReadonlyMat2} a the first operand\n * @param {ReadonlyMat2} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat2} out\n */\n\nfunction multiplyScalarAndAdd$3(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n return out;\n}\n/**\n * Alias for {@link mat2.multiply}\n * @function\n */\n\nvar mul$8 = multiply$8;\n/**\n * Alias for {@link mat2.subtract}\n * @function\n */\n\nvar sub$6 = subtract$6;\n\nvar mat2 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$8,\n clone: clone$8,\n copy: copy$8,\n identity: identity$5,\n fromValues: fromValues$8,\n set: set$8,\n transpose: transpose$2,\n invert: invert$5,\n adjoint: adjoint$2,\n determinant: determinant$3,\n multiply: multiply$8,\n rotate: rotate$4,\n scale: scale$8,\n fromRotation: fromRotation$4,\n fromScaling: fromScaling$3,\n str: str$8,\n frob: frob$3,\n LDU: LDU,\n add: add$8,\n subtract: subtract$6,\n exactEquals: exactEquals$8,\n equals: equals$8,\n multiplyScalar: multiplyScalar$3,\n multiplyScalarAndAdd: multiplyScalarAndAdd$3,\n mul: mul$8,\n sub: sub$6\n});\n\n/**\n * 2x3 Matrix\n * @module mat2d\n * @description\n * A mat2d contains six elements defined as:\n *
\n * [a, b,\n * c, d,\n * tx, ty]\n *
\n * This is a short form for the 3x3 matrix:\n *
\n * [a, b, 0,\n * c, d, 0,\n * tx, ty, 1]\n *
\n * The last column is ignored so the array is shorter and operations are faster.\n */\n\n/**\n * Creates a new identity mat2d\n *\n * @returns {mat2d} a new 2x3 matrix\n */\n\nfunction create$7() {\n var out = new ARRAY_TYPE(6);\n\n if (ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[4] = 0;\n out[5] = 0;\n }\n\n out[0] = 1;\n out[3] = 1;\n return out;\n}\n/**\n * Creates a new mat2d initialized with values from an existing matrix\n *\n * @param {ReadonlyMat2d} a matrix to clone\n * @returns {mat2d} a new 2x3 matrix\n */\n\nfunction clone$7(a) {\n var out = new ARRAY_TYPE(6);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n return out;\n}\n/**\n * Copy the values from one mat2d to another\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the source matrix\n * @returns {mat2d} out\n */\n\nfunction copy$7(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n return out;\n}\n/**\n * Set a mat2d to the identity matrix\n *\n * @param {mat2d} out the receiving matrix\n * @returns {mat2d} out\n */\n\nfunction identity$4(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = 0;\n out[5] = 0;\n return out;\n}\n/**\n * Create a new mat2d with the given values\n *\n * @param {Number} a Component A (index 0)\n * @param {Number} b Component B (index 1)\n * @param {Number} c Component C (index 2)\n * @param {Number} d Component D (index 3)\n * @param {Number} tx Component TX (index 4)\n * @param {Number} ty Component TY (index 5)\n * @returns {mat2d} A new mat2d\n */\n\nfunction fromValues$7(a, b, c, d, tx, ty) {\n var out = new ARRAY_TYPE(6);\n out[0] = a;\n out[1] = b;\n out[2] = c;\n out[3] = d;\n out[4] = tx;\n out[5] = ty;\n return out;\n}\n/**\n * Set the components of a mat2d to the given values\n *\n * @param {mat2d} out the receiving matrix\n * @param {Number} a Component A (index 0)\n * @param {Number} b Component B (index 1)\n * @param {Number} c Component C (index 2)\n * @param {Number} d Component D (index 3)\n * @param {Number} tx Component TX (index 4)\n * @param {Number} ty Component TY (index 5)\n * @returns {mat2d} out\n */\n\nfunction set$7(out, a, b, c, d, tx, ty) {\n out[0] = a;\n out[1] = b;\n out[2] = c;\n out[3] = d;\n out[4] = tx;\n out[5] = ty;\n return out;\n}\n/**\n * Inverts a mat2d\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the source matrix\n * @returns {mat2d} out\n */\n\nfunction invert$4(out, a) {\n var aa = a[0],\n ab = a[1],\n ac = a[2],\n ad = a[3];\n var atx = a[4],\n aty = a[5];\n var det = aa * ad - ab * ac;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = ad * det;\n out[1] = -ab * det;\n out[2] = -ac * det;\n out[3] = aa * det;\n out[4] = (ac * aty - ad * atx) * det;\n out[5] = (ab * atx - aa * aty) * det;\n return out;\n}\n/**\n * Calculates the determinant of a mat2d\n *\n * @param {ReadonlyMat2d} a the source matrix\n * @returns {Number} determinant of a\n */\n\nfunction determinant$2(a) {\n return a[0] * a[3] - a[1] * a[2];\n}\n/**\n * Multiplies two mat2d's\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the first operand\n * @param {ReadonlyMat2d} b the second operand\n * @returns {mat2d} out\n */\n\nfunction multiply$7(out, a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3],\n b4 = b[4],\n b5 = b[5];\n out[0] = a0 * b0 + a2 * b1;\n out[1] = a1 * b0 + a3 * b1;\n out[2] = a0 * b2 + a2 * b3;\n out[3] = a1 * b2 + a3 * b3;\n out[4] = a0 * b4 + a2 * b5 + a4;\n out[5] = a1 * b4 + a3 * b5 + a5;\n return out;\n}\n/**\n * Rotates a mat2d by the given angle\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2d} out\n */\n\nfunction rotate$3(out, a, rad) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5];\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n out[0] = a0 * c + a2 * s;\n out[1] = a1 * c + a3 * s;\n out[2] = a0 * -s + a2 * c;\n out[3] = a1 * -s + a3 * c;\n out[4] = a4;\n out[5] = a5;\n return out;\n}\n/**\n * Scales the mat2d by the dimensions in the given vec2\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the matrix to translate\n * @param {ReadonlyVec2} v the vec2 to scale the matrix by\n * @returns {mat2d} out\n **/\n\nfunction scale$7(out, a, v) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5];\n var v0 = v[0],\n v1 = v[1];\n out[0] = a0 * v0;\n out[1] = a1 * v0;\n out[2] = a2 * v1;\n out[3] = a3 * v1;\n out[4] = a4;\n out[5] = a5;\n return out;\n}\n/**\n * Translates the mat2d by the dimensions in the given vec2\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the matrix to translate\n * @param {ReadonlyVec2} v the vec2 to translate the matrix by\n * @returns {mat2d} out\n **/\n\nfunction translate$3(out, a, v) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5];\n var v0 = v[0],\n v1 = v[1];\n out[0] = a0;\n out[1] = a1;\n out[2] = a2;\n out[3] = a3;\n out[4] = a0 * v0 + a2 * v1 + a4;\n out[5] = a1 * v0 + a3 * v1 + a5;\n return out;\n}\n/**\n * Creates a matrix from a given angle\n * This is equivalent to (but much faster than):\n *\n * mat2d.identity(dest);\n * mat2d.rotate(dest, dest, rad);\n *\n * @param {mat2d} out mat2d receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2d} out\n */\n\nfunction fromRotation$3(out, rad) {\n var s = Math.sin(rad),\n c = Math.cos(rad);\n out[0] = c;\n out[1] = s;\n out[2] = -s;\n out[3] = c;\n out[4] = 0;\n out[5] = 0;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat2d.identity(dest);\n * mat2d.scale(dest, dest, vec);\n *\n * @param {mat2d} out mat2d receiving operation result\n * @param {ReadonlyVec2} v Scaling vector\n * @returns {mat2d} out\n */\n\nfunction fromScaling$2(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = v[1];\n out[4] = 0;\n out[5] = 0;\n return out;\n}\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat2d.identity(dest);\n * mat2d.translate(dest, dest, vec);\n *\n * @param {mat2d} out mat2d receiving operation result\n * @param {ReadonlyVec2} v Translation vector\n * @returns {mat2d} out\n */\n\nfunction fromTranslation$3(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = v[0];\n out[5] = v[1];\n return out;\n}\n/**\n * Returns a string representation of a mat2d\n *\n * @param {ReadonlyMat2d} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nfunction str$7(a) {\n return \"mat2d(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat2d\n *\n * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nfunction frob$2(a) {\n return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], 1);\n}\n/**\n * Adds two mat2d's\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the first operand\n * @param {ReadonlyMat2d} b the second operand\n * @returns {mat2d} out\n */\n\nfunction add$7(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the first operand\n * @param {ReadonlyMat2d} b the second operand\n * @returns {mat2d} out\n */\n\nfunction subtract$5(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n return out;\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat2d} out the receiving matrix\n * @param {ReadonlyMat2d} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat2d} out\n */\n\nfunction multiplyScalar$2(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n return out;\n}\n/**\n * Adds two mat2d's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat2d} out the receiving vector\n * @param {ReadonlyMat2d} a the first operand\n * @param {ReadonlyMat2d} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat2d} out\n */\n\nfunction multiplyScalarAndAdd$2(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat2d} a The first matrix.\n * @param {ReadonlyMat2d} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction exactEquals$7(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat2d} a The first matrix.\n * @param {ReadonlyMat2d} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction equals$7(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3],\n b4 = b[4],\n b5 = b[5];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5));\n}\n/**\n * Alias for {@link mat2d.multiply}\n * @function\n */\n\nvar mul$7 = multiply$7;\n/**\n * Alias for {@link mat2d.subtract}\n * @function\n */\n\nvar sub$5 = subtract$5;\n\nvar mat2d = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$7,\n clone: clone$7,\n copy: copy$7,\n identity: identity$4,\n fromValues: fromValues$7,\n set: set$7,\n invert: invert$4,\n determinant: determinant$2,\n multiply: multiply$7,\n rotate: rotate$3,\n scale: scale$7,\n translate: translate$3,\n fromRotation: fromRotation$3,\n fromScaling: fromScaling$2,\n fromTranslation: fromTranslation$3,\n str: str$7,\n frob: frob$2,\n add: add$7,\n subtract: subtract$5,\n multiplyScalar: multiplyScalar$2,\n multiplyScalarAndAdd: multiplyScalarAndAdd$2,\n exactEquals: exactEquals$7,\n equals: equals$7,\n mul: mul$7,\n sub: sub$5\n});\n\n/**\n * 3x3 Matrix\n * @module mat3\n */\n\n/**\n * Creates a new identity mat3\n *\n * @returns {mat3} a new 3x3 matrix\n */\n\nfunction create$6() {\n var out = new ARRAY_TYPE(9);\n\n if (ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n }\n\n out[0] = 1;\n out[4] = 1;\n out[8] = 1;\n return out;\n}\n/**\n * Copies the upper-left 3x3 values into the given mat3.\n *\n * @param {mat3} out the receiving 3x3 matrix\n * @param {ReadonlyMat4} a the source 4x4 matrix\n * @returns {mat3} out\n */\n\nfunction fromMat4$1(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[4];\n out[4] = a[5];\n out[5] = a[6];\n out[6] = a[8];\n out[7] = a[9];\n out[8] = a[10];\n return out;\n}\n/**\n * Creates a new mat3 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat3} a matrix to clone\n * @returns {mat3} a new 3x3 matrix\n */\n\nfunction clone$6(a) {\n var out = new ARRAY_TYPE(9);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n return out;\n}\n/**\n * Copy the values from one mat3 to another\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the source matrix\n * @returns {mat3} out\n */\n\nfunction copy$6(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n return out;\n}\n/**\n * Create a new mat3 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\n * @returns {mat3} A new mat3\n */\n\nfunction fromValues$6(m00, m01, m02, m10, m11, m12, m20, m21, m22) {\n var out = new ARRAY_TYPE(9);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m10;\n out[4] = m11;\n out[5] = m12;\n out[6] = m20;\n out[7] = m21;\n out[8] = m22;\n return out;\n}\n/**\n * Set the components of a mat3 to the given values\n *\n * @param {mat3} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\n * @returns {mat3} out\n */\n\nfunction set$6(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m10;\n out[4] = m11;\n out[5] = m12;\n out[6] = m20;\n out[7] = m21;\n out[8] = m22;\n return out;\n}\n/**\n * Set a mat3 to the identity matrix\n *\n * @param {mat3} out the receiving matrix\n * @returns {mat3} out\n */\n\nfunction identity$3(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 1;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 1;\n return out;\n}\n/**\n * Transpose the values of a mat3\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the source matrix\n * @returns {mat3} out\n */\n\nfunction transpose$1(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a12 = a[5];\n out[1] = a[3];\n out[2] = a[6];\n out[3] = a01;\n out[5] = a[7];\n out[6] = a02;\n out[7] = a12;\n } else {\n out[0] = a[0];\n out[1] = a[3];\n out[2] = a[6];\n out[3] = a[1];\n out[4] = a[4];\n out[5] = a[7];\n out[6] = a[2];\n out[7] = a[5];\n out[8] = a[8];\n }\n\n return out;\n}\n/**\n * Inverts a mat3\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the source matrix\n * @returns {mat3} out\n */\n\nfunction invert$3(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2];\n var a10 = a[3],\n a11 = a[4],\n a12 = a[5];\n var a20 = a[6],\n a21 = a[7],\n a22 = a[8];\n var b01 = a22 * a11 - a12 * a21;\n var b11 = -a22 * a10 + a12 * a20;\n var b21 = a21 * a10 - a11 * a20; // Calculate the determinant\n\n var det = a00 * b01 + a01 * b11 + a02 * b21;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = b01 * det;\n out[1] = (-a22 * a01 + a02 * a21) * det;\n out[2] = (a12 * a01 - a02 * a11) * det;\n out[3] = b11 * det;\n out[4] = (a22 * a00 - a02 * a20) * det;\n out[5] = (-a12 * a00 + a02 * a10) * det;\n out[6] = b21 * det;\n out[7] = (-a21 * a00 + a01 * a20) * det;\n out[8] = (a11 * a00 - a01 * a10) * det;\n return out;\n}\n/**\n * Calculates the adjugate of a mat3\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the source matrix\n * @returns {mat3} out\n */\n\nfunction adjoint$1(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2];\n var a10 = a[3],\n a11 = a[4],\n a12 = a[5];\n var a20 = a[6],\n a21 = a[7],\n a22 = a[8];\n out[0] = a11 * a22 - a12 * a21;\n out[1] = a02 * a21 - a01 * a22;\n out[2] = a01 * a12 - a02 * a11;\n out[3] = a12 * a20 - a10 * a22;\n out[4] = a00 * a22 - a02 * a20;\n out[5] = a02 * a10 - a00 * a12;\n out[6] = a10 * a21 - a11 * a20;\n out[7] = a01 * a20 - a00 * a21;\n out[8] = a00 * a11 - a01 * a10;\n return out;\n}\n/**\n * Calculates the determinant of a mat3\n *\n * @param {ReadonlyMat3} a the source matrix\n * @returns {Number} determinant of a\n */\n\nfunction determinant$1(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2];\n var a10 = a[3],\n a11 = a[4],\n a12 = a[5];\n var a20 = a[6],\n a21 = a[7],\n a22 = a[8];\n return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);\n}\n/**\n * Multiplies two mat3's\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the first operand\n * @param {ReadonlyMat3} b the second operand\n * @returns {mat3} out\n */\n\nfunction multiply$6(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2];\n var a10 = a[3],\n a11 = a[4],\n a12 = a[5];\n var a20 = a[6],\n a21 = a[7],\n a22 = a[8];\n var b00 = b[0],\n b01 = b[1],\n b02 = b[2];\n var b10 = b[3],\n b11 = b[4],\n b12 = b[5];\n var b20 = b[6],\n b21 = b[7],\n b22 = b[8];\n out[0] = b00 * a00 + b01 * a10 + b02 * a20;\n out[1] = b00 * a01 + b01 * a11 + b02 * a21;\n out[2] = b00 * a02 + b01 * a12 + b02 * a22;\n out[3] = b10 * a00 + b11 * a10 + b12 * a20;\n out[4] = b10 * a01 + b11 * a11 + b12 * a21;\n out[5] = b10 * a02 + b11 * a12 + b12 * a22;\n out[6] = b20 * a00 + b21 * a10 + b22 * a20;\n out[7] = b20 * a01 + b21 * a11 + b22 * a21;\n out[8] = b20 * a02 + b21 * a12 + b22 * a22;\n return out;\n}\n/**\n * Translate a mat3 by the given vector\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the matrix to translate\n * @param {ReadonlyVec2} v vector to translate by\n * @returns {mat3} out\n */\n\nfunction translate$2(out, a, v) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a10 = a[3],\n a11 = a[4],\n a12 = a[5],\n a20 = a[6],\n a21 = a[7],\n a22 = a[8],\n x = v[0],\n y = v[1];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a10;\n out[4] = a11;\n out[5] = a12;\n out[6] = x * a00 + y * a10 + a20;\n out[7] = x * a01 + y * a11 + a21;\n out[8] = x * a02 + y * a12 + a22;\n return out;\n}\n/**\n * Rotates a mat3 by the given angle\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat3} out\n */\n\nfunction rotate$2(out, a, rad) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a10 = a[3],\n a11 = a[4],\n a12 = a[5],\n a20 = a[6],\n a21 = a[7],\n a22 = a[8],\n s = Math.sin(rad),\n c = Math.cos(rad);\n out[0] = c * a00 + s * a10;\n out[1] = c * a01 + s * a11;\n out[2] = c * a02 + s * a12;\n out[3] = c * a10 - s * a00;\n out[4] = c * a11 - s * a01;\n out[5] = c * a12 - s * a02;\n out[6] = a20;\n out[7] = a21;\n out[8] = a22;\n return out;\n}\n/**\n * Scales the mat3 by the dimensions in the given vec2\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the matrix to rotate\n * @param {ReadonlyVec2} v the vec2 to scale the matrix by\n * @returns {mat3} out\n **/\n\nfunction scale$6(out, a, v) {\n var x = v[0],\n y = v[1];\n out[0] = x * a[0];\n out[1] = x * a[1];\n out[2] = x * a[2];\n out[3] = y * a[3];\n out[4] = y * a[4];\n out[5] = y * a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n return out;\n}\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat3.identity(dest);\n * mat3.translate(dest, dest, vec);\n *\n * @param {mat3} out mat3 receiving operation result\n * @param {ReadonlyVec2} v Translation vector\n * @returns {mat3} out\n */\n\nfunction fromTranslation$2(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 1;\n out[5] = 0;\n out[6] = v[0];\n out[7] = v[1];\n out[8] = 1;\n return out;\n}\n/**\n * Creates a matrix from a given angle\n * This is equivalent to (but much faster than):\n *\n * mat3.identity(dest);\n * mat3.rotate(dest, dest, rad);\n *\n * @param {mat3} out mat3 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat3} out\n */\n\nfunction fromRotation$2(out, rad) {\n var s = Math.sin(rad),\n c = Math.cos(rad);\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = -s;\n out[4] = c;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 1;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat3.identity(dest);\n * mat3.scale(dest, dest, vec);\n *\n * @param {mat3} out mat3 receiving operation result\n * @param {ReadonlyVec2} v Scaling vector\n * @returns {mat3} out\n */\n\nfunction fromScaling$1(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = v[1];\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 1;\n return out;\n}\n/**\n * Copies the values from a mat2d into a mat3\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat2d} a the matrix to copy\n * @returns {mat3} out\n **/\n\nfunction fromMat2d(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = 0;\n out[3] = a[2];\n out[4] = a[3];\n out[5] = 0;\n out[6] = a[4];\n out[7] = a[5];\n out[8] = 1;\n return out;\n}\n/**\n * Calculates a 3x3 matrix from the given quaternion\n *\n * @param {mat3} out mat3 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat3} out\n */\n\nfunction fromQuat$1(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[3] = yx - wz;\n out[6] = zx + wy;\n out[1] = yx + wz;\n out[4] = 1 - xx - zz;\n out[7] = zy - wx;\n out[2] = zx - wy;\n out[5] = zy + wx;\n out[8] = 1 - xx - yy;\n return out;\n}\n/**\n * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix\n *\n * @param {mat3} out mat3 receiving operation result\n * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from\n *\n * @returns {mat3} out\n */\n\nfunction normalFromMat4(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n return out;\n}\n/**\n * Generates a 2D projection matrix with the given bounds\n *\n * @param {mat3} out mat3 frustum matrix will be written into\n * @param {number} width Width of your gl context\n * @param {number} height Height of gl context\n * @returns {mat3} out\n */\n\nfunction projection(out, width, height) {\n out[0] = 2 / width;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = -2 / height;\n out[5] = 0;\n out[6] = -1;\n out[7] = 1;\n out[8] = 1;\n return out;\n}\n/**\n * Returns a string representation of a mat3\n *\n * @param {ReadonlyMat3} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nfunction str$6(a) {\n return \"mat3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat3\n *\n * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nfunction frob$1(a) {\n return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);\n}\n/**\n * Adds two mat3's\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the first operand\n * @param {ReadonlyMat3} b the second operand\n * @returns {mat3} out\n */\n\nfunction add$6(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the first operand\n * @param {ReadonlyMat3} b the second operand\n * @returns {mat3} out\n */\n\nfunction subtract$4(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n return out;\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat3} out the receiving matrix\n * @param {ReadonlyMat3} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat3} out\n */\n\nfunction multiplyScalar$1(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n return out;\n}\n/**\n * Adds two mat3's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat3} out the receiving vector\n * @param {ReadonlyMat3} a the first operand\n * @param {ReadonlyMat3} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat3} out\n */\n\nfunction multiplyScalarAndAdd$1(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat3} a The first matrix.\n * @param {ReadonlyMat3} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction exactEquals$6(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat3} a The first matrix.\n * @param {ReadonlyMat3} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction equals$6(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7],\n a8 = a[8];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3],\n b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7],\n b8 = b[8];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8));\n}\n/**\n * Alias for {@link mat3.multiply}\n * @function\n */\n\nvar mul$6 = multiply$6;\n/**\n * Alias for {@link mat3.subtract}\n * @function\n */\n\nvar sub$4 = subtract$4;\n\nvar mat3 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$6,\n fromMat4: fromMat4$1,\n clone: clone$6,\n copy: copy$6,\n fromValues: fromValues$6,\n set: set$6,\n identity: identity$3,\n transpose: transpose$1,\n invert: invert$3,\n adjoint: adjoint$1,\n determinant: determinant$1,\n multiply: multiply$6,\n translate: translate$2,\n rotate: rotate$2,\n scale: scale$6,\n fromTranslation: fromTranslation$2,\n fromRotation: fromRotation$2,\n fromScaling: fromScaling$1,\n fromMat2d: fromMat2d,\n fromQuat: fromQuat$1,\n normalFromMat4: normalFromMat4,\n projection: projection,\n str: str$6,\n frob: frob$1,\n add: add$6,\n subtract: subtract$4,\n multiplyScalar: multiplyScalar$1,\n multiplyScalarAndAdd: multiplyScalarAndAdd$1,\n exactEquals: exactEquals$6,\n equals: equals$6,\n mul: mul$6,\n sub: sub$4\n});\n\n/**\n * 4x4 Matrix Format: column-major, when typed out it looks like row-major The matrices are being post multiplied.\n * @module mat4\n */\n\n/**\n * Creates a new identity mat4\n *\n * @returns {mat4} a new 4x4 matrix\n */\n\nfunction create$5() {\n var out = new ARRAY_TYPE(16);\n\n if (ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n }\n\n out[0] = 1;\n out[5] = 1;\n out[10] = 1;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat4} a matrix to clone\n * @returns {mat4} a new 4x4 matrix\n */\n\nfunction clone$5(a) {\n var out = new ARRAY_TYPE(16);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Copy the values from one mat4 to another\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nfunction copy$5(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Create a new mat4 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} A new mat4\n */\n\nfunction fromValues$5(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n var out = new ARRAY_TYPE(16);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set the components of a mat4 to the given values\n *\n * @param {mat4} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} out\n */\n\nfunction set$5(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set a mat4 to the identity matrix\n *\n * @param {mat4} out the receiving matrix\n * @returns {mat4} out\n */\n\nfunction identity$2(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Transpose the values of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nfunction transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a12 = a[6],\n a13 = a[7];\n var a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n } else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Inverts a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nfunction invert$2(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n/**\n * Calculates the adjugate of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nfunction adjoint(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);\n out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));\n out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);\n out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));\n out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));\n out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);\n out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));\n out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);\n out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);\n out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));\n out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);\n out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));\n out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));\n out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);\n out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));\n out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);\n return out;\n}\n/**\n * Calculates the determinant of a mat4\n *\n * @param {ReadonlyMat4} a the source matrix\n * @returns {Number} determinant of a\n */\n\nfunction determinant(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n}\n/**\n * Multiplies two mat4s\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nfunction multiply$5(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15]; // Cache only the current line of the second matrix\n\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n}\n/**\n * Translate a mat4 by the given vector\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {mat4} out\n */\n\nfunction translate$1(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n } else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n\n return out;\n}\n/**\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\n * @returns {mat4} out\n **/\n\nfunction scale$5(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Rotates a mat4 by the given angle around the given axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nfunction rotate$1(out, a, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n var b00, b01, b02;\n var b10, b11, b12;\n var b20, b21, b22;\n\n if (len < EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11]; // Construct the elements of the rotation matrix\n\n b00 = x * x * t + c;\n b01 = y * x * t + z * s;\n b02 = z * x * t - y * s;\n b10 = x * y * t - z * s;\n b11 = y * y * t + c;\n b12 = z * y * t + x * s;\n b20 = x * z * t + y * s;\n b21 = y * z * t - x * s;\n b22 = z * z * t + c; // Perform rotation-specific matrix multiplication\n\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the X axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction rotateX$3(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[4] = a10 * c + a20 * s;\n out[5] = a11 * c + a21 * s;\n out[6] = a12 * c + a22 * s;\n out[7] = a13 * c + a23 * s;\n out[8] = a20 * c - a10 * s;\n out[9] = a21 * c - a11 * s;\n out[10] = a22 * c - a12 * s;\n out[11] = a23 * c - a13 * s;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Y axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction rotateY$3(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c - a20 * s;\n out[1] = a01 * c - a21 * s;\n out[2] = a02 * c - a22 * s;\n out[3] = a03 * c - a23 * s;\n out[8] = a00 * s + a20 * c;\n out[9] = a01 * s + a21 * c;\n out[10] = a02 * s + a22 * c;\n out[11] = a03 * s + a23 * c;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Z axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction rotateZ$3(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c + a10 * s;\n out[1] = a01 * c + a11 * s;\n out[2] = a02 * c + a12 * s;\n out[3] = a03 * c + a13 * s;\n out[4] = a10 * c - a00 * s;\n out[5] = a11 * c - a01 * s;\n out[6] = a12 * c - a02 * s;\n out[7] = a13 * c - a03 * s;\n return out;\n}\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nfunction fromTranslation$1(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.scale(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Scaling vector\n * @returns {mat4} out\n */\n\nfunction fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a given angle around a given axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotate(dest, dest, rad, axis);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nfunction fromRotation$1(out, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n\n if (len < EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c; // Perform rotation-specific matrix multiplication\n\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the X axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateX(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction fromXRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = c;\n out[6] = s;\n out[7] = 0;\n out[8] = 0;\n out[9] = -s;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Y axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateY(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction fromYRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = 0;\n out[2] = -s;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = s;\n out[9] = 0;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Z axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateZ(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nfunction fromZRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = 0;\n out[4] = -s;\n out[5] = c;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation and vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nfunction fromRotationTranslation$1(out, q, v) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - (yy + zz);\n out[1] = xy + wz;\n out[2] = xz - wy;\n out[3] = 0;\n out[4] = xy - wz;\n out[5] = 1 - (xx + zz);\n out[6] = yz + wx;\n out[7] = 0;\n out[8] = xz + wy;\n out[9] = yz - wx;\n out[10] = 1 - (xx + yy);\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 from a dual quat.\n *\n * @param {mat4} out Matrix\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @returns {mat4} mat4 receiving operation result\n */\n\nfunction fromQuat2(out, a) {\n var translation = new ARRAY_TYPE(3);\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense\n\n if (magnitude > 0) {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n } else {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n }\n\n fromRotationTranslation$1(out, a, translation);\n return out;\n}\n/**\n * Returns the translation vector component of a transformation\n * matrix. If a matrix is built with fromRotationTranslation,\n * the returned vector will be the same as the translation vector\n * originally supplied.\n * @param {vec3} out Vector to receive translation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nfunction getTranslation$1(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n}\n/**\n * Returns the scaling factor component of a transformation\n * matrix. If a matrix is built with fromRotationTranslationScale\n * with a normalized Quaternion paramter, the returned vector will be\n * the same as the scaling vector\n * originally supplied.\n * @param {vec3} out Vector to receive scaling factor component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nfunction getScaling(out, mat) {\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out[0] = Math.hypot(m11, m12, m13);\n out[1] = Math.hypot(m21, m22, m23);\n out[2] = Math.hypot(m31, m32, m33);\n return out;\n}\n/**\n * Returns a quaternion representing the rotational component\n * of a transformation matrix. If a matrix is built with\n * fromRotationTranslation, the returned quaternion will be the\n * same as the quaternion originally supplied.\n * @param {quat} out Quaternion to receive the rotation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {quat} out\n */\n\nfunction getRotation(out, mat) {\n var scaling = new ARRAY_TYPE(3);\n getScaling(scaling, mat);\n var is1 = 1 / scaling[0];\n var is2 = 1 / scaling[1];\n var is3 = 1 / scaling[2];\n var sm11 = mat[0] * is1;\n var sm12 = mat[1] * is2;\n var sm13 = mat[2] * is3;\n var sm21 = mat[4] * is1;\n var sm22 = mat[5] * is2;\n var sm23 = mat[6] * is3;\n var sm31 = mat[8] * is1;\n var sm32 = mat[9] * is2;\n var sm33 = mat[10] * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (sm23 - sm32) / S;\n out[1] = (sm31 - sm13) / S;\n out[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out[3] = (sm23 - sm32) / S;\n out[0] = 0.25 * S;\n out[1] = (sm12 + sm21) / S;\n out[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out[3] = (sm31 - sm13) / S;\n out[0] = (sm12 + sm21) / S;\n out[1] = 0.25 * S;\n out[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out[3] = (sm12 - sm21) / S;\n out[0] = (sm31 + sm13) / S;\n out[1] = (sm23 + sm32) / S;\n out[2] = 0.25 * S;\n }\n\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @returns {mat4} out\n */\n\nfunction fromRotationTranslationScale(out, q, v, s) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * mat4.translate(dest, origin);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n * mat4.translate(dest, negativeOrigin);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\n * @returns {mat4} out\n */\n\nfunction fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n var ox = o[0];\n var oy = o[1];\n var oz = o[2];\n var out0 = (1 - (yy + zz)) * sx;\n var out1 = (xy + wz) * sx;\n var out2 = (xz - wy) * sx;\n var out4 = (xy - wz) * sy;\n var out5 = (1 - (xx + zz)) * sy;\n var out6 = (yz + wx) * sy;\n var out8 = (xz + wy) * sz;\n var out9 = (yz - wx) * sz;\n var out10 = (1 - (xx + yy)) * sz;\n out[0] = out0;\n out[1] = out1;\n out[2] = out2;\n out[3] = 0;\n out[4] = out4;\n out[5] = out5;\n out[6] = out6;\n out[7] = 0;\n out[8] = out8;\n out[9] = out9;\n out[10] = out10;\n out[11] = 0;\n out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n out[15] = 1;\n return out;\n}\n/**\n * Calculates a 4x4 matrix from the given quaternion\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat4} out\n */\n\nfunction fromQuat(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a frustum matrix with the given bounds\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Number} left Left bound of the frustum\n * @param {Number} right Right bound of the frustum\n * @param {Number} bottom Bottom bound of the frustum\n * @param {Number} top Top bound of the frustum\n * @param {Number} near Near bound of the frustum\n * @param {Number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nfunction frustum(out, left, right, bottom, top, near, far) {\n var rl = 1 / (right - left);\n var tb = 1 / (top - bottom);\n var nf = 1 / (near - far);\n out[0] = near * 2 * rl;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = near * 2 * tb;\n out[6] = 0;\n out[7] = 0;\n out[8] = (right + left) * rl;\n out[9] = (top + bottom) * tb;\n out[10] = (far + near) * nf;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = far * near * 2 * nf;\n out[15] = 0;\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nfunction perspectiveNO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = (far + near) * nf;\n out[14] = 2 * far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -2 * near;\n }\n\n return out;\n}\n/**\n * Alias for {@link mat4.perspectiveNO}\n * @function\n */\n\nvar perspective = perspectiveNO;\n/**\n * Generates a perspective projection matrix suitable for WebGPU with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nfunction perspectiveZO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = far * nf;\n out[14] = far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -near;\n }\n\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given field of view.\n * This is primarily useful for generating projection matrices to be used\n * with the still experiemental WebVR API.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nfunction perspectiveFromFieldOfView(out, fov, near, far) {\n var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n var xScale = 2.0 / (leftTan + rightTan);\n var yScale = 2.0 / (upTan + downTan);\n out[0] = xScale;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n out[4] = 0.0;\n out[5] = yScale;\n out[6] = 0.0;\n out[7] = 0.0;\n out[8] = -((leftTan - rightTan) * xScale * 0.5);\n out[9] = (upTan - downTan) * yScale * 0.5;\n out[10] = far / (near - far);\n out[11] = -1.0;\n out[12] = 0.0;\n out[13] = 0.0;\n out[14] = far * near / (near - far);\n out[15] = 0.0;\n return out;\n}\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nfunction orthoNO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 2 * nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = (far + near) * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Alias for {@link mat4.orthoNO}\n * @function\n */\n\nvar ortho = orthoNO;\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nfunction orthoZO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = near * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nfunction lookAt(out, eye, center, up) {\n var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n var eyex = eye[0];\n var eyey = eye[1];\n var eyez = eye[2];\n var upx = up[0];\n var upy = up[1];\n var upz = up[2];\n var centerx = center[0];\n var centery = center[1];\n var centerz = center[2];\n\n if (Math.abs(eyex - centerx) < EPSILON && Math.abs(eyey - centery) < EPSILON && Math.abs(eyez - centerz) < EPSILON) {\n return identity$2(out);\n }\n\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.hypot(z0, z1, z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.hypot(x0, x1, x2);\n\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n } else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.hypot(y0, y1, y2);\n\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n } else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n}\n/**\n * Generates a matrix that makes something look at something else.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nfunction targetTo(out, eye, target, up) {\n var eyex = eye[0],\n eyey = eye[1],\n eyez = eye[2],\n upx = up[0],\n upy = up[1],\n upz = up[2];\n var z0 = eyex - target[0],\n z1 = eyey - target[1],\n z2 = eyez - target[2];\n var len = z0 * z0 + z1 * z1 + z2 * z2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n\n var x0 = upy * z2 - upz * z1,\n x1 = upz * z0 - upx * z2,\n x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n}\n/**\n * Returns a string representation of a mat4\n *\n * @param {ReadonlyMat4} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nfunction str$5(a) {\n return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat4\n *\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nfunction frob(a) {\n return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);\n}\n/**\n * Adds two mat4's\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nfunction add$5(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n out[9] = a[9] + b[9];\n out[10] = a[10] + b[10];\n out[11] = a[11] + b[11];\n out[12] = a[12] + b[12];\n out[13] = a[13] + b[13];\n out[14] = a[14] + b[14];\n out[15] = a[15] + b[15];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nfunction subtract$3(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n out[9] = a[9] - b[9];\n out[10] = a[10] - b[10];\n out[11] = a[11] - b[11];\n out[12] = a[12] - b[12];\n out[13] = a[13] - b[13];\n out[14] = a[14] - b[14];\n out[15] = a[15] - b[15];\n return out;\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat4} out\n */\n\nfunction multiplyScalar(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n out[9] = a[9] * b;\n out[10] = a[10] * b;\n out[11] = a[11] * b;\n out[12] = a[12] * b;\n out[13] = a[13] * b;\n out[14] = a[14] * b;\n out[15] = a[15] * b;\n return out;\n}\n/**\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat4} out the receiving vector\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat4} out\n */\n\nfunction multiplyScalarAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n out[9] = a[9] + b[9] * scale;\n out[10] = a[10] + b[10] * scale;\n out[11] = a[11] + b[11] * scale;\n out[12] = a[12] + b[12] * scale;\n out[13] = a[13] + b[13] * scale;\n out[14] = a[14] + b[14] * scale;\n out[15] = a[15] + b[15] * scale;\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction exactEquals$5(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nfunction equals$5(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var a8 = a[8],\n a9 = a[9],\n a10 = a[10],\n a11 = a[11];\n var a12 = a[12],\n a13 = a[13],\n a14 = a[14],\n a15 = a[15];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n var b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n var b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11];\n var b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n/**\n * Alias for {@link mat4.multiply}\n * @function\n */\n\nvar mul$5 = multiply$5;\n/**\n * Alias for {@link mat4.subtract}\n * @function\n */\n\nvar sub$3 = subtract$3;\n\nvar mat4 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$5,\n clone: clone$5,\n copy: copy$5,\n fromValues: fromValues$5,\n set: set$5,\n identity: identity$2,\n transpose: transpose,\n invert: invert$2,\n adjoint: adjoint,\n determinant: determinant,\n multiply: multiply$5,\n translate: translate$1,\n scale: scale$5,\n rotate: rotate$1,\n rotateX: rotateX$3,\n rotateY: rotateY$3,\n rotateZ: rotateZ$3,\n fromTranslation: fromTranslation$1,\n fromScaling: fromScaling,\n fromRotation: fromRotation$1,\n fromXRotation: fromXRotation,\n fromYRotation: fromYRotation,\n fromZRotation: fromZRotation,\n fromRotationTranslation: fromRotationTranslation$1,\n fromQuat2: fromQuat2,\n getTranslation: getTranslation$1,\n getScaling: getScaling,\n getRotation: getRotation,\n fromRotationTranslationScale: fromRotationTranslationScale,\n fromRotationTranslationScaleOrigin: fromRotationTranslationScaleOrigin,\n fromQuat: fromQuat,\n frustum: frustum,\n perspectiveNO: perspectiveNO,\n perspective: perspective,\n perspectiveZO: perspectiveZO,\n perspectiveFromFieldOfView: perspectiveFromFieldOfView,\n orthoNO: orthoNO,\n ortho: ortho,\n orthoZO: orthoZO,\n lookAt: lookAt,\n targetTo: targetTo,\n str: str$5,\n frob: frob,\n add: add$5,\n subtract: subtract$3,\n multiplyScalar: multiplyScalar,\n multiplyScalarAndAdd: multiplyScalarAndAdd,\n exactEquals: exactEquals$5,\n equals: equals$5,\n mul: mul$5,\n sub: sub$3\n});\n\n/**\n * 3 Dimensional Vector\n * @module vec3\n */\n\n/**\n * Creates a new, empty vec3\n *\n * @returns {vec3} a new 3D vector\n */\n\nfunction create$4() {\n var out = new ARRAY_TYPE(3);\n\n if (ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n\n return out;\n}\n/**\n * Creates a new vec3 initialized with values from an existing vector\n *\n * @param {ReadonlyVec3} a vector to clone\n * @returns {vec3} a new 3D vector\n */\n\nfunction clone$4(a) {\n var out = new ARRAY_TYPE(3);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Calculates the length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nfunction length$4(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Creates a new vec3 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} a new 3D vector\n */\n\nfunction fromValues$4(x, y, z) {\n var out = new ARRAY_TYPE(3);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Copy the values from one vec3 to another\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the source vector\n * @returns {vec3} out\n */\n\nfunction copy$4(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Set the components of a vec3 to the given values\n *\n * @param {vec3} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} out\n */\n\nfunction set$4(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Adds two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction add$4(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n}\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction subtract$2(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n}\n/**\n * Multiplies two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction multiply$4(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n}\n/**\n * Divides two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction divide$2(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n}\n/**\n * Math.ceil the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to ceil\n * @returns {vec3} out\n */\n\nfunction ceil$2(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n}\n/**\n * Math.floor the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to floor\n * @returns {vec3} out\n */\n\nfunction floor$2(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n}\n/**\n * Returns the minimum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction min$2(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n}\n/**\n * Returns the maximum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction max$2(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n}\n/**\n * Math.round the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to round\n * @returns {vec3} out\n */\n\nfunction round$2(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n return out;\n}\n/**\n * Scales a vec3 by a scalar number\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec3} out\n */\n\nfunction scale$4(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n}\n/**\n * Adds two vec3's after scaling the second operand by a scalar value\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec3} out\n */\n\nfunction scaleAndAdd$2(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n return out;\n}\n/**\n * Calculates the euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} distance between a and b\n */\n\nfunction distance$2(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Calculates the squared euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} squared distance between a and b\n */\n\nfunction squaredDistance$2(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Calculates the squared length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\n\nfunction squaredLength$4(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Negates the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to negate\n * @returns {vec3} out\n */\n\nfunction negate$2(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n}\n/**\n * Returns the inverse of the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to invert\n * @returns {vec3} out\n */\n\nfunction inverse$2(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n}\n/**\n * Normalize a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to normalize\n * @returns {vec3} out\n */\n\nfunction normalize$4(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var len = x * x + y * y + z * z;\n\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n return out;\n}\n/**\n * Calculates the dot product of two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} dot product of a and b\n */\n\nfunction dot$4(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n/**\n * Computes the cross product of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nfunction cross$2(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2];\n var bx = b[0],\n by = b[1],\n bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n}\n/**\n * Performs a linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nfunction lerp$4(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n}\n/**\n * Performs a hermite interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nfunction hermite(out, a, b, c, d, t) {\n var factorTimes2 = t * t;\n var factor1 = factorTimes2 * (2 * t - 3) + 1;\n var factor2 = factorTimes2 * (t - 2) + t;\n var factor3 = factorTimes2 * (t - 1);\n var factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Performs a bezier interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nfunction bezier(out, a, b, c, d, t) {\n var inverseFactor = 1 - t;\n var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n var factorTimes2 = t * t;\n var factor1 = inverseFactorTimesTwo * inverseFactor;\n var factor2 = 3 * t * inverseFactorTimesTwo;\n var factor3 = 3 * factorTimes2 * inverseFactor;\n var factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec3} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\n * @returns {vec3} out\n */\n\nfunction random$3(out, scale) {\n scale = scale || 1.0;\n var r = RANDOM() * 2.0 * Math.PI;\n var z = RANDOM() * 2.0 - 1.0;\n var zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n}\n/**\n * Transforms the vec3 with a mat4.\n * 4th vector component is implicitly '1'\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec3} out\n */\n\nfunction transformMat4$2(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n w = w || 1.0;\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return out;\n}\n/**\n * Transforms the vec3 with a mat3.\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\n * @returns {vec3} out\n */\n\nfunction transformMat3$1(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n}\n/**\n * Transforms the vec3 with a quat\n * Can also be used for dual quaternions. (Multiply it with the real part)\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyQuat} q quaternion to transform with\n * @returns {vec3} out\n */\n\nfunction transformQuat$1(out, a, q) {\n // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3];\n var x = a[0],\n y = a[1],\n z = a[2]; // var qvec = [qx, qy, qz];\n // var uv = vec3.cross([], qvec, a);\n\n var uvx = qy * z - qz * y,\n uvy = qz * x - qx * z,\n uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);\n\n var uuvx = qy * uvz - qz * uvy,\n uuvy = qz * uvx - qx * uvz,\n uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);\n\n var w2 = qw * 2;\n uvx *= w2;\n uvy *= w2;\n uvz *= w2; // vec3.scale(uuv, uuv, 2);\n\n uuvx *= 2;\n uuvy *= 2;\n uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));\n\n out[0] = x + uvx + uuvx;\n out[1] = y + uvy + uuvy;\n out[2] = z + uvz + uuvz;\n return out;\n}\n/**\n * Rotate a 3D vector around the x-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nfunction rotateX$2(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0];\n r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the y-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nfunction rotateY$2(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n r[1] = p[1];\n r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nfunction rotateZ$2(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n r[2] = p[2]; //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Get the angle between two 3D vectors\n * @param {ReadonlyVec3} a The first operand\n * @param {ReadonlyVec3} b The second operand\n * @returns {Number} The angle in radians\n */\n\nfunction angle$1(a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n bx = b[0],\n by = b[1],\n bz = b[2],\n mag1 = Math.sqrt(ax * ax + ay * ay + az * az),\n mag2 = Math.sqrt(bx * bx + by * by + bz * bz),\n mag = mag1 * mag2,\n cosine = mag && dot$4(a, b) / mag;\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n/**\n * Set the components of a vec3 to zero\n *\n * @param {vec3} out the receiving vector\n * @returns {vec3} out\n */\n\nfunction zero$2(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n return out;\n}\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec3} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nfunction str$4(a) {\n return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction exactEquals$4(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction equals$4(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n/**\n * Alias for {@link vec3.subtract}\n * @function\n */\n\nvar sub$2 = subtract$2;\n/**\n * Alias for {@link vec3.multiply}\n * @function\n */\n\nvar mul$4 = multiply$4;\n/**\n * Alias for {@link vec3.divide}\n * @function\n */\n\nvar div$2 = divide$2;\n/**\n * Alias for {@link vec3.distance}\n * @function\n */\n\nvar dist$2 = distance$2;\n/**\n * Alias for {@link vec3.squaredDistance}\n * @function\n */\n\nvar sqrDist$2 = squaredDistance$2;\n/**\n * Alias for {@link vec3.length}\n * @function\n */\n\nvar len$4 = length$4;\n/**\n * Alias for {@link vec3.squaredLength}\n * @function\n */\n\nvar sqrLen$4 = squaredLength$4;\n/**\n * Perform some operation over an array of vec3s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\n\nvar forEach$2 = function () {\n var vec = create$4();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n\n if (!stride) {\n stride = 3;\n }\n\n if (!offset) {\n offset = 0;\n }\n\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n }\n\n return a;\n };\n}();\n\nvar vec3 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$4,\n clone: clone$4,\n length: length$4,\n fromValues: fromValues$4,\n copy: copy$4,\n set: set$4,\n add: add$4,\n subtract: subtract$2,\n multiply: multiply$4,\n divide: divide$2,\n ceil: ceil$2,\n floor: floor$2,\n min: min$2,\n max: max$2,\n round: round$2,\n scale: scale$4,\n scaleAndAdd: scaleAndAdd$2,\n distance: distance$2,\n squaredDistance: squaredDistance$2,\n squaredLength: squaredLength$4,\n negate: negate$2,\n inverse: inverse$2,\n normalize: normalize$4,\n dot: dot$4,\n cross: cross$2,\n lerp: lerp$4,\n hermite: hermite,\n bezier: bezier,\n random: random$3,\n transformMat4: transformMat4$2,\n transformMat3: transformMat3$1,\n transformQuat: transformQuat$1,\n rotateX: rotateX$2,\n rotateY: rotateY$2,\n rotateZ: rotateZ$2,\n angle: angle$1,\n zero: zero$2,\n str: str$4,\n exactEquals: exactEquals$4,\n equals: equals$4,\n sub: sub$2,\n mul: mul$4,\n div: div$2,\n dist: dist$2,\n sqrDist: sqrDist$2,\n len: len$4,\n sqrLen: sqrLen$4,\n forEach: forEach$2\n});\n\n/**\n * 4 Dimensional Vector\n * @module vec4\n */\n\n/**\n * Creates a new, empty vec4\n *\n * @returns {vec4} a new 4D vector\n */\n\nfunction create$3() {\n var out = new ARRAY_TYPE(4);\n\n if (ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n }\n\n return out;\n}\n/**\n * Creates a new vec4 initialized with values from an existing vector\n *\n * @param {ReadonlyVec4} a vector to clone\n * @returns {vec4} a new 4D vector\n */\n\nfunction clone$3(a) {\n var out = new ARRAY_TYPE(4);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n}\n/**\n * Creates a new vec4 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @param {Number} w W component\n * @returns {vec4} a new 4D vector\n */\n\nfunction fromValues$3(x, y, z, w) {\n var out = new ARRAY_TYPE(4);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n}\n/**\n * Copy the values from one vec4 to another\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the source vector\n * @returns {vec4} out\n */\n\nfunction copy$3(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n}\n/**\n * Set the components of a vec4 to the given values\n *\n * @param {vec4} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @param {Number} w W component\n * @returns {vec4} out\n */\n\nfunction set$3(out, x, y, z, w) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n}\n/**\n * Adds two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction add$3(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n return out;\n}\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction subtract$1(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n return out;\n}\n/**\n * Multiplies two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction multiply$3(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n out[3] = a[3] * b[3];\n return out;\n}\n/**\n * Divides two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction divide$1(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n out[3] = a[3] / b[3];\n return out;\n}\n/**\n * Math.ceil the components of a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to ceil\n * @returns {vec4} out\n */\n\nfunction ceil$1(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n out[3] = Math.ceil(a[3]);\n return out;\n}\n/**\n * Math.floor the components of a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to floor\n * @returns {vec4} out\n */\n\nfunction floor$1(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n out[3] = Math.floor(a[3]);\n return out;\n}\n/**\n * Returns the minimum of two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction min$1(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n out[3] = Math.min(a[3], b[3]);\n return out;\n}\n/**\n * Returns the maximum of two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {vec4} out\n */\n\nfunction max$1(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n out[3] = Math.max(a[3], b[3]);\n return out;\n}\n/**\n * Math.round the components of a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to round\n * @returns {vec4} out\n */\n\nfunction round$1(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n out[3] = Math.round(a[3]);\n return out;\n}\n/**\n * Scales a vec4 by a scalar number\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec4} out\n */\n\nfunction scale$3(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n return out;\n}\n/**\n * Adds two vec4's after scaling the second operand by a scalar value\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec4} out\n */\n\nfunction scaleAndAdd$1(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n return out;\n}\n/**\n * Calculates the euclidian distance between two vec4's\n *\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {Number} distance between a and b\n */\n\nfunction distance$1(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n var w = b[3] - a[3];\n return Math.hypot(x, y, z, w);\n}\n/**\n * Calculates the squared euclidian distance between two vec4's\n *\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {Number} squared distance between a and b\n */\n\nfunction squaredDistance$1(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n var w = b[3] - a[3];\n return x * x + y * y + z * z + w * w;\n}\n/**\n * Calculates the length of a vec4\n *\n * @param {ReadonlyVec4} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nfunction length$3(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var w = a[3];\n return Math.hypot(x, y, z, w);\n}\n/**\n * Calculates the squared length of a vec4\n *\n * @param {ReadonlyVec4} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\n\nfunction squaredLength$3(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var w = a[3];\n return x * x + y * y + z * z + w * w;\n}\n/**\n * Negates the components of a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to negate\n * @returns {vec4} out\n */\n\nfunction negate$1(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = -a[3];\n return out;\n}\n/**\n * Returns the inverse of the components of a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to invert\n * @returns {vec4} out\n */\n\nfunction inverse$1(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n out[3] = 1.0 / a[3];\n return out;\n}\n/**\n * Normalize a vec4\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a vector to normalize\n * @returns {vec4} out\n */\n\nfunction normalize$3(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var w = a[3];\n var len = x * x + y * y + z * z + w * w;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n }\n\n out[0] = x * len;\n out[1] = y * len;\n out[2] = z * len;\n out[3] = w * len;\n return out;\n}\n/**\n * Calculates the dot product of two vec4's\n *\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @returns {Number} dot product of a and b\n */\n\nfunction dot$3(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n}\n/**\n * Returns the cross-product of three vectors in a 4-dimensional space\n *\n * @param {ReadonlyVec4} result the receiving vector\n * @param {ReadonlyVec4} U the first vector\n * @param {ReadonlyVec4} V the second vector\n * @param {ReadonlyVec4} W the third vector\n * @returns {vec4} result\n */\n\nfunction cross$1(out, u, v, w) {\n var A = v[0] * w[1] - v[1] * w[0],\n B = v[0] * w[2] - v[2] * w[0],\n C = v[0] * w[3] - v[3] * w[0],\n D = v[1] * w[2] - v[2] * w[1],\n E = v[1] * w[3] - v[3] * w[1],\n F = v[2] * w[3] - v[3] * w[2];\n var G = u[0];\n var H = u[1];\n var I = u[2];\n var J = u[3];\n out[0] = H * F - I * E + J * D;\n out[1] = -(G * F) + I * C - J * B;\n out[2] = G * E - H * C + J * A;\n out[3] = -(G * D) + H * B - I * A;\n return out;\n}\n/**\n * Performs a linear interpolation between two vec4's\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the first operand\n * @param {ReadonlyVec4} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec4} out\n */\n\nfunction lerp$3(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n var aw = a[3];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n out[3] = aw + t * (b[3] - aw);\n return out;\n}\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec4} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\n * @returns {vec4} out\n */\n\nfunction random$2(out, scale) {\n scale = scale || 1.0; // Marsaglia, George. Choosing a Point from the Surface of a\n // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.\n // http://projecteuclid.org/euclid.aoms/1177692644;\n\n var v1, v2, v3, v4;\n var s1, s2;\n\n do {\n v1 = RANDOM() * 2 - 1;\n v2 = RANDOM() * 2 - 1;\n s1 = v1 * v1 + v2 * v2;\n } while (s1 >= 1);\n\n do {\n v3 = RANDOM() * 2 - 1;\n v4 = RANDOM() * 2 - 1;\n s2 = v3 * v3 + v4 * v4;\n } while (s2 >= 1);\n\n var d = Math.sqrt((1 - s1) / s2);\n out[0] = scale * v1;\n out[1] = scale * v2;\n out[2] = scale * v3 * d;\n out[3] = scale * v4 * d;\n return out;\n}\n/**\n * Transforms the vec4 with a mat4.\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec4} out\n */\n\nfunction transformMat4$1(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2],\n w = a[3];\n out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;\n out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;\n out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;\n out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;\n return out;\n}\n/**\n * Transforms the vec4 with a quat\n *\n * @param {vec4} out the receiving vector\n * @param {ReadonlyVec4} a the vector to transform\n * @param {ReadonlyQuat} q quaternion to transform with\n * @returns {vec4} out\n */\n\nfunction transformQuat(out, a, q) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3]; // calculate quat * vec\n\n var ix = qw * x + qy * z - qz * y;\n var iy = qw * y + qz * x - qx * z;\n var iz = qw * z + qx * y - qy * x;\n var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat\n\n out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;\n out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;\n out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;\n out[3] = a[3];\n return out;\n}\n/**\n * Set the components of a vec4 to zero\n *\n * @param {vec4} out the receiving vector\n * @returns {vec4} out\n */\n\nfunction zero$1(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n return out;\n}\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec4} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nfunction str$3(a) {\n return \"vec4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \")\";\n}\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec4} a The first vector.\n * @param {ReadonlyVec4} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction exactEquals$3(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n}\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec4} a The first vector.\n * @param {ReadonlyVec4} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction equals$3(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));\n}\n/**\n * Alias for {@link vec4.subtract}\n * @function\n */\n\nvar sub$1 = subtract$1;\n/**\n * Alias for {@link vec4.multiply}\n * @function\n */\n\nvar mul$3 = multiply$3;\n/**\n * Alias for {@link vec4.divide}\n * @function\n */\n\nvar div$1 = divide$1;\n/**\n * Alias for {@link vec4.distance}\n * @function\n */\n\nvar dist$1 = distance$1;\n/**\n * Alias for {@link vec4.squaredDistance}\n * @function\n */\n\nvar sqrDist$1 = squaredDistance$1;\n/**\n * Alias for {@link vec4.length}\n * @function\n */\n\nvar len$3 = length$3;\n/**\n * Alias for {@link vec4.squaredLength}\n * @function\n */\n\nvar sqrLen$3 = squaredLength$3;\n/**\n * Perform some operation over an array of vec4s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\n\nvar forEach$1 = function () {\n var vec = create$3();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n\n if (!stride) {\n stride = 4;\n }\n\n if (!offset) {\n offset = 0;\n }\n\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n vec[3] = a[i + 3];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n a[i + 3] = vec[3];\n }\n\n return a;\n };\n}();\n\nvar vec4 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$3,\n clone: clone$3,\n fromValues: fromValues$3,\n copy: copy$3,\n set: set$3,\n add: add$3,\n subtract: subtract$1,\n multiply: multiply$3,\n divide: divide$1,\n ceil: ceil$1,\n floor: floor$1,\n min: min$1,\n max: max$1,\n round: round$1,\n scale: scale$3,\n scaleAndAdd: scaleAndAdd$1,\n distance: distance$1,\n squaredDistance: squaredDistance$1,\n length: length$3,\n squaredLength: squaredLength$3,\n negate: negate$1,\n inverse: inverse$1,\n normalize: normalize$3,\n dot: dot$3,\n cross: cross$1,\n lerp: lerp$3,\n random: random$2,\n transformMat4: transformMat4$1,\n transformQuat: transformQuat,\n zero: zero$1,\n str: str$3,\n exactEquals: exactEquals$3,\n equals: equals$3,\n sub: sub$1,\n mul: mul$3,\n div: div$1,\n dist: dist$1,\n sqrDist: sqrDist$1,\n len: len$3,\n sqrLen: sqrLen$3,\n forEach: forEach$1\n});\n\n/**\n * Quaternion\n * @module quat\n */\n\n/**\n * Creates a new identity quat\n *\n * @returns {quat} a new quaternion\n */\n\nfunction create$2() {\n var out = new ARRAY_TYPE(4);\n\n if (ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n\n out[3] = 1;\n return out;\n}\n/**\n * Set a quat to the identity quaternion\n *\n * @param {quat} out the receiving quaternion\n * @returns {quat} out\n */\n\nfunction identity$1(out) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n}\n/**\n * Sets a quat from the given angle and rotation axis,\n * then returns it.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyVec3} axis the axis around which to rotate\n * @param {Number} rad the angle in radians\n * @returns {quat} out\n **/\n\nfunction setAxisAngle(out, axis, rad) {\n rad = rad * 0.5;\n var s = Math.sin(rad);\n out[0] = s * axis[0];\n out[1] = s * axis[1];\n out[2] = s * axis[2];\n out[3] = Math.cos(rad);\n return out;\n}\n/**\n * Gets the rotation axis and angle for a given\n * quaternion. If a quaternion is created with\n * setAxisAngle, this method will return the same\n * values as providied in the original parameter list\n * OR functionally equivalent values.\n * Example: The quaternion formed by axis [0, 0, 1] and\n * angle -90 is the same as the quaternion formed by\n * [0, 0, 1] and 270. This method favors the latter.\n * @param {vec3} out_axis Vector receiving the axis of rotation\n * @param {ReadonlyQuat} q Quaternion to be decomposed\n * @return {Number} Angle, in radians, of the rotation\n */\n\nfunction getAxisAngle(out_axis, q) {\n var rad = Math.acos(q[3]) * 2.0;\n var s = Math.sin(rad / 2.0);\n\n if (s > EPSILON) {\n out_axis[0] = q[0] / s;\n out_axis[1] = q[1] / s;\n out_axis[2] = q[2] / s;\n } else {\n // If s is zero, return any axis (no rotation - axis does not matter)\n out_axis[0] = 1;\n out_axis[1] = 0;\n out_axis[2] = 0;\n }\n\n return rad;\n}\n/**\n * Gets the angular distance between two unit quaternions\n *\n * @param {ReadonlyQuat} a Origin unit quaternion\n * @param {ReadonlyQuat} b Destination unit quaternion\n * @return {Number} Angle, in radians, between the two quaternions\n */\n\nfunction getAngle(a, b) {\n var dotproduct = dot$2(a, b);\n return Math.acos(2 * dotproduct * dotproduct - 1);\n}\n/**\n * Multiplies two quat's\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @returns {quat} out\n */\n\nfunction multiply$2(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n var bx = b[0],\n by = b[1],\n bz = b[2],\n bw = b[3];\n out[0] = ax * bw + aw * bx + ay * bz - az * by;\n out[1] = ay * bw + aw * by + az * bx - ax * bz;\n out[2] = az * bw + aw * bz + ax * by - ay * bx;\n out[3] = aw * bw - ax * bx - ay * by - az * bz;\n return out;\n}\n/**\n * Rotates a quaternion by the given angle about the X axis\n *\n * @param {quat} out quat receiving operation result\n * @param {ReadonlyQuat} a quat to rotate\n * @param {number} rad angle (in radians) to rotate\n * @returns {quat} out\n */\n\nfunction rotateX$1(out, a, rad) {\n rad *= 0.5;\n var ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n var bx = Math.sin(rad),\n bw = Math.cos(rad);\n out[0] = ax * bw + aw * bx;\n out[1] = ay * bw + az * bx;\n out[2] = az * bw - ay * bx;\n out[3] = aw * bw - ax * bx;\n return out;\n}\n/**\n * Rotates a quaternion by the given angle about the Y axis\n *\n * @param {quat} out quat receiving operation result\n * @param {ReadonlyQuat} a quat to rotate\n * @param {number} rad angle (in radians) to rotate\n * @returns {quat} out\n */\n\nfunction rotateY$1(out, a, rad) {\n rad *= 0.5;\n var ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n var by = Math.sin(rad),\n bw = Math.cos(rad);\n out[0] = ax * bw - az * by;\n out[1] = ay * bw + aw * by;\n out[2] = az * bw + ax * by;\n out[3] = aw * bw - ay * by;\n return out;\n}\n/**\n * Rotates a quaternion by the given angle about the Z axis\n *\n * @param {quat} out quat receiving operation result\n * @param {ReadonlyQuat} a quat to rotate\n * @param {number} rad angle (in radians) to rotate\n * @returns {quat} out\n */\n\nfunction rotateZ$1(out, a, rad) {\n rad *= 0.5;\n var ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n var bz = Math.sin(rad),\n bw = Math.cos(rad);\n out[0] = ax * bw + ay * bz;\n out[1] = ay * bw - ax * bz;\n out[2] = az * bw + aw * bz;\n out[3] = aw * bw - az * bz;\n return out;\n}\n/**\n * Calculates the W component of a quat from the X, Y, and Z components.\n * Assumes that quaternion is 1 unit in length.\n * Any existing W component will be ignored.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate W component of\n * @returns {quat} out\n */\n\nfunction calculateW(out, a) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));\n return out;\n}\n/**\n * Calculate the exponential of a unit quaternion.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate the exponential of\n * @returns {quat} out\n */\n\nfunction exp(out, a) {\n var x = a[0],\n y = a[1],\n z = a[2],\n w = a[3];\n var r = Math.sqrt(x * x + y * y + z * z);\n var et = Math.exp(w);\n var s = r > 0 ? et * Math.sin(r) / r : 0;\n out[0] = x * s;\n out[1] = y * s;\n out[2] = z * s;\n out[3] = et * Math.cos(r);\n return out;\n}\n/**\n * Calculate the natural logarithm of a unit quaternion.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate the exponential of\n * @returns {quat} out\n */\n\nfunction ln(out, a) {\n var x = a[0],\n y = a[1],\n z = a[2],\n w = a[3];\n var r = Math.sqrt(x * x + y * y + z * z);\n var t = r > 0 ? Math.atan2(r, w) / r : 0;\n out[0] = x * t;\n out[1] = y * t;\n out[2] = z * t;\n out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);\n return out;\n}\n/**\n * Calculate the scalar power of a unit quaternion.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate the exponential of\n * @param {Number} b amount to scale the quaternion by\n * @returns {quat} out\n */\n\nfunction pow(out, a, b) {\n ln(out, a);\n scale$2(out, out, b);\n exp(out, out);\n return out;\n}\n/**\n * Performs a spherical linear interpolation between two quat\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {quat} out\n */\n\nfunction slerp(out, a, b, t) {\n // benchmarks:\n // http://jsperf.com/quaternion-slerp-implementations\n var ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n var bx = b[0],\n by = b[1],\n bz = b[2],\n bw = b[3];\n var omega, cosom, sinom, scale0, scale1; // calc cosine\n\n cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)\n\n if (cosom < 0.0) {\n cosom = -cosom;\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n } // calculate coefficients\n\n\n if (1.0 - cosom > EPSILON) {\n // standard case (slerp)\n omega = Math.acos(cosom);\n sinom = Math.sin(omega);\n scale0 = Math.sin((1.0 - t) * omega) / sinom;\n scale1 = Math.sin(t * omega) / sinom;\n } else {\n // \"from\" and \"to\" quaternions are very close\n // ... so we can do a linear interpolation\n scale0 = 1.0 - t;\n scale1 = t;\n } // calculate final values\n\n\n out[0] = scale0 * ax + scale1 * bx;\n out[1] = scale0 * ay + scale1 * by;\n out[2] = scale0 * az + scale1 * bz;\n out[3] = scale0 * aw + scale1 * bw;\n return out;\n}\n/**\n * Generates a random unit quaternion\n *\n * @param {quat} out the receiving quaternion\n * @returns {quat} out\n */\n\nfunction random$1(out) {\n // Implementation of http://planning.cs.uiuc.edu/node198.html\n // TODO: Calling random 3 times is probably not the fastest solution\n var u1 = RANDOM();\n var u2 = RANDOM();\n var u3 = RANDOM();\n var sqrt1MinusU1 = Math.sqrt(1 - u1);\n var sqrtU1 = Math.sqrt(u1);\n out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);\n out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);\n out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);\n out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);\n return out;\n}\n/**\n * Calculates the inverse of a quat\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate inverse of\n * @returns {quat} out\n */\n\nfunction invert$1(out, a) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;\n var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0\n\n out[0] = -a0 * invDot;\n out[1] = -a1 * invDot;\n out[2] = -a2 * invDot;\n out[3] = a3 * invDot;\n return out;\n}\n/**\n * Calculates the conjugate of a quat\n * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quat to calculate conjugate of\n * @returns {quat} out\n */\n\nfunction conjugate$1(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = a[3];\n return out;\n}\n/**\n * Creates a quaternion from the given 3x3 rotation matrix.\n *\n * NOTE: The resultant quaternion is not normalized, so you should be sure\n * to renormalize the quaternion yourself where necessary.\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyMat3} m rotation matrix\n * @returns {quat} out\n * @function\n */\n\nfunction fromMat3(out, m) {\n // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes\n // article \"Quaternion Calculus and Fast Animation\".\n var fTrace = m[0] + m[4] + m[8];\n var fRoot;\n\n if (fTrace > 0.0) {\n // |w| > 1/2, may as well choose w > 1/2\n fRoot = Math.sqrt(fTrace + 1.0); // 2w\n\n out[3] = 0.5 * fRoot;\n fRoot = 0.5 / fRoot; // 1/(4w)\n\n out[0] = (m[5] - m[7]) * fRoot;\n out[1] = (m[6] - m[2]) * fRoot;\n out[2] = (m[1] - m[3]) * fRoot;\n } else {\n // |w| <= 1/2\n var i = 0;\n if (m[4] > m[0]) i = 1;\n if (m[8] > m[i * 3 + i]) i = 2;\n var j = (i + 1) % 3;\n var k = (i + 2) % 3;\n fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);\n out[i] = 0.5 * fRoot;\n fRoot = 0.5 / fRoot;\n out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;\n out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;\n out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;\n }\n\n return out;\n}\n/**\n * Creates a quaternion from the given euler angle x, y, z.\n *\n * @param {quat} out the receiving quaternion\n * @param {x} Angle to rotate around X axis in degrees.\n * @param {y} Angle to rotate around Y axis in degrees.\n * @param {z} Angle to rotate around Z axis in degrees.\n * @returns {quat} out\n * @function\n */\n\nfunction fromEuler(out, x, y, z) {\n var halfToRad = 0.5 * Math.PI / 180.0;\n x *= halfToRad;\n y *= halfToRad;\n z *= halfToRad;\n var sx = Math.sin(x);\n var cx = Math.cos(x);\n var sy = Math.sin(y);\n var cy = Math.cos(y);\n var sz = Math.sin(z);\n var cz = Math.cos(z);\n out[0] = sx * cy * cz - cx * sy * sz;\n out[1] = cx * sy * cz + sx * cy * sz;\n out[2] = cx * cy * sz - sx * sy * cz;\n out[3] = cx * cy * cz + sx * sy * sz;\n return out;\n}\n/**\n * Returns a string representation of a quatenion\n *\n * @param {ReadonlyQuat} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nfunction str$2(a) {\n return \"quat(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \")\";\n}\n/**\n * Creates a new quat initialized with values from an existing quaternion\n *\n * @param {ReadonlyQuat} a quaternion to clone\n * @returns {quat} a new quaternion\n * @function\n */\n\nvar clone$2 = clone$3;\n/**\n * Creates a new quat initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @param {Number} w W component\n * @returns {quat} a new quaternion\n * @function\n */\n\nvar fromValues$2 = fromValues$3;\n/**\n * Copy the values from one quat to another\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the source quaternion\n * @returns {quat} out\n * @function\n */\n\nvar copy$2 = copy$3;\n/**\n * Set the components of a quat to the given values\n *\n * @param {quat} out the receiving quaternion\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @param {Number} w W component\n * @returns {quat} out\n * @function\n */\n\nvar set$2 = set$3;\n/**\n * Adds two quat's\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @returns {quat} out\n * @function\n */\n\nvar add$2 = add$3;\n/**\n * Alias for {@link quat.multiply}\n * @function\n */\n\nvar mul$2 = multiply$2;\n/**\n * Scales a quat by a scalar number\n *\n * @param {quat} out the receiving vector\n * @param {ReadonlyQuat} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {quat} out\n * @function\n */\n\nvar scale$2 = scale$3;\n/**\n * Calculates the dot product of two quat's\n *\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @returns {Number} dot product of a and b\n * @function\n */\n\nvar dot$2 = dot$3;\n/**\n * Performs a linear interpolation between two quat's\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {quat} out\n * @function\n */\n\nvar lerp$2 = lerp$3;\n/**\n * Calculates the length of a quat\n *\n * @param {ReadonlyQuat} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nvar length$2 = length$3;\n/**\n * Alias for {@link quat.length}\n * @function\n */\n\nvar len$2 = length$2;\n/**\n * Calculates the squared length of a quat\n *\n * @param {ReadonlyQuat} a vector to calculate squared length of\n * @returns {Number} squared length of a\n * @function\n */\n\nvar squaredLength$2 = squaredLength$3;\n/**\n * Alias for {@link quat.squaredLength}\n * @function\n */\n\nvar sqrLen$2 = squaredLength$2;\n/**\n * Normalize a quat\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a quaternion to normalize\n * @returns {quat} out\n * @function\n */\n\nvar normalize$2 = normalize$3;\n/**\n * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyQuat} a The first quaternion.\n * @param {ReadonlyQuat} b The second quaternion.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nvar exactEquals$2 = exactEquals$3;\n/**\n * Returns whether or not the quaternions have approximately the same elements in the same position.\n *\n * @param {ReadonlyQuat} a The first vector.\n * @param {ReadonlyQuat} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nvar equals$2 = equals$3;\n/**\n * Sets a quaternion to represent the shortest rotation from one\n * vector to another.\n *\n * Both vectors are assumed to be unit length.\n *\n * @param {quat} out the receiving quaternion.\n * @param {ReadonlyVec3} a the initial vector\n * @param {ReadonlyVec3} b the destination vector\n * @returns {quat} out\n */\n\nvar rotationTo = function () {\n var tmpvec3 = create$4();\n var xUnitVec3 = fromValues$4(1, 0, 0);\n var yUnitVec3 = fromValues$4(0, 1, 0);\n return function (out, a, b) {\n var dot = dot$4(a, b);\n\n if (dot < -0.999999) {\n cross$2(tmpvec3, xUnitVec3, a);\n if (len$4(tmpvec3) < 0.000001) cross$2(tmpvec3, yUnitVec3, a);\n normalize$4(tmpvec3, tmpvec3);\n setAxisAngle(out, tmpvec3, Math.PI);\n return out;\n } else if (dot > 0.999999) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n } else {\n cross$2(tmpvec3, a, b);\n out[0] = tmpvec3[0];\n out[1] = tmpvec3[1];\n out[2] = tmpvec3[2];\n out[3] = 1 + dot;\n return normalize$2(out, out);\n }\n };\n}();\n/**\n * Performs a spherical linear interpolation with two control points\n *\n * @param {quat} out the receiving quaternion\n * @param {ReadonlyQuat} a the first operand\n * @param {ReadonlyQuat} b the second operand\n * @param {ReadonlyQuat} c the third operand\n * @param {ReadonlyQuat} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {quat} out\n */\n\nvar sqlerp = function () {\n var temp1 = create$2();\n var temp2 = create$2();\n return function (out, a, b, c, d, t) {\n slerp(temp1, a, d, t);\n slerp(temp2, b, c, t);\n slerp(out, temp1, temp2, 2 * t * (1 - t));\n return out;\n };\n}();\n/**\n * Sets the specified quaternion with values corresponding to the given\n * axes. Each axis is a vec3 and is expected to be unit length and\n * perpendicular to all other specified axes.\n *\n * @param {ReadonlyVec3} view the vector representing the viewing direction\n * @param {ReadonlyVec3} right the vector representing the local \"right\" direction\n * @param {ReadonlyVec3} up the vector representing the local \"up\" direction\n * @returns {quat} out\n */\n\nvar setAxes = function () {\n var matr = create$6();\n return function (out, view, right, up) {\n matr[0] = right[0];\n matr[3] = right[1];\n matr[6] = right[2];\n matr[1] = up[0];\n matr[4] = up[1];\n matr[7] = up[2];\n matr[2] = -view[0];\n matr[5] = -view[1];\n matr[8] = -view[2];\n return normalize$2(out, fromMat3(out, matr));\n };\n}();\n\nvar quat = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$2,\n identity: identity$1,\n setAxisAngle: setAxisAngle,\n getAxisAngle: getAxisAngle,\n getAngle: getAngle,\n multiply: multiply$2,\n rotateX: rotateX$1,\n rotateY: rotateY$1,\n rotateZ: rotateZ$1,\n calculateW: calculateW,\n exp: exp,\n ln: ln,\n pow: pow,\n slerp: slerp,\n random: random$1,\n invert: invert$1,\n conjugate: conjugate$1,\n fromMat3: fromMat3,\n fromEuler: fromEuler,\n str: str$2,\n clone: clone$2,\n fromValues: fromValues$2,\n copy: copy$2,\n set: set$2,\n add: add$2,\n mul: mul$2,\n scale: scale$2,\n dot: dot$2,\n lerp: lerp$2,\n length: length$2,\n len: len$2,\n squaredLength: squaredLength$2,\n sqrLen: sqrLen$2,\n normalize: normalize$2,\n exactEquals: exactEquals$2,\n equals: equals$2,\n rotationTo: rotationTo,\n sqlerp: sqlerp,\n setAxes: setAxes\n});\n\n/**\n * Dual Quaternion \n * Format: [real, dual] \n * Quaternion format: XYZW \n * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended. \n * @module quat2\n */\n\n/**\n * Creates a new identity dual quat\n *\n * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]\n */\n\nfunction create$1() {\n var dq = new ARRAY_TYPE(8);\n\n if (ARRAY_TYPE != Float32Array) {\n dq[0] = 0;\n dq[1] = 0;\n dq[2] = 0;\n dq[4] = 0;\n dq[5] = 0;\n dq[6] = 0;\n dq[7] = 0;\n }\n\n dq[3] = 1;\n return dq;\n}\n/**\n * Creates a new quat initialized with values from an existing quaternion\n *\n * @param {ReadonlyQuat2} a dual quaternion to clone\n * @returns {quat2} new dual quaternion\n * @function\n */\n\nfunction clone$1(a) {\n var dq = new ARRAY_TYPE(8);\n dq[0] = a[0];\n dq[1] = a[1];\n dq[2] = a[2];\n dq[3] = a[3];\n dq[4] = a[4];\n dq[5] = a[5];\n dq[6] = a[6];\n dq[7] = a[7];\n return dq;\n}\n/**\n * Creates a new dual quat initialized with the given values\n *\n * @param {Number} x1 X component\n * @param {Number} y1 Y component\n * @param {Number} z1 Z component\n * @param {Number} w1 W component\n * @param {Number} x2 X component\n * @param {Number} y2 Y component\n * @param {Number} z2 Z component\n * @param {Number} w2 W component\n * @returns {quat2} new dual quaternion\n * @function\n */\n\nfunction fromValues$1(x1, y1, z1, w1, x2, y2, z2, w2) {\n var dq = new ARRAY_TYPE(8);\n dq[0] = x1;\n dq[1] = y1;\n dq[2] = z1;\n dq[3] = w1;\n dq[4] = x2;\n dq[5] = y2;\n dq[6] = z2;\n dq[7] = w2;\n return dq;\n}\n/**\n * Creates a new dual quat from the given values (quat and translation)\n *\n * @param {Number} x1 X component\n * @param {Number} y1 Y component\n * @param {Number} z1 Z component\n * @param {Number} w1 W component\n * @param {Number} x2 X component (translation)\n * @param {Number} y2 Y component (translation)\n * @param {Number} z2 Z component (translation)\n * @returns {quat2} new dual quaternion\n * @function\n */\n\nfunction fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {\n var dq = new ARRAY_TYPE(8);\n dq[0] = x1;\n dq[1] = y1;\n dq[2] = z1;\n dq[3] = w1;\n var ax = x2 * 0.5,\n ay = y2 * 0.5,\n az = z2 * 0.5;\n dq[4] = ax * w1 + ay * z1 - az * y1;\n dq[5] = ay * w1 + az * x1 - ax * z1;\n dq[6] = az * w1 + ax * y1 - ay * x1;\n dq[7] = -ax * x1 - ay * y1 - az * z1;\n return dq;\n}\n/**\n * Creates a dual quat from a quaternion and a translation\n *\n * @param {ReadonlyQuat2} dual quaternion receiving operation result\n * @param {ReadonlyQuat} q a normalized quaternion\n * @param {ReadonlyVec3} t tranlation vector\n * @returns {quat2} dual quaternion receiving operation result\n * @function\n */\n\nfunction fromRotationTranslation(out, q, t) {\n var ax = t[0] * 0.5,\n ay = t[1] * 0.5,\n az = t[2] * 0.5,\n bx = q[0],\n by = q[1],\n bz = q[2],\n bw = q[3];\n out[0] = bx;\n out[1] = by;\n out[2] = bz;\n out[3] = bw;\n out[4] = ax * bw + ay * bz - az * by;\n out[5] = ay * bw + az * bx - ax * bz;\n out[6] = az * bw + ax * by - ay * bx;\n out[7] = -ax * bx - ay * by - az * bz;\n return out;\n}\n/**\n * Creates a dual quat from a translation\n *\n * @param {ReadonlyQuat2} dual quaternion receiving operation result\n * @param {ReadonlyVec3} t translation vector\n * @returns {quat2} dual quaternion receiving operation result\n * @function\n */\n\nfunction fromTranslation(out, t) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = t[0] * 0.5;\n out[5] = t[1] * 0.5;\n out[6] = t[2] * 0.5;\n out[7] = 0;\n return out;\n}\n/**\n * Creates a dual quat from a quaternion\n *\n * @param {ReadonlyQuat2} dual quaternion receiving operation result\n * @param {ReadonlyQuat} q the quaternion\n * @returns {quat2} dual quaternion receiving operation result\n * @function\n */\n\nfunction fromRotation(out, q) {\n out[0] = q[0];\n out[1] = q[1];\n out[2] = q[2];\n out[3] = q[3];\n out[4] = 0;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n return out;\n}\n/**\n * Creates a new dual quat from a matrix (4x4)\n *\n * @param {quat2} out the dual quaternion\n * @param {ReadonlyMat4} a the matrix\n * @returns {quat2} dual quat receiving operation result\n * @function\n */\n\nfunction fromMat4(out, a) {\n //TODO Optimize this\n var outer = create$2();\n getRotation(outer, a);\n var t = new ARRAY_TYPE(3);\n getTranslation$1(t, a);\n fromRotationTranslation(out, outer, t);\n return out;\n}\n/**\n * Copy the values from one dual quat to another\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the source dual quaternion\n * @returns {quat2} out\n * @function\n */\n\nfunction copy$1(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n return out;\n}\n/**\n * Set a dual quat to the identity dual quaternion\n *\n * @param {quat2} out the receiving quaternion\n * @returns {quat2} out\n */\n\nfunction identity(out) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = 0;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n return out;\n}\n/**\n * Set the components of a dual quat to the given values\n *\n * @param {quat2} out the receiving quaternion\n * @param {Number} x1 X component\n * @param {Number} y1 Y component\n * @param {Number} z1 Z component\n * @param {Number} w1 W component\n * @param {Number} x2 X component\n * @param {Number} y2 Y component\n * @param {Number} z2 Z component\n * @param {Number} w2 W component\n * @returns {quat2} out\n * @function\n */\n\nfunction set$1(out, x1, y1, z1, w1, x2, y2, z2, w2) {\n out[0] = x1;\n out[1] = y1;\n out[2] = z1;\n out[3] = w1;\n out[4] = x2;\n out[5] = y2;\n out[6] = z2;\n out[7] = w2;\n return out;\n}\n/**\n * Gets the real part of a dual quat\n * @param {quat} out real part\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @return {quat} real part\n */\n\nvar getReal = copy$2;\n/**\n * Gets the dual part of a dual quat\n * @param {quat} out dual part\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @return {quat} dual part\n */\n\nfunction getDual(out, a) {\n out[0] = a[4];\n out[1] = a[5];\n out[2] = a[6];\n out[3] = a[7];\n return out;\n}\n/**\n * Set the real component of a dual quat to the given quaternion\n *\n * @param {quat2} out the receiving quaternion\n * @param {ReadonlyQuat} q a quaternion representing the real part\n * @returns {quat2} out\n * @function\n */\n\nvar setReal = copy$2;\n/**\n * Set the dual component of a dual quat to the given quaternion\n *\n * @param {quat2} out the receiving quaternion\n * @param {ReadonlyQuat} q a quaternion representing the dual part\n * @returns {quat2} out\n * @function\n */\n\nfunction setDual(out, q) {\n out[4] = q[0];\n out[5] = q[1];\n out[6] = q[2];\n out[7] = q[3];\n return out;\n}\n/**\n * Gets the translation of a normalized dual quat\n * @param {vec3} out translation\n * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed\n * @return {vec3} translation\n */\n\nfunction getTranslation(out, a) {\n var ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7],\n bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3];\n out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n return out;\n}\n/**\n * Translates a dual quat by the given vector\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {quat2} out\n */\n\nfunction translate(out, a, v) {\n var ax1 = a[0],\n ay1 = a[1],\n az1 = a[2],\n aw1 = a[3],\n bx1 = v[0] * 0.5,\n by1 = v[1] * 0.5,\n bz1 = v[2] * 0.5,\n ax2 = a[4],\n ay2 = a[5],\n az2 = a[6],\n aw2 = a[7];\n out[0] = ax1;\n out[1] = ay1;\n out[2] = az1;\n out[3] = aw1;\n out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;\n out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;\n out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;\n out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;\n return out;\n}\n/**\n * Rotates a dual quat around the X axis\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @param {number} rad how far should the rotation be\n * @returns {quat2} out\n */\n\nfunction rotateX(out, a, rad) {\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7],\n ax1 = ax * bw + aw * bx + ay * bz - az * by,\n ay1 = ay * bw + aw * by + az * bx - ax * bz,\n az1 = az * bw + aw * bz + ax * by - ay * bx,\n aw1 = aw * bw - ax * bx - ay * by - az * bz;\n rotateX$1(out, a, rad);\n bx = out[0];\n by = out[1];\n bz = out[2];\n bw = out[3];\n out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\n out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\n out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\n out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\n return out;\n}\n/**\n * Rotates a dual quat around the Y axis\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @param {number} rad how far should the rotation be\n * @returns {quat2} out\n */\n\nfunction rotateY(out, a, rad) {\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7],\n ax1 = ax * bw + aw * bx + ay * bz - az * by,\n ay1 = ay * bw + aw * by + az * bx - ax * bz,\n az1 = az * bw + aw * bz + ax * by - ay * bx,\n aw1 = aw * bw - ax * bx - ay * by - az * bz;\n rotateY$1(out, a, rad);\n bx = out[0];\n by = out[1];\n bz = out[2];\n bw = out[3];\n out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\n out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\n out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\n out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\n return out;\n}\n/**\n * Rotates a dual quat around the Z axis\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @param {number} rad how far should the rotation be\n * @returns {quat2} out\n */\n\nfunction rotateZ(out, a, rad) {\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7],\n ax1 = ax * bw + aw * bx + ay * bz - az * by,\n ay1 = ay * bw + aw * by + az * bx - ax * bz,\n az1 = az * bw + aw * bz + ax * by - ay * bx,\n aw1 = aw * bw - ax * bx - ay * by - az * bz;\n rotateZ$1(out, a, rad);\n bx = out[0];\n by = out[1];\n bz = out[2];\n bw = out[3];\n out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\n out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\n out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\n out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\n return out;\n}\n/**\n * Rotates a dual quat by a given quaternion (a * q)\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @param {ReadonlyQuat} q quaternion to rotate by\n * @returns {quat2} out\n */\n\nfunction rotateByQuatAppend(out, a, q) {\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3],\n ax = a[0],\n ay = a[1],\n az = a[2],\n aw = a[3];\n out[0] = ax * qw + aw * qx + ay * qz - az * qy;\n out[1] = ay * qw + aw * qy + az * qx - ax * qz;\n out[2] = az * qw + aw * qz + ax * qy - ay * qx;\n out[3] = aw * qw - ax * qx - ay * qy - az * qz;\n ax = a[4];\n ay = a[5];\n az = a[6];\n aw = a[7];\n out[4] = ax * qw + aw * qx + ay * qz - az * qy;\n out[5] = ay * qw + aw * qy + az * qx - ax * qz;\n out[6] = az * qw + aw * qz + ax * qy - ay * qx;\n out[7] = aw * qw - ax * qx - ay * qy - az * qz;\n return out;\n}\n/**\n * Rotates a dual quat by a given quaternion (q * a)\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat} q quaternion to rotate by\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @returns {quat2} out\n */\n\nfunction rotateByQuatPrepend(out, q, a) {\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3],\n bx = a[0],\n by = a[1],\n bz = a[2],\n bw = a[3];\n out[0] = qx * bw + qw * bx + qy * bz - qz * by;\n out[1] = qy * bw + qw * by + qz * bx - qx * bz;\n out[2] = qz * bw + qw * bz + qx * by - qy * bx;\n out[3] = qw * bw - qx * bx - qy * by - qz * bz;\n bx = a[4];\n by = a[5];\n bz = a[6];\n bw = a[7];\n out[4] = qx * bw + qw * bx + qy * bz - qz * by;\n out[5] = qy * bw + qw * by + qz * bx - qx * bz;\n out[6] = qz * bw + qw * bz + qx * by - qy * bx;\n out[7] = qw * bw - qx * bx - qy * by - qz * bz;\n return out;\n}\n/**\n * Rotates a dual quat around a given axis. Does the normalisation automatically\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the dual quaternion to rotate\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @param {Number} rad how far the rotation should be\n * @returns {quat2} out\n */\n\nfunction rotateAroundAxis(out, a, axis, rad) {\n //Special case for rad = 0\n if (Math.abs(rad) < EPSILON) {\n return copy$1(out, a);\n }\n\n var axisLength = Math.hypot(axis[0], axis[1], axis[2]);\n rad = rad * 0.5;\n var s = Math.sin(rad);\n var bx = s * axis[0] / axisLength;\n var by = s * axis[1] / axisLength;\n var bz = s * axis[2] / axisLength;\n var bw = Math.cos(rad);\n var ax1 = a[0],\n ay1 = a[1],\n az1 = a[2],\n aw1 = a[3];\n out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\n out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\n out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\n out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\n var ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n out[4] = ax * bw + aw * bx + ay * bz - az * by;\n out[5] = ay * bw + aw * by + az * bx - ax * bz;\n out[6] = az * bw + aw * bz + ax * by - ay * bx;\n out[7] = aw * bw - ax * bx - ay * by - az * bz;\n return out;\n}\n/**\n * Adds two dual quat's\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the first operand\n * @param {ReadonlyQuat2} b the second operand\n * @returns {quat2} out\n * @function\n */\n\nfunction add$1(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n return out;\n}\n/**\n * Multiplies two dual quat's\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a the first operand\n * @param {ReadonlyQuat2} b the second operand\n * @returns {quat2} out\n */\n\nfunction multiply$1(out, a, b) {\n var ax0 = a[0],\n ay0 = a[1],\n az0 = a[2],\n aw0 = a[3],\n bx1 = b[4],\n by1 = b[5],\n bz1 = b[6],\n bw1 = b[7],\n ax1 = a[4],\n ay1 = a[5],\n az1 = a[6],\n aw1 = a[7],\n bx0 = b[0],\n by0 = b[1],\n bz0 = b[2],\n bw0 = b[3];\n out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;\n out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;\n out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;\n out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;\n out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;\n out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;\n out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;\n out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;\n return out;\n}\n/**\n * Alias for {@link quat2.multiply}\n * @function\n */\n\nvar mul$1 = multiply$1;\n/**\n * Scales a dual quat by a scalar number\n *\n * @param {quat2} out the receiving dual quat\n * @param {ReadonlyQuat2} a the dual quat to scale\n * @param {Number} b amount to scale the dual quat by\n * @returns {quat2} out\n * @function\n */\n\nfunction scale$1(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n return out;\n}\n/**\n * Calculates the dot product of two dual quat's (The dot product of the real parts)\n *\n * @param {ReadonlyQuat2} a the first operand\n * @param {ReadonlyQuat2} b the second operand\n * @returns {Number} dot product of a and b\n * @function\n */\n\nvar dot$1 = dot$2;\n/**\n * Performs a linear interpolation between two dual quats's\n * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)\n *\n * @param {quat2} out the receiving dual quat\n * @param {ReadonlyQuat2} a the first operand\n * @param {ReadonlyQuat2} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {quat2} out\n */\n\nfunction lerp$1(out, a, b, t) {\n var mt = 1 - t;\n if (dot$1(a, b) < 0) t = -t;\n out[0] = a[0] * mt + b[0] * t;\n out[1] = a[1] * mt + b[1] * t;\n out[2] = a[2] * mt + b[2] * t;\n out[3] = a[3] * mt + b[3] * t;\n out[4] = a[4] * mt + b[4] * t;\n out[5] = a[5] * mt + b[5] * t;\n out[6] = a[6] * mt + b[6] * t;\n out[7] = a[7] * mt + b[7] * t;\n return out;\n}\n/**\n * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a dual quat to calculate inverse of\n * @returns {quat2} out\n */\n\nfunction invert(out, a) {\n var sqlen = squaredLength$1(a);\n out[0] = -a[0] / sqlen;\n out[1] = -a[1] / sqlen;\n out[2] = -a[2] / sqlen;\n out[3] = a[3] / sqlen;\n out[4] = -a[4] / sqlen;\n out[5] = -a[5] / sqlen;\n out[6] = -a[6] / sqlen;\n out[7] = a[7] / sqlen;\n return out;\n}\n/**\n * Calculates the conjugate of a dual quat\n * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.\n *\n * @param {quat2} out the receiving quaternion\n * @param {ReadonlyQuat2} a quat to calculate conjugate of\n * @returns {quat2} out\n */\n\nfunction conjugate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = a[3];\n out[4] = -a[4];\n out[5] = -a[5];\n out[6] = -a[6];\n out[7] = a[7];\n return out;\n}\n/**\n * Calculates the length of a dual quat\n *\n * @param {ReadonlyQuat2} a dual quat to calculate length of\n * @returns {Number} length of a\n * @function\n */\n\nvar length$1 = length$2;\n/**\n * Alias for {@link quat2.length}\n * @function\n */\n\nvar len$1 = length$1;\n/**\n * Calculates the squared length of a dual quat\n *\n * @param {ReadonlyQuat2} a dual quat to calculate squared length of\n * @returns {Number} squared length of a\n * @function\n */\n\nvar squaredLength$1 = squaredLength$2;\n/**\n * Alias for {@link quat2.squaredLength}\n * @function\n */\n\nvar sqrLen$1 = squaredLength$1;\n/**\n * Normalize a dual quat\n *\n * @param {quat2} out the receiving dual quaternion\n * @param {ReadonlyQuat2} a dual quaternion to normalize\n * @returns {quat2} out\n * @function\n */\n\nfunction normalize$1(out, a) {\n var magnitude = squaredLength$1(a);\n\n if (magnitude > 0) {\n magnitude = Math.sqrt(magnitude);\n var a0 = a[0] / magnitude;\n var a1 = a[1] / magnitude;\n var a2 = a[2] / magnitude;\n var a3 = a[3] / magnitude;\n var b0 = a[4];\n var b1 = a[5];\n var b2 = a[6];\n var b3 = a[7];\n var a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;\n out[0] = a0;\n out[1] = a1;\n out[2] = a2;\n out[3] = a3;\n out[4] = (b0 - a0 * a_dot_b) / magnitude;\n out[5] = (b1 - a1 * a_dot_b) / magnitude;\n out[6] = (b2 - a2 * a_dot_b) / magnitude;\n out[7] = (b3 - a3 * a_dot_b) / magnitude;\n }\n\n return out;\n}\n/**\n * Returns a string representation of a dual quatenion\n *\n * @param {ReadonlyQuat2} a dual quaternion to represent as a string\n * @returns {String} string representation of the dual quat\n */\n\nfunction str$1(a) {\n return \"quat2(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \")\";\n}\n/**\n * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyQuat2} a the first dual quaternion.\n * @param {ReadonlyQuat2} b the second dual quaternion.\n * @returns {Boolean} true if the dual quaternions are equal, false otherwise.\n */\n\nfunction exactEquals$1(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7];\n}\n/**\n * Returns whether or not the dual quaternions have approximately the same elements in the same position.\n *\n * @param {ReadonlyQuat2} a the first dual quat.\n * @param {ReadonlyQuat2} b the second dual quat.\n * @returns {Boolean} true if the dual quats are equal, false otherwise.\n */\n\nfunction equals$1(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3],\n a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3],\n b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7));\n}\n\nvar quat2 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create$1,\n clone: clone$1,\n fromValues: fromValues$1,\n fromRotationTranslationValues: fromRotationTranslationValues,\n fromRotationTranslation: fromRotationTranslation,\n fromTranslation: fromTranslation,\n fromRotation: fromRotation,\n fromMat4: fromMat4,\n copy: copy$1,\n identity: identity,\n set: set$1,\n getReal: getReal,\n getDual: getDual,\n setReal: setReal,\n setDual: setDual,\n getTranslation: getTranslation,\n translate: translate,\n rotateX: rotateX,\n rotateY: rotateY,\n rotateZ: rotateZ,\n rotateByQuatAppend: rotateByQuatAppend,\n rotateByQuatPrepend: rotateByQuatPrepend,\n rotateAroundAxis: rotateAroundAxis,\n add: add$1,\n multiply: multiply$1,\n mul: mul$1,\n scale: scale$1,\n dot: dot$1,\n lerp: lerp$1,\n invert: invert,\n conjugate: conjugate,\n length: length$1,\n len: len$1,\n squaredLength: squaredLength$1,\n sqrLen: sqrLen$1,\n normalize: normalize$1,\n str: str$1,\n exactEquals: exactEquals$1,\n equals: equals$1\n});\n\n/**\n * 2 Dimensional Vector\n * @module vec2\n */\n\n/**\n * Creates a new, empty vec2\n *\n * @returns {vec2} a new 2D vector\n */\n\nfunction create() {\n var out = new ARRAY_TYPE(2);\n\n if (ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n }\n\n return out;\n}\n/**\n * Creates a new vec2 initialized with values from an existing vector\n *\n * @param {ReadonlyVec2} a vector to clone\n * @returns {vec2} a new 2D vector\n */\n\nfunction clone(a) {\n var out = new ARRAY_TYPE(2);\n out[0] = a[0];\n out[1] = a[1];\n return out;\n}\n/**\n * Creates a new vec2 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @returns {vec2} a new 2D vector\n */\n\nfunction fromValues(x, y) {\n var out = new ARRAY_TYPE(2);\n out[0] = x;\n out[1] = y;\n return out;\n}\n/**\n * Copy the values from one vec2 to another\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the source vector\n * @returns {vec2} out\n */\n\nfunction copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n return out;\n}\n/**\n * Set the components of a vec2 to the given values\n *\n * @param {vec2} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @returns {vec2} out\n */\n\nfunction set(out, x, y) {\n out[0] = x;\n out[1] = y;\n return out;\n}\n/**\n * Adds two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n return out;\n}\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n return out;\n}\n/**\n * Multiplies two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction multiply(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n return out;\n}\n/**\n * Divides two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction divide(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n return out;\n}\n/**\n * Math.ceil the components of a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to ceil\n * @returns {vec2} out\n */\n\nfunction ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n return out;\n}\n/**\n * Math.floor the components of a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to floor\n * @returns {vec2} out\n */\n\nfunction floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n return out;\n}\n/**\n * Returns the minimum of two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n return out;\n}\n/**\n * Returns the maximum of two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec2} out\n */\n\nfunction max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n return out;\n}\n/**\n * Math.round the components of a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to round\n * @returns {vec2} out\n */\n\nfunction round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n return out;\n}\n/**\n * Scales a vec2 by a scalar number\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec2} out\n */\n\nfunction scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n return out;\n}\n/**\n * Adds two vec2's after scaling the second operand by a scalar value\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec2} out\n */\n\nfunction scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n return out;\n}\n/**\n * Calculates the euclidian distance between two vec2's\n *\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {Number} distance between a and b\n */\n\nfunction distance(a, b) {\n var x = b[0] - a[0],\n y = b[1] - a[1];\n return Math.hypot(x, y);\n}\n/**\n * Calculates the squared euclidian distance between two vec2's\n *\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {Number} squared distance between a and b\n */\n\nfunction squaredDistance(a, b) {\n var x = b[0] - a[0],\n y = b[1] - a[1];\n return x * x + y * y;\n}\n/**\n * Calculates the length of a vec2\n *\n * @param {ReadonlyVec2} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nfunction length(a) {\n var x = a[0],\n y = a[1];\n return Math.hypot(x, y);\n}\n/**\n * Calculates the squared length of a vec2\n *\n * @param {ReadonlyVec2} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\n\nfunction squaredLength(a) {\n var x = a[0],\n y = a[1];\n return x * x + y * y;\n}\n/**\n * Negates the components of a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to negate\n * @returns {vec2} out\n */\n\nfunction negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n return out;\n}\n/**\n * Returns the inverse of the components of a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to invert\n * @returns {vec2} out\n */\n\nfunction inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n return out;\n}\n/**\n * Normalize a vec2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a vector to normalize\n * @returns {vec2} out\n */\n\nfunction normalize(out, a) {\n var x = a[0],\n y = a[1];\n var len = x * x + y * y;\n\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n return out;\n}\n/**\n * Calculates the dot product of two vec2's\n *\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {Number} dot product of a and b\n */\n\nfunction dot(a, b) {\n return a[0] * b[0] + a[1] * b[1];\n}\n/**\n * Computes the cross product of two vec2's\n * Note that the cross product must by definition produce a 3D vector\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @returns {vec3} out\n */\n\nfunction cross(out, a, b) {\n var z = a[0] * b[1] - a[1] * b[0];\n out[0] = out[1] = 0;\n out[2] = z;\n return out;\n}\n/**\n * Performs a linear interpolation between two vec2's\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the first operand\n * @param {ReadonlyVec2} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec2} out\n */\n\nfunction lerp(out, a, b, t) {\n var ax = a[0],\n ay = a[1];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n return out;\n}\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec2} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\n * @returns {vec2} out\n */\n\nfunction random(out, scale) {\n scale = scale || 1.0;\n var r = RANDOM() * 2.0 * Math.PI;\n out[0] = Math.cos(r) * scale;\n out[1] = Math.sin(r) * scale;\n return out;\n}\n/**\n * Transforms the vec2 with a mat2\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the vector to transform\n * @param {ReadonlyMat2} m matrix to transform with\n * @returns {vec2} out\n */\n\nfunction transformMat2(out, a, m) {\n var x = a[0],\n y = a[1];\n out[0] = m[0] * x + m[2] * y;\n out[1] = m[1] * x + m[3] * y;\n return out;\n}\n/**\n * Transforms the vec2 with a mat2d\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the vector to transform\n * @param {ReadonlyMat2d} m matrix to transform with\n * @returns {vec2} out\n */\n\nfunction transformMat2d(out, a, m) {\n var x = a[0],\n y = a[1];\n out[0] = m[0] * x + m[2] * y + m[4];\n out[1] = m[1] * x + m[3] * y + m[5];\n return out;\n}\n/**\n * Transforms the vec2 with a mat3\n * 3rd vector component is implicitly '1'\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the vector to transform\n * @param {ReadonlyMat3} m matrix to transform with\n * @returns {vec2} out\n */\n\nfunction transformMat3(out, a, m) {\n var x = a[0],\n y = a[1];\n out[0] = m[0] * x + m[3] * y + m[6];\n out[1] = m[1] * x + m[4] * y + m[7];\n return out;\n}\n/**\n * Transforms the vec2 with a mat4\n * 3rd vector component is implicitly '0'\n * 4th vector component is implicitly '1'\n *\n * @param {vec2} out the receiving vector\n * @param {ReadonlyVec2} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec2} out\n */\n\nfunction transformMat4(out, a, m) {\n var x = a[0];\n var y = a[1];\n out[0] = m[0] * x + m[4] * y + m[12];\n out[1] = m[1] * x + m[5] * y + m[13];\n return out;\n}\n/**\n * Rotate a 2D vector\n * @param {vec2} out The receiving vec2\n * @param {ReadonlyVec2} a The vec2 point to rotate\n * @param {ReadonlyVec2} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec2} out\n */\n\nfunction rotate(out, a, b, rad) {\n //Translate point to the origin\n var p0 = a[0] - b[0],\n p1 = a[1] - b[1],\n sinC = Math.sin(rad),\n cosC = Math.cos(rad); //perform rotation and translate to correct position\n\n out[0] = p0 * cosC - p1 * sinC + b[0];\n out[1] = p0 * sinC + p1 * cosC + b[1];\n return out;\n}\n/**\n * Get the angle between two 2D vectors\n * @param {ReadonlyVec2} a The first operand\n * @param {ReadonlyVec2} b The second operand\n * @returns {Number} The angle in radians\n */\n\nfunction angle(a, b) {\n var x1 = a[0],\n y1 = a[1],\n x2 = b[0],\n y2 = b[1],\n // mag is the product of the magnitudes of a and b\n mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),\n // mag &&.. short circuits if mag == 0\n cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1\n\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n/**\n * Set the components of a vec2 to zero\n *\n * @param {vec2} out the receiving vector\n * @returns {vec2} out\n */\n\nfunction zero(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n return out;\n}\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec2} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nfunction str(a) {\n return \"vec2(\" + a[0] + \", \" + a[1] + \")\";\n}\n/**\n * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec2} a The first vector.\n * @param {ReadonlyVec2} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1];\n}\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec2} a The first vector.\n * @param {ReadonlyVec2} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nfunction equals(a, b) {\n var a0 = a[0],\n a1 = a[1];\n var b0 = b[0],\n b1 = b[1];\n return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1));\n}\n/**\n * Alias for {@link vec2.length}\n * @function\n */\n\nvar len = length;\n/**\n * Alias for {@link vec2.subtract}\n * @function\n */\n\nvar sub = subtract;\n/**\n * Alias for {@link vec2.multiply}\n * @function\n */\n\nvar mul = multiply;\n/**\n * Alias for {@link vec2.divide}\n * @function\n */\n\nvar div = divide;\n/**\n * Alias for {@link vec2.distance}\n * @function\n */\n\nvar dist = distance;\n/**\n * Alias for {@link vec2.squaredDistance}\n * @function\n */\n\nvar sqrDist = squaredDistance;\n/**\n * Alias for {@link vec2.squaredLength}\n * @function\n */\n\nvar sqrLen = squaredLength;\n/**\n * Perform some operation over an array of vec2s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\n\nvar forEach = function () {\n var vec = create();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n\n if (!stride) {\n stride = 2;\n }\n\n if (!offset) {\n offset = 0;\n }\n\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n }\n\n return a;\n };\n}();\n\nvar vec2 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create: create,\n clone: clone,\n fromValues: fromValues,\n copy: copy,\n set: set,\n add: add,\n subtract: subtract,\n multiply: multiply,\n divide: divide,\n ceil: ceil,\n floor: floor,\n min: min,\n max: max,\n round: round,\n scale: scale,\n scaleAndAdd: scaleAndAdd,\n distance: distance,\n squaredDistance: squaredDistance,\n length: length,\n squaredLength: squaredLength,\n negate: negate,\n inverse: inverse,\n normalize: normalize,\n dot: dot,\n cross: cross,\n lerp: lerp,\n random: random,\n transformMat2: transformMat2,\n transformMat2d: transformMat2d,\n transformMat3: transformMat3,\n transformMat4: transformMat4,\n rotate: rotate,\n angle: angle,\n zero: zero,\n str: str,\n exactEquals: exactEquals,\n equals: equals,\n len: len,\n sub: sub,\n mul: mul,\n div: div,\n dist: dist,\n sqrDist: sqrDist,\n sqrLen: sqrLen,\n forEach: forEach\n});\n\n/**\n * Provides a way to calculate velocity via effectively creating a \"complementary filter\".\n *\n * `velQuick` and `velSmooth` separately accumulate over time. `velInstant` and `velUsed` do not accumulate and are\n * discarded each update. `velQuick` is responsive, but noisy. `velSmooth` is laggy but eventually more accurate. By\n * tracking them separately the used result can be responsive in the short term and accurate in the long term.\n *\n * TODO: This class will be moved to a final location in the @typhonjs-svelte/lib/math package.\n */\nclass TJSVelocityTrack\n{\n /** @type {number} */\n #lastSampleTime;\n\n /**\n * Tracks the last sample point.\n *\n * @type {{x: number, y: number, z: number}}\n */\n #lastSamplePoint = { x: 0, y: 0, z: 0 };\n\n /**\n * Defines the settle time in milliseconds that resets any tracked velocity state.\n *\n * @type {number}\n */\n #resetDeltaTime;\n\n /**\n * Stores the scaling conversion for used velocity calculation. By default, this is 1000 which converts the velocity\n * calculation to velocity per second. Set to `1` for instance for velocity per millisecond.\n *\n * @type {number}\n */\n #scaleTime;\n\n /**\n * Stores the instant velocity between current and last sample point.\n *\n * @type {{x: number, y: number, z: number}}\n */\n #velInstant = { x: 0, y: 0, z: 0 };\n\n /**\n * Stores the `quick` running calculated velocity.\n *\n * @type {{x: number, y: number, z: number}}\n */\n #velQuick = { x: 0, y: 0, z: 0 };\n\n /**\n * Stores the `smooth` running calculated velocity.\n *\n * @type {{x: number, y: number, z: number}}\n */\n #velSmooth = { x: 0, y: 0, z: 0 };\n\n /**\n * Stores the mix between `quick` and `smooth` running velocity.\n *\n * @type {{x: number, y: number, z: number}}\n */\n #velUsed = { x: 0, y: 0, z: 0 };\n\n /**\n * Creates a velocity tracker instance.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.resetDeltaTime=50] - Delta time in milliseconds that resets velocity tracking.\n *\n * @param {number} [opts.scaleTime=1000] - Scales velocity calculation to new time frame. 1000 is velocity per\n * second.\n */\n constructor({ resetDeltaTime = 50, scaleTime = 1000 } = {})\n {\n this.resetDeltaTime = resetDeltaTime;\n this.scaleTime = scaleTime;\n\n Object.seal(this.#velUsed);\n }\n\n /**\n * @returns {number} Gets `resetDeltaTime`.\n */\n get resetDeltaTime() { return this.#resetDeltaTime; }\n\n /**\n * @returns {number} Gets `scaleTime`.\n */\n get scaleTime() { return this.#scaleTime; }\n\n /**\n * Sets `resetDeltaTime`.\n *\n * @param {number} resetDeltaTime - Delta time in milliseconds that resets velocity tracking.\n */\n set resetDeltaTime(resetDeltaTime)\n {\n if (!Number.isFinite(resetDeltaTime) || resetDeltaTime < 0)\n {\n throw new TypeError(`'resetDeltaTime' is not a positive finite number.`);\n }\n\n this.#resetDeltaTime = resetDeltaTime;\n }\n\n /**\n * Sets `scaleTime`.\n *\n * @param {number} scaleTime - Scales velocity calculation to new time frame. 1000 is velocity per second.\n */\n set scaleTime(scaleTime)\n {\n if (!Number.isFinite(scaleTime) || scaleTime < 0)\n {\n throw new TypeError(`'scaleTime' is not a positive finite number.`);\n }\n\n this.#scaleTime = scaleTime;\n }\n\n /**\n * Resets velocity tracking data.\n *\n * @param {number} [x=0] - 'X' value to set to last sample point.\n *\n * @param {number} [y=0] - 'Y' value to set to last sample point.\n *\n * @param {number} [z=0] - 'Z' value to set to last sample point.\n *\n * @param {number} [sampleTime=performance.now()] - A sample time in milliseconds resolution.\n */\n reset(x = 0, y = 0, z = 0, sampleTime = performance.now())\n {\n if (!Number.isFinite(x)) { throw new TypeError(`'x' is not a finite number.`); }\n if (!Number.isFinite(y)) { throw new TypeError(`'y' is not a finite number.`); }\n if (!Number.isFinite(z)) { throw new TypeError(`'z' is not a finite number.`); }\n if (!Number.isFinite(sampleTime)) { throw new TypeError(`'sampleTime' is not a finite number.`); }\n\n // Reset velocity tracking variables.\n this.#lastSampleTime = sampleTime;\n\n this.#lastSamplePoint.x = x;\n this.#lastSamplePoint.y = y;\n this.#lastSamplePoint.z = z;\n\n this.#velInstant.x = this.#velQuick.x = this.#velSmooth.x = this.#velUsed.x = 0;\n this.#velInstant.y = this.#velQuick.y = this.#velSmooth.y = this.#velUsed.y = 0;\n this.#velInstant.z = this.#velQuick.z = this.#velSmooth.z = this.#velUsed.z = 0;\n }\n\n /**\n * Runs ongoing velocity calculation of x / y / z given a sample time.\n *\n * @param {number|undefined} x - New sample X\n *\n * @param {number|undefined} y - New sample Y\n *\n * @param {number|undefined} z - New sample Z\n *\n * @param {number} [sampleTime=performance.now()] - An optional specific time w/ millisecond resolution.\n *\n * @returns {{x: number, y: number, z: number}} current velocity.\n */\n update(x = void 0, y = void 0, z = void 0, sampleTime = performance.now())\n {\n if (!Number.isFinite(sampleTime)) { throw new TypeError(`'sampleTime' is not a finite number.`); }\n\n const deltaTime = sampleTime - this.#lastSampleTime + Number.EPSILON;\n this.#lastSampleTime = sampleTime;\n\n // Reset velocity tracking if the delta time is greater than `resetDeltaTime`.\n if (deltaTime > this.#resetDeltaTime)\n {\n this.reset(x, y, z, sampleTime);\n return this.#velUsed;\n }\n\n if (Number.isFinite(x))\n {\n this.#velInstant.x = (x - this.#lastSamplePoint.x) / deltaTime;\n\n this.#lastSamplePoint.x = x;\n\n this.#velQuick.x = lerp$5(this.#velQuick.x, this.#velInstant.x, 0.1);\n this.#velSmooth.x = lerp$5(this.#velSmooth.x, this.#velInstant.x, 0.01);\n this.#velUsed.x = lerp$5(this.#velSmooth.x, this.#velQuick.x, 0.5) * this.#scaleTime;\n }\n\n if (Number.isFinite(y))\n {\n this.#velInstant.y = (y - this.#lastSamplePoint.y) / deltaTime;\n\n this.#lastSamplePoint.y = y;\n\n this.#velQuick.y = lerp$5(this.#velQuick.y, this.#velInstant.y, 0.1);\n this.#velSmooth.y = lerp$5(this.#velSmooth.y, this.#velInstant.y, 0.01);\n\n this.#velUsed.y = lerp$5(this.#velSmooth.y, this.#velQuick.y, 0.5) * this.#scaleTime;\n }\n\n if (Number.isFinite(z))\n {\n this.#velInstant.z = (z - this.#lastSamplePoint.z) / deltaTime;\n\n this.#lastSamplePoint.z = z;\n\n this.#velQuick.z = lerp$5(this.#velQuick.z, this.#velInstant.z, 0.1);\n this.#velSmooth.z = lerp$5(this.#velSmooth.z, this.#velInstant.z, 0.01);\n this.#velUsed.z = lerp$5(this.#velSmooth.z, this.#velQuick.z, 0.5) * this.#scaleTime;\n }\n\n return this.#velUsed;\n }\n\n /**\n * Gets the current velocity tracking data.\n *\n * @returns {{x: number, y: number, z: number}} Velocity tracking data.\n */\n get()\n {\n this.#velUsed.x = lerp$5(this.#velSmooth.x, this.#velQuick.x, 0.5) * this.#scaleTime;\n this.#velUsed.y = lerp$5(this.#velSmooth.y, this.#velQuick.y, 0.5) * this.#scaleTime;\n this.#velUsed.z = lerp$5(this.#velSmooth.z, this.#velQuick.z, 0.5) * this.#scaleTime;\n\n return this.#velUsed;\n }\n}\n\nexport { TJSVelocityTrack, degToRad, common as glMatrix, lerp$5 as lerp, mat2, mat2d, mat3, mat4, quat, quat2, radToDeg, vec2, vec3, vec4 };\n//# sourceMappingURL=index.js.map\n","/**\n * Provides a basic {@link TJSBasicAnimation} implementation for Position animation.\n */\nexport class AnimationControl\n{\n /** @type {object} */\n #animationData;\n\n /** @type {Promise} */\n #finishedPromise;\n\n #willFinish;\n\n /**\n * Defines a static empty / void animation control.\n *\n * @type {AnimationControl}\n */\n static #voidControl = new AnimationControl(null);\n\n /**\n * Provides a static void / undefined AnimationControl that is automatically resolved.\n *\n * @returns {AnimationControl} Void AnimationControl\n */\n static get voidControl() { return this.#voidControl; }\n\n /**\n * @param {object|null} [animationData] - Animation data from {@link AnimationAPI}.\n *\n * @param {boolean} [willFinish] - Promise that tracks animation finished state.\n */\n constructor(animationData, willFinish = false)\n {\n this.#animationData = animationData;\n this.#willFinish = willFinish;\n\n // Set this control to animation data.\n if (animationData !== null && typeof animationData === 'object')\n {\n animationData.control = this;\n }\n }\n\n /**\n * Get a promise that resolves when animation is finished.\n *\n * @returns {Promise}\n */\n get finished()\n {\n if (!(this.#finishedPromise instanceof Promise))\n {\n this.#finishedPromise = this.#willFinish ? new Promise((resolve) => this.#animationData.resolve = resolve) :\n Promise.resolve();\n }\n\n return this.#finishedPromise;\n }\n\n /**\n * Returns whether this animation is currently active / animating.\n *\n * Note: a delayed animation may not be started / active yet. Use {@link AnimationControl.isFinished} to determine\n * if an animation is actually finished.\n *\n * @returns {boolean} Animation active state.\n */\n get isActive() { return this.#animationData.active; }\n\n /**\n * Returns whether this animation is completely finished.\n *\n * @returns {boolean} Animation finished state.\n */\n get isFinished() { return this.#animationData.finished; }\n\n /**\n * Cancels the animation.\n */\n cancel()\n {\n const animationData = this.#animationData;\n\n if (animationData === null || animationData === void 0) { return; }\n\n // Set cancelled state to true and this animation data instance will be removed from AnimationManager on next\n // update.\n animationData.cancelled = true;\n }\n}\n","/**\n * Provides animation management and scheduling allowing all Position instances to utilize one micro-task.\n */\nexport class AnimationManager\n{\n /**\n * @type {object[]}\n */\n static activeList = [];\n\n /**\n * @type {object[]}\n */\n static newList = [];\n\n /**\n * @type {number}\n */\n static current;\n\n /**\n * Add animation data.\n *\n * @param {object} data -\n */\n static add(data)\n {\n const now = performance.now();\n\n // Offset start time by delta between last rAF time. This allows continuous tween cycles to appear naturally as\n // starting from the instant they are added to the AnimationManager. This is what makes `draggable` smooth when\n // easing is enabled.\n data.start = now + (AnimationManager.current - now);\n\n AnimationManager.newList.push(data);\n }\n\n /**\n * Manage all animation\n */\n static animate()\n {\n const current = AnimationManager.current = performance.now();\n\n // Early out of the rAF callback when there are no current animations.\n if (AnimationManager.activeList.length === 0 && AnimationManager.newList.length === 0)\n {\n globalThis.requestAnimationFrame(AnimationManager.animate);\n return;\n }\n\n if (AnimationManager.newList.length)\n {\n // Process new data\n for (let cntr = AnimationManager.newList.length; --cntr >= 0;)\n {\n const data = AnimationManager.newList[cntr];\n\n // If animation instance has been cancelled before start then remove it from new list and cleanup.\n if (data.cancelled)\n {\n AnimationManager.newList.splice(cntr, 1);\n data.cleanup(data);\n }\n\n // If data is active then process it now. Delayed animations start with `active` false.\n if (data.active)\n {\n // Remove from new list and add to active list.\n AnimationManager.newList.splice(cntr, 1);\n AnimationManager.activeList.push(data);\n }\n }\n }\n\n // Process active animations.\n for (let cntr = AnimationManager.activeList.length; --cntr >= 0;)\n {\n const data = AnimationManager.activeList[cntr];\n\n // Remove any animations that have been canceled.\n // Ensure that the element is still connected otherwise remove it from active list and continue.\n if (data.cancelled || (data.el !== void 0 && !data.el.isConnected))\n {\n AnimationManager.activeList.splice(cntr, 1);\n data.cleanup(data);\n continue;\n }\n\n data.current = current - data.start;\n\n // Remove this animation instance if current animating time exceeds duration.\n if (data.current >= data.duration)\n {\n // Prepare final update with end position data.\n for (let dataCntr = data.keys.length; --dataCntr >= 0;)\n {\n const key = data.keys[dataCntr];\n data.newData[key] = data.destination[key];\n }\n\n data.position.set(data.newData);\n\n AnimationManager.activeList.splice(cntr, 1);\n data.cleanup(data);\n\n continue;\n }\n\n // Apply easing to create an eased time.\n const easedTime = data.ease(data.current / data.duration);\n\n for (let dataCntr = data.keys.length; --dataCntr >= 0;)\n {\n const key = data.keys[dataCntr];\n data.newData[key] = data.interpolate(data.initial[key], data.destination[key], easedTime);\n }\n\n data.position.set(data.newData);\n }\n\n globalThis.requestAnimationFrame(AnimationManager.animate);\n }\n\n /**\n * Cancels all animations for given Position instance.\n *\n * @param {Position} position - Position instance.\n */\n static cancel(position)\n {\n for (let cntr = AnimationManager.activeList.length; --cntr >= 0;)\n {\n const data = AnimationManager.activeList[cntr];\n if (data.position === position)\n {\n AnimationManager.activeList.splice(cntr, 1);\n data.cancelled = true;\n data.cleanup(data);\n }\n }\n\n for (let cntr = AnimationManager.newList.length; --cntr >= 0;)\n {\n const data = AnimationManager.newList[cntr];\n if (data.position === position)\n {\n AnimationManager.newList.splice(cntr, 1);\n data.cancelled = true;\n data.cleanup(data);\n }\n }\n }\n\n /**\n * Cancels all active and delayed animations.\n */\n static cancelAll()\n {\n for (let cntr = AnimationManager.activeList.length; --cntr >= 0;)\n {\n const data = AnimationManager.activeList[cntr];\n data.cancelled = true;\n data.cleanup(data);\n }\n\n for (let cntr = AnimationManager.newList.length; --cntr >= 0;)\n {\n const data = AnimationManager.newList[cntr];\n data.cancelled = true;\n data.cleanup(data);\n }\n\n AnimationManager.activeList.length = 0;\n AnimationManager.newList.length = 0;\n }\n\n /**\n * Gets all {@link AnimationControl} instances for a given Position instance.\n *\n * @param {Position} position - Position instance.\n *\n * @returns {AnimationControl[]} All scheduled AnimationControl instances for the given Position instance.\n */\n static getScheduled(position)\n {\n const results = [];\n\n for (let cntr = AnimationManager.activeList.length; --cntr >= 0;)\n {\n const data = AnimationManager.activeList[cntr];\n if (data.position === position)\n {\n results.push(data.control);\n }\n }\n\n for (let cntr = AnimationManager.newList.length; --cntr >= 0;)\n {\n const data = AnimationManager.newList[cntr];\n if (data.position === position)\n {\n results.push(data.control);\n }\n }\n\n return results;\n }\n}\n\n// Start animation manager immediately. It constantly is running in background.\nAnimationManager.animate();\n","/**\n * Stores the PositionData properties that can be animated.\n *\n * @type {Set}\n */\nconst animateKeys = new Set([\n // Main keys\n 'left', 'top', 'maxWidth', 'maxHeight', 'minWidth', 'minHeight', 'width', 'height',\n 'rotateX', 'rotateY', 'rotateZ', 'scale', 'translateX', 'translateY', 'translateZ', 'zIndex',\n\n // Aliases\n 'rotation'\n]);\n\n/**\n * Defines the keys of PositionData that are transform keys.\n *\n * @type {string[]}\n */\nconst transformKeys = ['rotateX', 'rotateY', 'rotateZ', 'scale', 'translateX', 'translateY', 'translateZ'];\n\nObject.freeze(transformKeys);\n\n/**\n * Parses a relative value string in the form of '+=', '-=', or '*=' and float / numeric value. IE '+=0.2'.\n *\n * @type {RegExp}\n */\nconst relativeRegex = /^([-+*])=(-?[\\d]*\\.?[\\d]+)$/;\n\n/**\n * Provides numeric defaults for all parameters. This is used by {@link Position.get} to optionally provide\n * numeric defaults.\n *\n * @type {{rotation: number, scale: number, minWidth: null, minHeight: null, translateZ: number, top: number, left: number, maxHeight: null, translateY: number, translateX: number, width: number, transformOrigin: null, rotateX: number, rotateY: number, height: number, maxWidth: null, zIndex: null, rotateZ: number}}\n */\nconst numericDefaults = {\n // Other keys\n height: 0,\n left: 0,\n maxHeight: null,\n maxWidth: null,\n minHeight: null,\n minWidth: null,\n top: 0,\n transformOrigin: null,\n width: 0,\n zIndex: null,\n\n rotateX: 0,\n rotateY: 0,\n rotateZ: 0,\n scale: 1,\n translateX: 0,\n translateY: 0,\n translateZ: 0,\n\n rotation: 0\n};\n\nObject.freeze(numericDefaults);\n\n/**\n * Sets numeric defaults for a {@link PositionData} like object.\n *\n * @param {object} data - A PositionData like object.\n */\nfunction setNumericDefaults(data)\n{\n // Transform keys\n if (data.rotateX === null) { data.rotateX = 0; }\n if (data.rotateY === null) { data.rotateY = 0; }\n if (data.rotateZ === null) { data.rotateZ = 0; }\n if (data.translateX === null) { data.translateX = 0; }\n if (data.translateY === null) { data.translateY = 0; }\n if (data.translateZ === null) { data.translateZ = 0; }\n if (data.scale === null) { data.scale = 1; }\n\n // Aliases\n if (data.rotation === null) { data.rotation = 0; }\n}\n\n/**\n * Defines bitwise keys for transforms used in {@link Transforms.getMat4}.\n *\n * @type {object}\n */\nconst transformKeysBitwise = {\n rotateX: 1,\n rotateY: 2,\n rotateZ: 4,\n scale: 8,\n translateX: 16,\n translateY: 32,\n translateZ: 64\n};\n\nObject.freeze(transformKeysBitwise);\n\n/**\n * Defines the default transform origin.\n *\n * @type {string}\n */\nconst transformOriginDefault = 'top left';\n\n/**\n * Defines the valid transform origins.\n *\n * @type {string[]}\n */\nconst transformOrigins = ['top left', 'top center', 'top right', 'center left', 'center', 'center right', 'bottom left',\n 'bottom center', 'bottom right'];\n\nObject.freeze(transformOrigins);\n\nexport {\n animateKeys,\n numericDefaults,\n relativeRegex,\n setNumericDefaults,\n transformKeys,\n transformKeysBitwise,\n transformOriginDefault,\n transformOrigins\n};\n","import * as constants from './constants.js';\n\n/**\n * Converts any relative string values for animatable keys to actual updates performed against current data.\n *\n * @param {PositionDataExtended} positionData - position data.\n *\n * @param {Position|PositionData} position - The source position instance.\n */\nexport function convertRelative(positionData, position)\n{\n for (const key in positionData)\n {\n // Key is animatable / numeric.\n if (constants.animateKeys.has(key))\n {\n const value = positionData[key];\n\n if (typeof value !== 'string') { continue; }\n\n // Ignore 'auto' and 'inherit' string values.\n if (value === 'auto' || value === 'inherit') { continue; }\n\n const regexResults = constants.relativeRegex.exec(value);\n\n if (!regexResults)\n {\n throw new Error(\n `convertRelative error: malformed relative key (${key}) with value (${value})`);\n }\n\n const current = position[key];\n\n switch (regexResults[1])\n {\n case '-':\n positionData[key] = current - parseFloat(regexResults[2]);\n break;\n\n case '+':\n positionData[key] = current + parseFloat(regexResults[2]);\n break;\n\n case '*':\n positionData[key] = current * parseFloat(regexResults[2]);\n break;\n }\n }\n }\n}\n","import { cubicOut } from 'svelte/easing';\n\nimport { lerp } from '@typhonjs-fvtt/runtime/svelte/math';\nimport {\n isIterable,\n isObject } from '@typhonjs-fvtt/runtime/svelte/util';\n\nimport { AnimationControl } from './AnimationControl.js';\nimport { AnimationManager } from './AnimationManager.js';\n\nimport { convertRelative } from '../convertRelative.js';\n\nimport {\n animateKeys,\n setNumericDefaults } from '../constants.js';\n\nexport class AnimationAPI\n{\n /** @type {PositionData} */\n #data;\n\n /** @type {Position} */\n #position;\n\n /**\n * Tracks the number of animation control instances that are active.\n *\n * @type {number}\n */\n #instanceCount = 0;\n\n /**\n * Provides a bound function to pass as data to AnimationManager to invoke\n *\n * @type {Function}\n * @see {AnimationAPI.#cleanupInstance}\n */\n #cleanup;\n\n constructor(position, data)\n {\n this.#position = position;\n this.#data = data;\n\n this.#cleanup = this.#cleanupInstance.bind(this);\n }\n\n /**\n * Returns whether there are scheduled animations whether active or delayed for this Position.\n *\n * @returns {boolean} Are there active animation instances.\n */\n get isScheduled()\n {\n return this.#instanceCount > 0;\n }\n\n /**\n * Adds / schedules an animation w/ the AnimationManager. This contains the final steps common to all tweens.\n *\n * @param {object} initial -\n *\n * @param {object} destination -\n *\n * @param {number} duration -\n *\n * @param {HTMLElement} el -\n *\n * @param {number} delay -\n *\n * @param {Function} ease -\n *\n * @param {Function} interpolate -\n *\n * @returns {AnimationControl} The associated animation control.\n */\n #addAnimation(initial, destination, duration, el, delay, ease, interpolate)\n {\n // Set initial data for transform values that are often null by default.\n setNumericDefaults(initial);\n setNumericDefaults(destination);\n\n // Reject all initial data that is not a number.\n for (const key in initial)\n {\n if (!Number.isFinite(initial[key])) { delete initial[key]; }\n }\n\n const keys = Object.keys(initial);\n const newData = Object.assign({ immediateElementUpdate: true }, initial);\n\n // Nothing to animate, so return now.\n if (keys.length === 0) { return AnimationControl.voidControl; }\n\n const animationData = {\n active: true,\n cleanup: this.#cleanup,\n cancelled: false,\n control: void 0,\n current: 0,\n destination,\n duration: duration * 1000, // Internally the AnimationManager works in ms.\n ease,\n el,\n finished: false,\n initial,\n interpolate,\n keys,\n newData,\n position: this.#position,\n resolve: void 0,\n start: void 0\n };\n\n if (delay > 0)\n {\n animationData.active = false;\n\n // Delay w/ setTimeout and schedule w/ AnimationManager if not already canceled\n setTimeout(() =>\n {\n if (!animationData.cancelled)\n {\n animationData.active = true;\n\n const now = performance.now();\n\n // Offset start time by delta between last rAF time. This allows a delayed tween to start from the\n // precise delayed time.\n animationData.start = now + (AnimationManager.current - now);\n }\n }, delay * 1000);\n }\n\n // Schedule immediately w/ AnimationManager\n this.#instanceCount++;\n AnimationManager.add(animationData);\n\n // Create animation control\n return new AnimationControl(animationData, true);\n }\n\n /**\n * Cancels all animation instances for this Position instance.\n */\n cancel()\n {\n AnimationManager.cancel(this.#position);\n }\n\n /**\n * Cleans up an animation instance.\n *\n * @param {object} data - Animation data for an animation instance.\n */\n #cleanupInstance(data)\n {\n this.#instanceCount--;\n\n data.active = false;\n data.finished = true;\n\n if (typeof data.resolve === 'function') { data.resolve(data.cancelled); }\n }\n\n /**\n * Returns all currently scheduled AnimationControl instances for this Position instance.\n *\n * @returns {AnimationControl[]} All currently scheduled animation controls for this Position instance.\n */\n getScheduled()\n {\n return AnimationManager.getScheduled(this.#position);\n }\n\n /**\n * Provides a tween from given position data to the current position.\n *\n * @param {PositionDataExtended} fromData - The starting position.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.delay=0] - Delay in seconds before animation starts.\n *\n * @param {number} [opts.duration=1] - Duration in seconds.\n *\n * @param {Function} [opts.ease=cubicOut] - Easing function.\n *\n * @param {Function} [opts.interpolate=lerp] - Interpolation function.\n *\n * @returns {AnimationControl} A control object that can cancel animation and provides a `finished` Promise.\n */\n from(fromData, { delay = 0, duration = 1, ease = cubicOut, interpolate = lerp } = {})\n {\n if (!isObject(fromData))\n {\n throw new TypeError(`AnimationAPI.from error: 'fromData' is not an object.`);\n }\n\n const position = this.#position;\n const parent = position.parent;\n\n // Early out if the application is not positionable.\n if (parent !== void 0 && typeof parent?.options?.positionable === 'boolean' && !parent?.options?.positionable)\n {\n return AnimationControl.voidControl;\n }\n\n // Cache any target element allowing AnimationManager to stop animation if it becomes disconnected from DOM.\n const targetEl = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n const el = targetEl instanceof HTMLElement && targetEl.isConnected ? targetEl : void 0;\n\n if (!Number.isFinite(delay) || delay < 0)\n {\n throw new TypeError(`AnimationAPI.from error: 'delay' is not a positive number.`);\n }\n\n if (!Number.isFinite(duration) || duration < 0)\n {\n throw new TypeError(`AnimationAPI.from error: 'duration' is not a positive number.`);\n }\n\n if (typeof ease !== 'function')\n {\n throw new TypeError(`AnimationAPI.from error: 'ease' is not a function.`);\n }\n\n if (typeof interpolate !== 'function')\n {\n throw new TypeError(`AnimationAPI.from error: 'interpolate' is not a function.`);\n }\n\n const initial = {};\n const destination = {};\n\n const data = this.#data;\n\n // Set initial data if the key / data is defined and the end position is not equal to current data.\n for (const key in fromData)\n {\n if (data[key] !== void 0 && fromData[key] !== data[key])\n {\n initial[key] = fromData[key];\n destination[key] = data[key];\n }\n }\n\n convertRelative(initial, data);\n\n return this.#addAnimation(initial, destination, duration, el, delay, ease, interpolate);\n }\n\n /**\n * Provides a tween from given position data to the current position.\n *\n * @param {PositionDataExtended} fromData - The starting position.\n *\n * @param {PositionDataExtended} toData - The ending position.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.delay=0] - Delay in seconds before animation starts.\n *\n * @param {number} [opts.duration=1] - Duration in seconds.\n *\n * @param {Function} [opts.ease=cubicOut] - Easing function.\n *\n * @param {Function} [opts.interpolate=lerp] - Interpolation function.\n *\n * @returns {AnimationControl} A control object that can cancel animation and provides a `finished` Promise.\n */\n fromTo(fromData, toData, { delay = 0, duration = 1, ease = cubicOut, interpolate = lerp } = {})\n {\n if (!isObject(fromData))\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'fromData' is not an object.`);\n }\n\n if (!isObject(toData))\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'toData' is not an object.`);\n }\n\n const parent = this.#position.parent;\n\n // Early out if the application is not positionable.\n if (parent !== void 0 && typeof parent?.options?.positionable === 'boolean' && !parent?.options?.positionable)\n {\n return AnimationControl.voidControl;\n }\n\n // Cache any target element allowing AnimationManager to stop animation if it becomes disconnected from DOM.\n const targetEl = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n const el = targetEl instanceof HTMLElement && targetEl.isConnected ? targetEl : void 0;\n\n if (!Number.isFinite(delay) || delay < 0)\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'delay' is not a positive number.`);\n }\n\n if (!Number.isFinite(duration) || duration < 0)\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'duration' is not a positive number.`);\n }\n\n if (typeof ease !== 'function')\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'ease' is not a function.`);\n }\n\n if (typeof interpolate !== 'function')\n {\n throw new TypeError(`AnimationAPI.fromTo error: 'interpolate' is not a function.`);\n }\n\n const initial = {};\n const destination = {};\n\n const data = this.#data;\n\n // Set initial data if the key / data is defined and the end position is not equal to current data.\n for (const key in fromData)\n {\n if (toData[key] === void 0)\n {\n console.warn(\n `AnimationAPI.fromTo warning: key ('${key}') from 'fromData' missing in 'toData'; skipping this key.`);\n continue;\n }\n\n if (data[key] !== void 0)\n {\n initial[key] = fromData[key];\n destination[key] = toData[key];\n }\n }\n\n convertRelative(initial, data);\n convertRelative(destination, data);\n\n return this.#addAnimation(initial, destination, duration, el, delay, ease, interpolate);\n }\n\n /**\n * Provides a tween to given position data from the current position.\n *\n * @param {PositionDataExtended} toData - The destination position.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.delay=0] - Delay in seconds before animation starts.\n *\n * @param {number} [opts.duration=1] - Duration in seconds.\n *\n * @param {Function} [opts.ease=cubicOut] - Easing function.\n *\n * @param {Function} [opts.interpolate=lerp] - Interpolation function.\n *\n * @returns {AnimationControl} A control object that can cancel animation and provides a `finished` Promise.\n */\n to(toData, { delay = 0, duration = 1, ease = cubicOut, interpolate = lerp } = {})\n {\n if (!isObject(toData))\n {\n throw new TypeError(`AnimationAPI.to error: 'toData' is not an object.`);\n }\n\n const parent = this.#position.parent;\n\n // Early out if the application is not positionable.\n if (parent !== void 0 && typeof parent?.options?.positionable === 'boolean' && !parent?.options?.positionable)\n {\n return AnimationControl.voidControl;\n }\n\n // Cache any target element allowing AnimationManager to stop animation if it becomes disconnected from DOM.\n const targetEl = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n const el = targetEl instanceof HTMLElement && targetEl.isConnected ? targetEl : void 0;\n\n if (!Number.isFinite(delay) || delay < 0)\n {\n throw new TypeError(`AnimationAPI.to error: 'delay' is not a positive number.`);\n }\n\n if (!Number.isFinite(duration) || duration < 0)\n {\n throw new TypeError(`AnimationAPI.to error: 'duration' is not a positive number.`);\n }\n\n if (typeof ease !== 'function')\n {\n throw new TypeError(`AnimationAPI.to error: 'ease' is not a function.`);\n }\n\n if (typeof interpolate !== 'function')\n {\n throw new TypeError(`AnimationAPI.to error: 'interpolate' is not a function.`);\n }\n\n const initial = {};\n const destination = {};\n\n const data = this.#data;\n\n // Set initial data if the key / data is defined and the end position is not equal to current data.\n for (const key in toData)\n {\n if (data[key] !== void 0 && toData[key] !== data[key])\n {\n destination[key] = toData[key];\n initial[key] = data[key];\n }\n }\n\n convertRelative(destination, data);\n\n return this.#addAnimation(initial, destination, duration, el, delay, ease, interpolate);\n }\n\n /**\n * Returns a function that provides an optimized way to constantly update a to-tween.\n *\n * @param {Iterable} keys - The keys for quickTo.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.duration=1] - Duration in seconds.\n *\n * @param {Function} [opts.ease=cubicOut] - Easing function.\n *\n * @param {Function} [opts.interpolate=lerp] - Interpolation function.\n *\n * @returns {quickToCallback} quick-to tween function.\n */\n quickTo(keys, { duration = 1, ease = cubicOut, interpolate = lerp } = {})\n {\n if (!isIterable(keys))\n {\n throw new TypeError(`AnimationAPI.quickTo error: 'keys' is not an iterable list.`);\n }\n\n const parent = this.#position.parent;\n\n // Early out if the application is not positionable.\n if (parent !== void 0 && typeof parent?.options?.positionable === 'boolean' && !parent?.options?.positionable)\n {\n throw new Error(`AnimationAPI.quickTo error: 'parent' is not positionable.`);\n }\n\n if (!Number.isFinite(duration) || duration < 0)\n {\n throw new TypeError(`AnimationAPI.quickTo error: 'duration' is not a positive number.`);\n }\n\n if (typeof ease !== 'function')\n {\n throw new TypeError(`AnimationAPI.quickTo error: 'ease' is not a function.`);\n }\n\n if (typeof interpolate !== 'function')\n {\n throw new TypeError(`AnimationAPI.quickTo error: 'interpolate' is not a function.`);\n }\n\n const initial = {};\n const destination = {};\n\n const data = this.#data;\n\n // Set initial data if the key / data is defined and the end position is not equal to current data.\n for (const key of keys)\n {\n if (typeof key !== 'string')\n {\n throw new TypeError(`AnimationAPI.quickTo error: key is not a string.`);\n }\n\n if (!animateKeys.has(key))\n {\n throw new Error(`AnimationAPI.quickTo error: key ('${key}') is not animatable.`);\n }\n\n if (data[key] !== void 0)\n {\n destination[key] = data[key];\n initial[key] = data[key];\n }\n }\n\n const keysArray = [...keys];\n\n Object.freeze(keysArray);\n\n const newData = Object.assign({ immediateElementUpdate: true }, initial);\n\n const animationData = {\n active: true,\n cleanup: this.#cleanup,\n cancelled: false,\n control: void 0,\n current: 0,\n destination,\n duration: duration * 1000, // Internally the AnimationManager works in ms.\n ease,\n el: void 0,\n finished: true, // Note: start in finished state to add to AnimationManager on first callback.\n initial,\n interpolate,\n keys,\n newData,\n position: this.#position,\n resolve: void 0,\n start: void 0\n };\n\n const quickToCB = (...args) =>\n {\n const argsLength = args.length;\n\n if (argsLength === 0) { return; }\n\n for (let cntr = keysArray.length; --cntr >= 0;)\n {\n const key = keysArray[cntr];\n if (data[key] !== void 0) { initial[key] = data[key]; }\n }\n\n // Handle case where the first arg is an object. Update all quickTo keys from data contained in the object.\n if (isObject(args[0]))\n {\n const objData = args[0];\n\n for (const key in objData)\n {\n if (destination[key] !== void 0) { destination[key] = objData[key]; }\n }\n }\n else // Assign each variable argument to the key specified in the initial `keys` array above.\n {\n for (let cntr = 0; cntr < argsLength && cntr < keysArray.length; cntr++)\n {\n const key = keysArray[cntr];\n if (destination[key] !== void 0) { destination[key] = args[cntr]; }\n }\n }\n\n convertRelative(destination, data);\n\n // Set initial data for transform values that are often null by default.\n setNumericDefaults(initial);\n setNumericDefaults(destination);\n\n // Set target element to animation data to track if it is removed from the DOM hence ending the animation.\n const targetEl = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n animationData.el = targetEl instanceof HTMLElement && targetEl.isConnected ? targetEl : void 0;\n\n // Reschedule the quickTo animation with AnimationManager as it is finished.\n if (animationData.finished)\n {\n animationData.finished = false;\n animationData.active = true;\n animationData.current = 0;\n\n this.#instanceCount++;\n AnimationManager.add(animationData);\n }\n else // QuickTo animation is currently scheduled w/ AnimationManager so reset start and current time.\n {\n const now = performance.now();\n\n // Offset start time by delta between last rAF time. This allows a delayed tween to start from the\n // precise delayed time.\n animationData.start = now + (AnimationManager.current - now);\n animationData.current = 0;\n }\n };\n\n quickToCB.keys = keysArray;\n\n /**\n * Sets options of quickTo tween.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {number} [opts.duration] - Duration in seconds.\n *\n * @param {Function} [opts.ease] - Easing function.\n *\n * @param {Function} [opts.interpolate] - Interpolation function.\n *\n * @returns {quickToCallback} The quickTo callback.\n */\n quickToCB.options = ({ duration, ease, interpolate } = {}) => // eslint-disable-line no-shadow\n {\n if (duration !== void 0 && (!Number.isFinite(duration) || duration < 0))\n {\n throw new TypeError(`AnimationAPI.quickTo.options error: 'duration' is not a positive number.`);\n }\n\n if (ease !== void 0 && typeof ease !== 'function')\n {\n throw new TypeError(`AnimationAPI.quickTo.options error: 'ease' is not a function.`);\n }\n\n if (interpolate !== void 0 && typeof interpolate !== 'function')\n {\n throw new TypeError(`AnimationAPI.quickTo.options error: 'interpolate' is not a function.`);\n }\n\n if (duration >= 0) { animationData.duration = duration * 1000; }\n if (ease) { animationData.ease = ease; }\n if (interpolate) { animationData.interpolate = interpolate; }\n\n return quickToCB;\n };\n\n return quickToCB;\n }\n}\n\n/**\n * @callback quickToCallback\n *\n * @param {...number|object} args - Either individual numbers corresponding to the order in which keys are specified or\n * a single object with keys specified and numerical values.\n *\n * @property {({duration?: number, ease?: Function, interpolate?: Function}) => quickToCallback} options - A function\n * to update options for quickTo function.\n */\n","/**\n * Provides a basic {@link TJSBasicAnimation} implementation for a Position animation for a group of Position instances.\n */\nexport class AnimationGroupControl\n{\n /** @type {AnimationControl[]} */\n #animationControls;\n\n /** @type {Promise[]>} */\n #finishedPromise;\n\n /**\n * Defines a static empty / void animation control.\n *\n * @type {AnimationGroupControl}\n */\n static #voidControl = new AnimationGroupControl(null);\n\n /**\n * Provides a static void / undefined AnimationGroupControl that is automatically resolved.\n *\n * @returns {AnimationGroupControl} Void AnimationGroupControl\n */\n static get voidControl() { return this.#voidControl; }\n\n /**\n * @param {AnimationControl[]} animationControls - An array of AnimationControl instances.\n */\n constructor(animationControls)\n {\n this.#animationControls = animationControls;\n }\n\n /**\n * Get a promise that resolves when all animations are finished.\n *\n * @returns {Promise[]>|Promise} Finished Promise for all animations.\n */\n get finished()\n {\n const animationControls = this.#animationControls;\n\n if (animationControls === null || animationControls === void 0) { return Promise.resolve(); }\n\n if (!(this.#finishedPromise instanceof Promise))\n {\n const promises = [];\n for (let cntr = animationControls.length; --cntr >= 0;)\n {\n promises.push(animationControls[cntr].finished);\n }\n\n this.#finishedPromise = Promise.all(promises);\n }\n\n return this.#finishedPromise;\n }\n\n /**\n * Returns whether there are active animation instances for this group.\n *\n * Note: a delayed animation may not be started / active yet. Use {@link AnimationGroupControl.isFinished} to\n * determine if all animations in the group are finished.\n *\n * @returns {boolean} Are there active animation instances.\n */\n get isActive()\n {\n const animationControls = this.#animationControls;\n\n if (animationControls === null || animationControls === void 0) { return false; }\n\n for (let cntr = animationControls.length; --cntr >= 0;)\n {\n if (animationControls[cntr].isActive) { return true; }\n }\n\n return false;\n }\n\n /**\n * Returns whether all animations in the group are finished.\n *\n * @returns {boolean} Are all animation instances finished.\n */\n get isFinished()\n {\n const animationControls = this.#animationControls;\n\n if (animationControls === null || animationControls === void 0) { return true; }\n\n for (let cntr = animationControls.length; --cntr >= 0;)\n {\n if (!animationControls[cntr].isFinished) { return false; }\n }\n\n return false;\n }\n\n /**\n * Cancels the all animations.\n */\n cancel()\n {\n const animationControls = this.#animationControls;\n\n if (animationControls === null || animationControls === void 0) { return; }\n\n for (let cntr = this.#animationControls.length; --cntr >= 0;)\n {\n this.#animationControls[cntr].cancel();\n }\n }\n}\n","import {\n isIterable,\n isObject } from '@typhonjs-fvtt/runtime/svelte/util';\n\nimport { AnimationManager } from './AnimationManager.js';\nimport { AnimationAPI } from './AnimationAPI.js';\nimport { AnimationGroupControl } from './AnimationGroupControl.js';\n\n/**\n * Provides a public API for grouping multiple {@link Position} animations together with the AnimationManager.\n *\n * Note: To remove cyclic dependencies as this class provides the Position static / group Animation API `instanceof`\n * checks are not done against Position. Instead, a check for the animate property being an instanceof\n * {@link AnimationAPI} is performed in {@link AnimationGroupAPI.#isPosition}.\n *\n * @see AnimationAPI\n */\nexport class AnimationGroupAPI\n{\n /**\n * Checks of the given object is a Position instance by checking for AnimationAPI.\n *\n * @param {*} object - Any data.\n *\n * @returns {boolean} Is Position.\n */\n static #isPosition(object)\n {\n return object !== null && typeof object === 'object' && object.animate instanceof AnimationAPI;\n }\n\n /**\n * Cancels any animation for given Position data.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n */\n static cancel(position)\n {\n if (isIterable(position))\n {\n let index = -1;\n\n for (const entry of position)\n {\n index++;\n\n const actualPosition = this.#isPosition(entry) ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.cancel warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n AnimationManager.cancel(actualPosition);\n }\n }\n else\n {\n const actualPosition = this.#isPosition(position) ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.cancel warning: No Position instance found.`);\n return;\n }\n\n AnimationManager.cancel(actualPosition);\n }\n }\n\n /**\n * Cancels all Position animation.\n */\n static cancelAll() { AnimationManager.cancelAll(); }\n\n /**\n * Gets all animation controls for the given position data.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n *\n * @returns {{position: Position, data: object|void, controls: AnimationControl[]}[]} Results array.\n */\n static getScheduled(position)\n {\n const results = [];\n\n if (isIterable(position))\n {\n let index = -1;\n\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.getScheduled warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n const controls = AnimationManager.getScheduled(actualPosition);\n\n results.push({ position: actualPosition, data: isPosition ? void 0 : entry, controls });\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.getScheduled warning: No Position instance found.`);\n return results;\n }\n\n const controls = AnimationManager.getScheduled(actualPosition);\n\n results.push({ position: actualPosition, data: isPosition ? void 0 : position, controls });\n }\n\n return results;\n }\n\n /**\n * Provides the `from` animation tween for one or more Position instances as a group.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n *\n * @param {object|Function} fromData -\n *\n * @param {object|Function} options -\n *\n * @returns {TJSBasicAnimation} Basic animation control.\n */\n static from(position, fromData, options)\n {\n if (!isObject(fromData) && typeof fromData !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.from error: 'fromData' is not an object or function.`);\n }\n\n if (options !== void 0 && !isObject(options) && typeof options !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.from error: 'options' is not an object or function.`);\n }\n\n /**\n * @type {AnimationControl[]}\n */\n const animationControls = [];\n\n let index = -1;\n let callbackOptions;\n\n const hasDataCallback = typeof fromData === 'function';\n const hasOptionCallback = typeof options === 'function';\n const hasCallback = hasDataCallback || hasOptionCallback;\n\n if (hasCallback) { callbackOptions = { index, position: void 0, data: void 0 }; }\n\n let actualFromData = fromData;\n let actualOptions = options;\n\n if (isIterable(position))\n {\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.from warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n }\n\n if (hasDataCallback)\n {\n actualFromData = fromData(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualFromData === null || actualFromData === void 0) { continue; }\n\n if (typeof actualFromData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.from error: fromData callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualOptions === null || actualOptions === void 0) { continue; }\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.from error: options callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.from(actualFromData, actualOptions));\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.from warning: No Position instance found.`);\n return AnimationGroupControl.voidControl;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n }\n\n if (hasDataCallback)\n {\n actualFromData = fromData(callbackOptions);\n\n if (typeof actualFromData !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.from error: fromData callback function failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.from error: options callback function failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.from(actualFromData, actualOptions));\n }\n\n return new AnimationGroupControl(animationControls);\n }\n\n /**\n * Provides the `fromTo` animation tween for one or more Position instances as a group.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n *\n * @param {object|Function} fromData -\n *\n * @param {object|Function} toData -\n *\n * @param {object|Function} options -\n *\n * @returns {TJSBasicAnimation} Basic animation control.\n */\n static fromTo(position, fromData, toData, options)\n {\n if (!isObject(fromData) && typeof fromData !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: 'fromData' is not an object or function.`);\n }\n\n if (!isObject(toData) && typeof toData !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: 'toData' is not an object or function.`);\n }\n\n if (options !== void 0 && !isObject(options) && typeof options !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: 'options' is not an object or function.`);\n }\n\n /**\n * @type {AnimationControl[]}\n */\n const animationControls = [];\n\n let index = -1;\n let callbackOptions;\n\n const hasFromCallback = typeof fromData === 'function';\n const hasToCallback = typeof toData === 'function';\n const hasOptionCallback = typeof options === 'function';\n const hasCallback = hasFromCallback || hasToCallback || hasOptionCallback;\n\n if (hasCallback) { callbackOptions = { index, position: void 0, data: void 0 }; }\n\n let actualFromData = fromData;\n let actualToData = toData;\n let actualOptions = options;\n\n if (isIterable(position))\n {\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.fromTo warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n }\n\n if (hasFromCallback)\n {\n actualFromData = fromData(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualFromData === null || actualFromData === void 0) { continue; }\n\n if (typeof actualFromData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: fromData callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n if (hasToCallback)\n {\n actualToData = toData(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualToData === null || actualToData === void 0) { continue; }\n\n if (typeof actualToData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: toData callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualOptions === null || actualOptions === void 0) { continue; }\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.fromTo error: options callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.fromTo(actualFromData, actualToData, actualOptions));\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.fromTo warning: No Position instance found.`);\n return AnimationGroupControl.voidControl;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n }\n\n if (hasFromCallback)\n {\n actualFromData = fromData(callbackOptions);\n\n if (typeof actualFromData !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.fromTo error: fromData callback function failed to return an object.`);\n }\n }\n\n if (hasToCallback)\n {\n actualToData = toData(callbackOptions);\n\n if (typeof actualToData !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.fromTo error: toData callback function failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.fromTo error: options callback function failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.fromTo(actualFromData, actualToData, actualOptions));\n }\n\n return new AnimationGroupControl(animationControls);\n }\n\n /**\n * Provides the `to` animation tween for one or more Position instances as a group.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n *\n * @param {object|Function} toData -\n *\n * @param {object|Function} options -\n *\n * @returns {TJSBasicAnimation} Basic animation control.\n */\n static to(position, toData, options)\n {\n if (!isObject(toData) && typeof toData !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.to error: 'toData' is not an object or function.`);\n }\n\n if (options !== void 0 && !isObject(options) && typeof options !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.to error: 'options' is not an object or function.`);\n }\n\n /**\n * @type {AnimationControl[]}\n */\n const animationControls = [];\n\n let index = -1;\n let callbackOptions;\n\n const hasDataCallback = typeof toData === 'function';\n const hasOptionCallback = typeof options === 'function';\n const hasCallback = hasDataCallback || hasOptionCallback;\n\n if (hasCallback) { callbackOptions = { index, position: void 0, data: void 0 }; }\n\n let actualToData = toData;\n let actualOptions = options;\n\n if (isIterable(position))\n {\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.to warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n }\n\n if (hasDataCallback)\n {\n actualToData = toData(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualToData === null || actualToData === void 0) { continue; }\n\n if (typeof actualToData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.to error: toData callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualOptions === null || actualOptions === void 0) { continue; }\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.to error: options callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.to(actualToData, actualOptions));\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.to warning: No Position instance found.`);\n return AnimationGroupControl.voidControl;\n }\n\n if (hasCallback)\n {\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n }\n\n if (hasDataCallback)\n {\n actualToData = toData(callbackOptions);\n\n if (typeof actualToData !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.to error: toData callback function failed to return an object.`);\n }\n }\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.to error: options callback function failed to return an object.`);\n }\n }\n\n animationControls.push(actualPosition.animate.to(actualToData, actualOptions));\n }\n\n return new AnimationGroupControl(animationControls);\n }\n\n /**\n * Provides the `to` animation tween for one or more Position instances as a group.\n *\n * @param {Position|{position: Position}|Iterable|Iterable<{position: Position}>} position -\n *\n * @param {Iterable} keys -\n *\n * @param {object|Function} options -\n *\n * @returns {quickToCallback} Basic animation control.\n */\n static quickTo(position, keys, options)\n {\n if (!isIterable(keys))\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: 'keys' is not an iterable list.`);\n }\n\n if (options !== void 0 && !isObject(options) && typeof options !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: 'options' is not an object or function.`);\n }\n\n /**\n * @type {quickToCallback[]}\n */\n const quickToCallbacks = [];\n\n let index = -1;\n\n const hasOptionCallback = typeof options === 'function';\n\n const callbackOptions = { index, position: void 0, data: void 0 };\n\n let actualOptions = options;\n\n if (isIterable(position))\n {\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.quickTo warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualOptions === null || actualOptions === void 0) { continue; }\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: options callback function iteration(${\n index}) failed to return an object.`);\n }\n }\n\n quickToCallbacks.push(actualPosition.animate.quickTo(keys, actualOptions));\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.quickTo warning: No Position instance found.`);\n return () => null;\n }\n\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n\n if (hasOptionCallback)\n {\n actualOptions = options(callbackOptions);\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.quickTo error: options callback function failed to return an object.`);\n }\n }\n\n quickToCallbacks.push(actualPosition.animate.quickTo(keys, actualOptions));\n }\n\n const keysArray = [...keys];\n\n Object.freeze(keysArray);\n\n const quickToCB = (...args) =>\n {\n const argsLength = args.length;\n\n if (argsLength === 0) { return; }\n\n if (typeof args[0] === 'function')\n {\n const dataCallback = args[0];\n\n index = -1;\n let cntr = 0;\n\n if (isIterable(position))\n {\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition)) { continue; }\n\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n\n const toData = dataCallback(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (toData === null || toData === void 0) { continue; }\n\n /**\n * @type {boolean}\n */\n const toDataIterable = isIterable(toData);\n\n if (!Number.isFinite(toData) && !toDataIterable && typeof toData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: toData callback function iteration(${\n index}) failed to return a finite number, iterable list, or object.`);\n }\n\n if (toDataIterable)\n {\n quickToCallbacks[cntr++](...toData);\n }\n else\n {\n quickToCallbacks[cntr++](toData);\n }\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition)) { return; }\n\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n\n const toData = dataCallback(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (toData === null || toData === void 0) { return; }\n\n const toDataIterable = isIterable(toData);\n\n if (!Number.isFinite(toData) && !toDataIterable && typeof toData !== 'object')\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: toData callback function iteration(${\n index}) failed to return a finite number, iterable list, or object.`);\n }\n\n if (toDataIterable)\n {\n quickToCallbacks[cntr++](...toData);\n }\n else\n {\n quickToCallbacks[cntr++](toData);\n }\n }\n }\n else\n {\n for (let cntr = quickToCallbacks.length; --cntr >= 0;)\n {\n quickToCallbacks[cntr](...args);\n }\n }\n };\n\n quickToCB.keys = keysArray;\n\n /**\n * Sets options of quickTo tween.\n *\n * @param {object|Function} [options] - Optional parameters.\n *\n * @param {number} [options.duration] - Duration in seconds.\n *\n * @param {Function} [options.ease] - Easing function.\n *\n * @param {Function} [options.interpolate] - Interpolation function.\n *\n * @returns {quickToCallback} The quickTo callback.\n */\n quickToCB.options = (options) => // eslint-disable-line no-shadow\n {\n if (options !== void 0 && !isObject(options) && typeof options !== 'function')\n {\n throw new TypeError(`AnimationGroupAPI.quickTo error: 'options' is not an object or function.`);\n }\n\n // Set options object for each quickTo callback.\n if (isObject(options))\n {\n for (let cntr = quickToCallbacks.length; --cntr >= 0;) { quickToCallbacks[cntr].options(options); }\n }\n else if (typeof options === 'function')\n {\n if (isIterable(position))\n {\n index = -1;\n let cntr = 0;\n\n for (const entry of position)\n {\n index++;\n\n const isPosition = this.#isPosition(entry);\n const actualPosition = isPosition ? entry : entry.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(\n `AnimationGroupAPI.quickTo.options warning: No Position instance found at index: ${index}.`);\n continue;\n }\n\n callbackOptions.index = index;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : entry;\n\n actualOptions = options(callbackOptions);\n\n // Returned data from callback is null / undefined, so skip this position instance.\n if (actualOptions === null || actualOptions === void 0) { continue; }\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.quickTo.options error: options callback function iteration(${\n index}) failed to return an object.`);\n }\n\n quickToCallbacks[cntr++].options(actualOptions);\n }\n }\n else\n {\n const isPosition = this.#isPosition(position);\n const actualPosition = isPosition ? position : position.position;\n\n if (!this.#isPosition(actualPosition))\n {\n console.warn(`AnimationGroupAPI.quickTo.options warning: No Position instance found.`);\n return quickToCB;\n }\n\n callbackOptions.index = 0;\n callbackOptions.position = position;\n callbackOptions.data = isPosition ? void 0 : position;\n\n actualOptions = options(callbackOptions);\n\n if (typeof actualOptions !== 'object')\n {\n throw new TypeError(\n `AnimationGroupAPI.quickTo error: options callback function failed to return an object.`);\n }\n\n quickToCallbacks[0].options(actualOptions);\n }\n }\n\n return quickToCB;\n };\n\n return quickToCB;\n }\n}\n","export class Centered\n{\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * Provides a manual setting of the element height. As things go `offsetHeight` causes a browser layout and is not\n * performance oriented. If manually set this height is used instead of `offsetHeight`.\n *\n * @type {number}\n */\n #height;\n\n /**\n * Set from an optional value in the constructor to lock accessors preventing modification.\n */\n #lock;\n\n /**\n * Provides a manual setting of the element width. As things go `offsetWidth` causes a browser layout and is not\n * performance oriented. If manually set this width is used instead of `offsetWidth`.\n *\n * @type {number}\n */\n #width;\n\n constructor({ element, lock = false, width, height } = {})\n {\n this.element = element;\n this.width = width;\n this.height = height;\n\n this.#lock = typeof lock === 'boolean' ? lock : false;\n }\n\n get element() { return this.#element; }\n\n get height() { return this.#height; }\n\n get width() { return this.#width; }\n\n set element(element)\n {\n if (this.#lock) { return; }\n\n if (element === void 0 || element === null || element instanceof HTMLElement)\n {\n this.#element = element;\n }\n else\n {\n throw new TypeError(`'element' is not a HTMLElement, undefined, or null.`);\n }\n }\n\n set height(height)\n {\n if (this.#lock) { return; }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n set width(width)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n }\n\n setDimension(width, height)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n getLeft(width)\n {\n // Determine containing bounds from manual values; or any element; lastly the browser width / height.\n const boundsWidth = this.#width ?? this.#element?.offsetWidth ?? globalThis.innerWidth;\n\n return (boundsWidth - width) / 2;\n }\n\n getTop(height)\n {\n const boundsHeight = this.#height ?? this.#element?.offsetHeight ?? globalThis.innerHeight;\n\n return (boundsHeight - height) / 2;\n }\n}\n","import { Centered } from './Centered.js';\n\nconst browserCentered = new Centered();\n\nexport { browserCentered, Centered };\n\n","export class PositionChangeSet\n{\n constructor()\n {\n this.left = false;\n this.top = false;\n this.width = false;\n this.height = false;\n this.maxHeight = false;\n this.maxWidth = false;\n this.minHeight = false;\n this.minWidth = false;\n this.zIndex = false;\n this.transform = false;\n this.transformOrigin = false;\n }\n\n hasChange()\n {\n return this.left || this.top || this.width || this.height || this.maxHeight || this.maxWidth || this.minHeight ||\n this.minWidth || this.zIndex || this.transform || this.transformOrigin;\n }\n\n set(value)\n {\n this.left = value;\n this.top = value;\n this.width = value;\n this.height = value;\n this.maxHeight = value;\n this.maxWidth = value;\n this.minHeight = value;\n this.minWidth = value;\n this.zIndex = value;\n this.transform = value;\n this.transformOrigin = value;\n }\n}\n","/**\n * Defines stored positional data.\n */\nexport class PositionData\n{\n constructor({ height = null, left = null, maxHeight = null, maxWidth = null, minHeight = null, minWidth = null,\n rotateX = null, rotateY = null, rotateZ = null, scale = null, translateX = null, translateY = null,\n translateZ = null, top = null, transformOrigin = null, width = null, zIndex = null } = {})\n {\n /**\n * @type {number|'auto'|'inherit'|null}\n */\n this.height = height;\n\n /**\n * @type {number|null}\n */\n this.left = left;\n\n /**\n * @type {number|null}\n */\n this.maxHeight = maxHeight;\n\n /**\n * @type {number|null}\n */\n this.maxWidth = maxWidth;\n\n /**\n * @type {number|null}\n */\n this.minHeight = minHeight;\n\n /**\n * @type {number|null}\n */\n this.minWidth = minWidth;\n\n /**\n * @type {number|null}\n */\n this.rotateX = rotateX;\n\n /**\n * @type {number|null}\n */\n this.rotateY = rotateY;\n\n /**\n * @type {number|null}\n */\n this.rotateZ = rotateZ;\n\n /**\n * @type {number|null}\n */\n this.scale = scale;\n\n /**\n * @type {number|null}\n */\n this.top = top;\n\n /**\n * @type {string|null}\n */\n this.transformOrigin = transformOrigin;\n\n /**\n * @type {number|null}\n */\n this.translateX = translateX;\n\n /**\n * @type {number|null}\n */\n this.translateY = translateY;\n\n /**\n * @type {number|null}\n */\n this.translateZ = translateZ;\n\n /**\n * @type {number|'auto'|'inherit'|null}\n */\n this.width = width;\n\n /**\n * @type {number|null}\n */\n this.zIndex = zIndex;\n\n Object.seal(this);\n }\n\n /**\n * Copies given data to this instance.\n *\n * @param {PositionData} data - Copy from this instance.\n *\n * @returns {PositionData} This instance.\n */\n copy(data)\n {\n this.height = data.height;\n this.left = data.left;\n this.maxHeight = data.maxHeight;\n this.maxWidth = data.maxWidth;\n this.minHeight = data.minHeight;\n this.minWidth = data.minWidth;\n this.rotateX = data.rotateX;\n this.rotateY = data.rotateY;\n this.rotateZ = data.rotateZ;\n this.scale = data.scale;\n this.top = data.top;\n this.transformOrigin = data.transformOrigin;\n this.translateX = data.translateX;\n this.translateY = data.translateY;\n this.translateZ = data.translateZ;\n this.width = data.width;\n this.zIndex = data.zIndex;\n\n return this;\n }\n}\n","import { linear } from 'svelte/easing';\n\nimport { lerp } from '@typhonjs-fvtt/runtime/svelte/math';\nimport { isIterable } from '@typhonjs-fvtt/runtime/svelte/util';\n\nexport class PositionStateAPI\n{\n /** @type {PositionData} */\n #data;\n\n /**\n * @type {Map}\n */\n #dataSaved = new Map();\n\n /** @type {Position} */\n #position;\n\n /** @type {Transforms} */\n #transforms;\n\n constructor(position, data, transforms)\n {\n this.#position = position;\n this.#data = data;\n this.#transforms = transforms;\n }\n\n /**\n * Returns any stored save state by name.\n *\n * @param {string} name - Saved data set name.\n *\n * @returns {PositionDataExtended} The saved data set.\n */\n get({ name })\n {\n if (typeof name !== 'string') { throw new TypeError(`Position - getSave error: 'name' is not a string.`); }\n\n return this.#dataSaved.get(name);\n }\n\n /**\n * Returns any associated default data.\n *\n * @returns {PositionDataExtended} Associated default data.\n */\n getDefault()\n {\n return this.#dataSaved.get('#defaultData');\n }\n\n /**\n * Removes and returns any position state by name.\n *\n * @param {object} options - Options.\n *\n * @param {string} options.name - Name to remove and retrieve.\n *\n * @returns {PositionDataExtended} Saved position data.\n */\n remove({ name })\n {\n if (typeof name !== 'string') { throw new TypeError(`Position - remove: 'name' is not a string.`); }\n\n const data = this.#dataSaved.get(name);\n this.#dataSaved.delete(name);\n\n return data;\n }\n\n /**\n * Resets data to default values and invokes set.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {boolean} [opts.keepZIndex=false] - When true keeps current z-index.\n *\n * @param {boolean} [opts.invokeSet=true] - When true invokes set method.\n *\n * @returns {boolean} Operation successful.\n */\n reset({ keepZIndex = false, invokeSet = true } = {})\n {\n const defaultData = this.#dataSaved.get('#defaultData');\n\n // Quit early if there is no saved default data.\n if (typeof defaultData !== 'object') { return false; }\n\n // Cancel all animations for Position if there are currently any scheduled.\n if (this.#position.animate.isScheduled)\n {\n this.#position.animate.cancel();\n }\n\n const zIndex = this.#position.zIndex;\n\n const data = Object.assign({}, defaultData);\n\n if (keepZIndex) { data.zIndex = zIndex; }\n\n // Reset the transform data.\n this.#transforms.reset(data);\n\n // If current minimized invoke `maximize`.\n if (this.#position.parent?.reactive?.minimized)\n {\n this.#position.parent?.maximize?.({ animate: false, duration: 0 });\n }\n\n // Note next clock tick scheduling.\n if (invokeSet) { setTimeout(() => this.#position.set(data), 0); }\n\n return true;\n }\n\n /**\n * Restores a saved positional state returning the data. Several optional parameters are available\n * to control whether the restore action occurs silently (no store / inline styles updates), animates\n * to the stored data, or simply sets the stored data. Restoring via {@link AnimationAPI.to} allows\n * specification of the duration, easing, and interpolate functions along with configuring a Promise to be\n * returned if awaiting the end of the animation.\n *\n * @param {object} params - Parameters\n *\n * @param {string} params.name - Saved data set name.\n *\n * @param {boolean} [params.remove=false] - Remove data set.\n *\n * @param {Iterable} [params.properties] - Specific properties to set / animate.\n *\n * @param {boolean} [params.silent] - Set position data directly; no store or style updates.\n *\n * @param {boolean} [params.async=false] - If animating return a Promise that resolves with any saved data.\n *\n * @param {boolean} [params.animateTo=false] - Animate to restore data.\n *\n * @param {number} [params.duration=0.1] - Duration in seconds.\n *\n * @param {Function} [params.ease=linear] - Easing function.\n *\n * @param {Function} [params.interpolate=lerp] - Interpolation function.\n *\n * @returns {PositionDataExtended|Promise} Saved position data.\n */\n restore({ name, remove = false, properties, silent = false, async = false, animateTo = false, duration = 0.1,\n ease = linear, interpolate = lerp })\n {\n if (typeof name !== 'string') { throw new TypeError(`Position - restore error: 'name' is not a string.`); }\n\n const dataSaved = this.#dataSaved.get(name);\n\n if (dataSaved)\n {\n if (remove) { this.#dataSaved.delete(name); }\n\n let data = dataSaved;\n\n if (isIterable(properties))\n {\n data = {};\n for (const property of properties) { data[property] = dataSaved[property]; }\n }\n\n // Update data directly with no store or inline style updates.\n if (silent)\n {\n for (const property in data) { this.#data[property] = data[property]; }\n return dataSaved;\n }\n else if (animateTo) // Animate to saved data.\n {\n // Provide special handling to potentially change transform origin as this parameter is not animated.\n if (data.transformOrigin !== this.#position.transformOrigin)\n {\n this.#position.transformOrigin = data.transformOrigin;\n }\n\n // Return a Promise with saved data that resolves after animation ends.\n if (async)\n {\n return this.#position.animate.to(data, { duration, ease, interpolate }).finished.then(() => dataSaved);\n }\n else // Animate synchronously.\n {\n this.#position.animate.to(data, { duration, ease, interpolate });\n }\n }\n else\n {\n // Default options is to set data for an immediate update.\n this.#position.set(data);\n }\n }\n\n return dataSaved;\n }\n\n /**\n * Saves current position state with the opportunity to add extra data to the saved state.\n *\n * @param {object} opts - Options.\n *\n * @param {string} opts.name - name to index this saved data.\n *\n * @param {...*} [opts.extra] - Extra data to add to saved data.\n *\n * @returns {PositionData} Current position data\n */\n save({ name, ...extra })\n {\n if (typeof name !== 'string') { throw new TypeError(`Position - save error: 'name' is not a string.`); }\n\n const data = this.#position.get(extra);\n\n this.#dataSaved.set(name, data);\n\n return data;\n }\n\n /**\n * Directly sets a position state.\n *\n * @param {object} opts - Options.\n *\n * @param {string} opts.name - name to index this saved data.\n *\n * @param {...*} [opts.data] - Position data to set.\n */\n set({ name, ...data })\n {\n if (typeof name !== 'string') { throw new TypeError(`Position - set error: 'name' is not a string.`); }\n\n this.#dataSaved.set(name, data);\n }\n}\n","import { writable } from 'svelte/store';\n\nimport { propertyStore } from '@typhonjs-fvtt/runtime/svelte/store';\nimport { styleParsePixels } from '@typhonjs-fvtt/runtime/svelte/util';\n\nexport class StyleCache\n{\n constructor()\n {\n /** @type {HTMLElement|undefined} */\n this.el = void 0;\n\n /** @type {CSSStyleDeclaration} */\n this.computed = void 0;\n\n /** @type {number|undefined} */\n this.marginLeft = void 0;\n\n /** @type {number|undefined} */\n this.marginTop = void 0;\n\n /** @type {number|undefined} */\n this.maxHeight = void 0;\n\n /** @type {number|undefined} */\n this.maxWidth = void 0;\n\n /** @type {number|undefined} */\n this.minHeight = void 0;\n\n /** @type {number|undefined} */\n this.minWidth = void 0;\n\n /** @type {boolean} */\n this.hasWillChange = false;\n\n /**\n * @type {ResizeObserverData}\n */\n this.resizeObserved = {\n contentHeight: void 0,\n contentWidth: void 0,\n offsetHeight: void 0,\n offsetWidth: void 0\n };\n\n /**\n * Provides a writable store to track offset & content width / height from an associated `resizeObserver` action.\n *\n * @type {Writable}\n */\n const storeResizeObserved = writable(this.resizeObserved);\n\n this.stores = {\n element: writable(this.el),\n resizeContentHeight: propertyStore(storeResizeObserved, 'contentHeight'),\n resizeContentWidth: propertyStore(storeResizeObserved, 'contentWidth'),\n resizeObserved: storeResizeObserved,\n resizeOffsetHeight: propertyStore(storeResizeObserved, 'offsetHeight'),\n resizeOffsetWidth: propertyStore(storeResizeObserved, 'offsetWidth')\n };\n }\n\n /**\n * Returns the cached offsetHeight from any attached `resizeObserver` action otherwise gets the offsetHeight from\n * the element directly. The more optimized path is using `resizeObserver` as getting it from the element\n * directly is more expensive and alters the execution order of an animation frame.\n *\n * @returns {number} The element offsetHeight.\n */\n get offsetHeight()\n {\n if (this.el instanceof HTMLElement)\n {\n return this.resizeObserved.offsetHeight !== void 0 ? this.resizeObserved.offsetHeight : this.el.offsetHeight;\n }\n\n throw new Error(`StyleCache - get offsetHeight error: no element assigned.`);\n }\n\n /**\n * Returns the cached offsetWidth from any attached `resizeObserver` action otherwise gets the offsetWidth from\n * the element directly. The more optimized path is using `resizeObserver` as getting it from the element\n * directly is more expensive and alters the execution order of an animation frame.\n *\n * @returns {number} The element offsetHeight.\n */\n get offsetWidth()\n {\n if (this.el instanceof HTMLElement)\n {\n return this.resizeObserved.offsetWidth !== void 0 ? this.resizeObserved.offsetWidth : this.el.offsetWidth;\n }\n\n throw new Error(`StyleCache - get offsetWidth error: no element assigned.`);\n }\n\n /**\n * @param {HTMLElement} el -\n *\n * @returns {boolean} Does element match cached element.\n */\n hasData(el) { return this.el === el; }\n\n /**\n * Resets the style cache.\n */\n reset()\n {\n // Remove will-change inline style from previous element if it is still connected.\n if (this.el instanceof HTMLElement && this.el.isConnected && !this.hasWillChange)\n {\n this.el.style.willChange = null;\n }\n\n this.el = void 0;\n this.computed = void 0;\n this.marginLeft = void 0;\n this.marginTop = void 0;\n this.maxHeight = void 0;\n this.maxWidth = void 0;\n this.minHeight = void 0;\n this.minWidth = void 0;\n\n this.hasWillChange = false;\n\n // Silently reset `resizedObserved`; With proper usage the `resizeObserver` action issues an update on removal.\n this.resizeObserved.contentHeight = void 0;\n this.resizeObserved.contentWidth = void 0;\n this.resizeObserved.offsetHeight = void 0;\n this.resizeObserved.offsetWidth = void 0;\n\n // Reset the tracked element this Position instance is modifying.\n this.stores.element.set(void 0);\n }\n\n /**\n * Updates the style cache with new data from the given element.\n *\n * @param {HTMLElement} el - An HTML element.\n */\n update(el)\n {\n this.el = el;\n\n this.computed = globalThis.getComputedStyle(el);\n\n this.marginLeft = styleParsePixels(el.style.marginLeft) ?? styleParsePixels(this.computed.marginLeft);\n this.marginTop = styleParsePixels(el.style.marginTop) ?? styleParsePixels(this.computed.marginTop);\n this.maxHeight = styleParsePixels(el.style.maxHeight) ?? styleParsePixels(this.computed.maxHeight);\n this.maxWidth = styleParsePixels(el.style.maxWidth) ?? styleParsePixels(this.computed.maxWidth);\n\n // Note that the computed styles for below will always be 0px / 0 when no style is active.\n this.minHeight = styleParsePixels(el.style.minHeight) ?? styleParsePixels(this.computed.minHeight);\n this.minWidth = styleParsePixels(el.style.minWidth) ?? styleParsePixels(this.computed.minWidth);\n\n // Tracks if there already is a will-change property on the inline or computed styles.\n const willChange = el.style.willChange !== '' ? el.style.willChange : void 0 ?? this.computed.willChange;\n\n this.hasWillChange = willChange !== '' && willChange !== 'auto';\n\n // Update the tracked element this Position instance is modifying.\n this.stores.element.set(el);\n }\n}\n","import { mat4, vec3 } from '@typhonjs-fvtt/runtime/svelte/math';\n\n/**\n * Provides the output data for {@link Transforms.getData}.\n */\nexport class TransformData\n{\n constructor()\n {\n Object.seal(this);\n }\n\n /**\n * Stores the calculated bounding rectangle.\n *\n * @type {DOMRect}\n */\n #boundingRect = new DOMRect();\n\n /**\n * Stores the individual transformed corner points of the window in screenspace clockwise from:\n * top left -> top right -> bottom right -> bottom left.\n *\n * @type {Vector3[]}\n */\n #corners = [vec3.create(), vec3.create(), vec3.create(), vec3.create()];\n\n /**\n * Stores the current gl-matrix mat4 data.\n *\n * @type {Matrix4}\n */\n #mat4 = mat4.create();\n\n /**\n * Stores the pre & post origin translations to apply to matrix transforms.\n *\n * @type {Matrix4[]}\n */\n #originTranslations = [mat4.create(), mat4.create()];\n\n /**\n * @returns {DOMRect} The bounding rectangle.\n */\n get boundingRect() { return this.#boundingRect; }\n\n /**\n * @returns {Vector3[]} The transformed corner points as vec3 in screen space.\n */\n get corners() { return this.#corners; }\n\n /**\n * @returns {string} Returns the CSS style string for the transform matrix.\n */\n get css() { return `matrix3d(${this.mat4.join(',')})`; }\n\n /**\n * @returns {Matrix4} The transform matrix.\n */\n get mat4() { return this.#mat4; }\n\n /**\n * @returns {Matrix4[]} The pre / post translation matrices for origin translation.\n */\n get originTranslations() { return this.#originTranslations; }\n}\n\n/**\n * @typedef {Float32Array} Vector3 - 3 Dimensional Vector.\n *\n * @see https://glmatrix.net/docs/module-vec3.html\n */\n\n/**\n * @typedef {Float32Array} Matrix4 - 4x4 Matrix; Format: column-major, when typed out it looks like row-major.\n *\n * @see https://glmatrix.net/docs/module-mat4.html\n */\n","/**\n * Provides the storage and sequencing of managed position validators. Each validator added may be a bespoke function or\n * a {@link ValidatorData} object containing an `id`, `validator`, and `weight` attributes; `validator` is the only\n * required attribute.\n *\n * The `id` attribute can be anything that creates a unique ID for the validator; recommended strings or numbers. This\n * allows validators to be removed by ID easily.\n *\n * The `weight` attribute is a number between 0 and 1 inclusive that allows validators to be added in a\n * predictable order which is especially handy if they are manipulated at runtime. A lower weighted validator always\n * runs before a higher weighted validator. If no weight is specified the default of '1' is assigned and it is appended\n * to the end of the validators list.\n *\n * This class forms the public API which is accessible from the `.validators` getter in the main Position instance.\n * ```\n * const position = new Position();\n * position.validators.add(...);\n * position.validators.clear();\n * position.validators.length;\n * position.validators.remove(...);\n * position.validators.removeBy(...);\n * position.validators.removeById(...);\n * ```\n */\nexport class AdapterValidators\n{\n /**\n * @type {ValidatorData[]}\n */\n #validatorData;\n\n #mapUnsubscribe = new Map();\n\n /**\n * @returns {[AdapterValidators, ValidatorData[]]} Returns this and internal storage for validator adapter.\n */\n constructor()\n {\n this.#validatorData = [];\n\n Object.seal(this);\n\n return [this, this.#validatorData];\n }\n\n /**\n * @returns {number} Returns the length of the validators array.\n */\n get length() { return this.#validatorData.length; }\n\n /**\n * Provides an iterator for validators.\n *\n * @returns {Generator} Generator / iterator of validators.\n * @yields {ValidatorData}\n */\n *[Symbol.iterator]()\n {\n if (this.#validatorData.length === 0) { return; }\n\n for (const entry of this.#validatorData)\n {\n yield { ...entry };\n }\n }\n\n /**\n * @param {...(ValidatorFn|ValidatorData)} validators -\n */\n add(...validators)\n {\n /**\n * Tracks the number of validators added that have subscriber functionality.\n *\n * @type {number}\n */\n let subscribeCount = 0;\n\n for (const validator of validators)\n {\n const validatorType = typeof validator;\n\n if (validatorType !== 'function' && validatorType !== 'object' || validator === null)\n {\n throw new TypeError(`AdapterValidator error: 'validator' is not a function or object.`);\n }\n\n let data = void 0;\n let subscribeFn = void 0;\n\n switch (validatorType)\n {\n case 'function':\n data = {\n id: void 0,\n validator,\n weight: 1\n };\n\n subscribeFn = validator.subscribe;\n break;\n\n case 'object':\n if (typeof validator.validator !== 'function')\n {\n throw new TypeError(`AdapterValidator error: 'validator' attribute is not a function.`);\n }\n\n if (validator.weight !== void 0 && typeof validator.weight !== 'number' ||\n (validator.weight < 0 || validator.weight > 1))\n {\n throw new TypeError(\n `AdapterValidator error: 'weight' attribute is not a number between '0 - 1' inclusive.`);\n }\n\n data = {\n id: validator.id !== void 0 ? validator.id : void 0,\n validator: validator.validator.bind(validator),\n weight: validator.weight || 1,\n instance: validator\n };\n\n subscribeFn = validator.validator.subscribe ?? validator.subscribe;\n break;\n }\n\n // Find the index to insert where data.weight is less than existing values weight.\n const index = this.#validatorData.findIndex((value) =>\n {\n return data.weight < value.weight;\n });\n\n // If an index was found insert at that location.\n if (index >= 0)\n {\n this.#validatorData.splice(index, 0, data);\n }\n else // push to end of validators.\n {\n this.#validatorData.push(data);\n }\n\n if (typeof subscribeFn === 'function')\n {\n // TODO: consider how to handle validator updates.\n const unsubscribe = subscribeFn();\n\n // Ensure that unsubscribe is a function.\n if (typeof unsubscribe !== 'function')\n {\n throw new TypeError(\n 'AdapterValidator error: Filter has subscribe function, but no unsubscribe function is returned.');\n }\n\n // Ensure that the same validator is not subscribed to multiple times.\n if (this.#mapUnsubscribe.has(data.validator))\n {\n throw new Error(\n 'AdapterValidator error: Filter added already has an unsubscribe function registered.');\n }\n\n this.#mapUnsubscribe.set(data.validator, unsubscribe);\n subscribeCount++;\n }\n }\n\n // Filters with subscriber functionality are assumed to immediately invoke the `subscribe` callback. If the\n // subscriber count is less than the amount of validators added then automatically trigger an index update\n // manually.\n // TODO: handle validator updates.\n // if (subscribeCount < validators.length) { this.#indexUpdate(); }\n }\n\n clear()\n {\n this.#validatorData.length = 0;\n\n // Unsubscribe from all validators with subscription support.\n for (const unsubscribe of this.#mapUnsubscribe.values())\n {\n unsubscribe();\n }\n\n this.#mapUnsubscribe.clear();\n\n // TODO: handle validator updates.\n // this.#indexUpdate();\n }\n\n /**\n * @param {...(ValidatorFn|ValidatorData)} validators -\n */\n remove(...validators)\n {\n const length = this.#validatorData.length;\n\n if (length === 0) { return; }\n\n for (const data of validators)\n {\n // Handle the case that the validator may either be a function or a validator entry / object.\n const actualValidator = typeof data === 'function' ? data : data !== null && typeof data === 'object' ?\n data.validator : void 0;\n\n if (!actualValidator) { continue; }\n\n for (let cntr = this.#validatorData.length; --cntr >= 0;)\n {\n if (this.#validatorData[cntr].validator === actualValidator)\n {\n this.#validatorData.splice(cntr, 1);\n\n // Invoke any unsubscribe function for given validator then remove from tracking.\n let unsubscribe = void 0;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(actualValidator)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(actualValidator);\n }\n }\n }\n }\n\n // Update the index a validator was removed.\n // TODO: handle validator updates.\n // if (length !== this.#validatorData.length) { this.#indexUpdate(); }\n }\n\n /**\n * Remove validators by the provided callback. The callback takes 3 parameters: `id`, `validator`, and `weight`.\n * Any truthy value returned will remove that validator.\n *\n * @param {function(*, ValidatorFn, number): boolean} callback - Callback function to evaluate each validator\n * entry.\n */\n removeBy(callback)\n {\n const length = this.#validatorData.length;\n\n if (length === 0) { return; }\n\n if (typeof callback !== 'function')\n {\n throw new TypeError(`AdapterValidator error: 'callback' is not a function.`);\n }\n\n this.#validatorData = this.#validatorData.filter((data) =>\n {\n const remove = callback.call(callback, { ...data });\n\n if (remove)\n {\n let unsubscribe;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(data.validator)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(data.validator);\n }\n }\n\n // Reverse remove boolean to properly validator / remove this validator.\n return !remove;\n });\n\n // TODO: handle validator updates.\n // if (length !== this.#validatorData.length) { this.#indexUpdate(); }\n }\n\n removeById(...ids)\n {\n const length = this.#validatorData.length;\n\n if (length === 0) { return; }\n\n this.#validatorData = this.#validatorData.filter((data) =>\n {\n let remove = false;\n\n for (const id of ids) { remove |= data.id === id; }\n\n // If not keeping invoke any unsubscribe function for given validator then remove from tracking.\n if (remove)\n {\n let unsubscribe;\n if (typeof (unsubscribe = this.#mapUnsubscribe.get(data.validator)) === 'function')\n {\n unsubscribe();\n this.#mapUnsubscribe.delete(data.validator);\n }\n }\n\n return !remove; // Swap here to actually remove the item via array validator method.\n });\n\n // TODO: handle validator updates.\n // if (length !== this.#validatorData.length) { this.#indexUpdate(); }\n }\n}\n\n/**\n * @callback ValidatorFn - Position validator function that takes a {@link PositionData} instance potentially\n * modifying it or returning null if invalid.\n *\n * @param {ValidationData} valData - Validation data.\n *\n * @returns {PositionData|null} The validated position data or null to cancel position update.\n *\n */\n\n/**\n * @typedef {object} ValidatorData\n *\n * @property {*} [id=undefined] - An ID associated with this validator. Can be used to remove the validator.\n *\n * @property {ValidatorFn} validator - Position validator function that takes a {@link PositionData} instance\n * potentially modifying it or returning null if invalid.\n *\n * @property {number} [weight=1] - A number between 0 and 1 inclusive to position this validator against others.\n *\n * @property {Function} [subscribe] - Optional subscribe function following the Svelte store / subscribe pattern.\n */\n","export class BasicBounds\n{\n /**\n * When true constrains the min / max width or height to element.\n *\n * @type {boolean}\n */\n #constrain;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * When true the validator is active.\n *\n * @type {boolean}\n */\n #enabled;\n\n /**\n * Provides a manual setting of the element height. As things go `offsetHeight` causes a browser layout and is not\n * performance oriented. If manually set this height is used instead of `offsetHeight`.\n *\n * @type {number}\n */\n #height;\n\n /**\n * Set from an optional value in the constructor to lock accessors preventing modification.\n */\n #lock;\n\n /**\n * Provides a manual setting of the element width. As things go `offsetWidth` causes a browser layout and is not\n * performance oriented. If manually set this width is used instead of `offsetWidth`.\n *\n * @type {number}\n */\n #width;\n\n constructor({ constrain = true, element, enabled = true, lock = false, width, height } = {})\n {\n this.element = element;\n this.constrain = constrain;\n this.enabled = enabled;\n this.width = width;\n this.height = height;\n\n this.#lock = typeof lock === 'boolean' ? lock : false;\n }\n\n get constrain() { return this.#constrain; }\n\n get element() { return this.#element; }\n\n get enabled() { return this.#enabled; }\n\n get height() { return this.#height; }\n\n get width() { return this.#width; }\n\n set constrain(constrain)\n {\n if (this.#lock) { return; }\n\n if (typeof constrain !== 'boolean') { throw new TypeError(`'constrain' is not a boolean.`); }\n\n this.#constrain = constrain;\n }\n\n set element(element)\n {\n if (this.#lock) { return; }\n\n if (element === void 0 || element === null || element instanceof HTMLElement)\n {\n this.#element = element;\n }\n else\n {\n throw new TypeError(`'element' is not a HTMLElement, undefined, or null.`);\n }\n }\n\n set enabled(enabled)\n {\n if (this.#lock) { return; }\n\n if (typeof enabled !== 'boolean') { throw new TypeError(`'enabled' is not a boolean.`); }\n\n this.#enabled = enabled;\n }\n\n set height(height)\n {\n if (this.#lock) { return; }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n set width(width)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n }\n\n setDimension(width, height)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n /**\n * Provides a validator that respects transforms in positional data constraining the position to within the target\n * elements bounds.\n *\n * @param {ValidationData} valData - The associated validation data for position updates.\n *\n * @returns {PositionData} Potentially adjusted position data.\n */\n validator(valData)\n {\n // Early out if element is undefined or local enabled state is false.\n if (!this.#enabled) { return valData.position; }\n\n // Determine containing bounds from manual values; or any element; lastly the browser width / height.\n const boundsWidth = this.#width ?? this.#element?.offsetWidth ?? globalThis.innerWidth;\n const boundsHeight = this.#height ?? this.#element?.offsetHeight ?? globalThis.innerHeight;\n\n if (typeof valData.position.width === 'number')\n {\n const maxW = valData.maxWidth ?? (this.#constrain ? boundsWidth : Number.MAX_SAFE_INTEGER);\n valData.position.width = valData.width = Math.clamped(valData.position.width, valData.minWidth, maxW);\n\n if ((valData.width + valData.position.left + valData.marginLeft) > boundsWidth)\n {\n valData.position.left = boundsWidth - valData.width - valData.marginLeft;\n }\n }\n\n if (typeof valData.position.height === 'number')\n {\n const maxH = valData.maxHeight ?? (this.#constrain ? boundsHeight : Number.MAX_SAFE_INTEGER);\n valData.position.height = valData.height = Math.clamped(valData.position.height, valData.minHeight, maxH);\n\n if ((valData.height + valData.position.top + valData.marginTop) > boundsHeight)\n {\n valData.position.top = boundsHeight - valData.height - valData.marginTop;\n }\n }\n\n const maxL = Math.max(boundsWidth - valData.width - valData.marginLeft, 0);\n valData.position.left = Math.round(Math.clamped(valData.position.left, 0, maxL));\n\n const maxT = Math.max(boundsHeight - valData.height - valData.marginTop, 0);\n valData.position.top = Math.round(Math.clamped(valData.position.top, 0, maxT));\n\n return valData.position;\n }\n}\n","import { TransformData } from '../transform/TransformData.js';\n\nconst s_TRANSFORM_DATA = new TransformData();\n\nexport class TransformBounds\n{\n /**\n * When true constrains the min / max width or height to element.\n *\n * @type {boolean}\n */\n #constrain;\n\n /**\n * @type {HTMLElement}\n */\n #element;\n\n /**\n * When true the validator is active.\n *\n * @type {boolean}\n */\n #enabled;\n\n /**\n * Provides a manual setting of the element height. As things go `offsetHeight` causes a browser layout and is not\n * performance oriented. If manually set this height is used instead of `offsetHeight`.\n *\n * @type {number}\n */\n #height;\n\n /**\n * Set from an optional value in the constructor to lock accessors preventing modification.\n */\n #lock;\n\n /**\n * Provides a manual setting of the element width. As things go `offsetWidth` causes a browser layout and is not\n * performance oriented. If manually set this width is used instead of `offsetWidth`.\n *\n * @type {number}\n */\n #width;\n\n constructor({ constrain = true, element, enabled = true, lock = false, width, height } = {})\n {\n this.element = element;\n this.constrain = constrain;\n this.enabled = enabled;\n this.width = width;\n this.height = height;\n\n this.#lock = typeof lock === 'boolean' ? lock : false;\n }\n\n get constrain() { return this.#constrain; }\n\n get element() { return this.#element; }\n\n get enabled() { return this.#enabled; }\n\n get height() { return this.#height; }\n\n get width() { return this.#width; }\n\n set constrain(constrain)\n {\n if (this.#lock) { return; }\n\n if (typeof constrain !== 'boolean') { throw new TypeError(`'constrain' is not a boolean.`); }\n\n this.#constrain = constrain;\n }\n\n set element(element)\n {\n if (this.#lock) { return; }\n\n if (element === void 0 || element === null || element instanceof HTMLElement)\n {\n this.#element = element;\n }\n else\n {\n throw new TypeError(`'element' is not a HTMLElement, undefined, or null.`);\n }\n }\n\n set enabled(enabled)\n {\n if (this.#lock) { return; }\n\n if (typeof enabled !== 'boolean') { throw new TypeError(`'enabled' is not a boolean.`); }\n\n this.#enabled = enabled;\n }\n\n set height(height)\n {\n if (this.#lock) { return; }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n set width(width)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n }\n\n setDimension(width, height)\n {\n if (this.#lock) { return; }\n\n if (width === void 0 || Number.isFinite(width))\n {\n this.#width = width;\n }\n else\n {\n throw new TypeError(`'width' is not a finite number or undefined.`);\n }\n\n if (height === void 0 || Number.isFinite(height))\n {\n this.#height = height;\n }\n else\n {\n throw new TypeError(`'height' is not a finite number or undefined.`);\n }\n }\n\n /**\n * Provides a validator that respects transforms in positional data constraining the position to within the target\n * elements bounds.\n *\n * @param {ValidationData} valData - The associated validation data for position updates.\n *\n * @returns {PositionData} Potentially adjusted position data.\n */\n validator(valData)\n {\n // Early out if element is undefined or local enabled state is false.\n if (!this.#enabled) { return valData.position; }\n\n // Determine containing bounds from manual values; or any element; lastly the browser width / height.\n const boundsWidth = this.#width ?? this.#element?.offsetWidth ?? globalThis.innerWidth;\n const boundsHeight = this.#height ?? this.#element?.offsetHeight ?? globalThis.innerHeight;\n\n // Ensure min / max width constraints when position width is a number; not 'auto' or 'inherit'. If constrain is\n // true cap width bounds.\n if (typeof valData.position.width === 'number')\n {\n const maxW = valData.maxWidth ?? (this.#constrain ? boundsWidth : Number.MAX_SAFE_INTEGER);\n valData.position.width = Math.clamped(valData.width, valData.minWidth, maxW);\n }\n\n // Ensure min / max height constraints when position height is a number; not 'auto' or 'inherit'. If constrain\n // is true cap height bounds.\n if (typeof valData.position.height === 'number')\n {\n const maxH = valData.maxHeight ?? (this.#constrain ? boundsHeight : Number.MAX_SAFE_INTEGER);\n valData.position.height = Math.clamped(valData.height, valData.minHeight, maxH);\n }\n\n // Get transform data. First set constraints including any margin top / left as offsets and width / height. Used\n // when position width / height is 'auto'.\n const data = valData.transforms.getData(valData.position, s_TRANSFORM_DATA, valData);\n\n // Check the bounding rectangle against browser height / width. Adjust position based on how far the overlap of\n // the bounding rect is outside the bounds height / width. The order below matters as the constraints are top /\n // left oriented, so perform those checks last.\n\n const initialX = data.boundingRect.x;\n const initialY = data.boundingRect.y;\n\n if (data.boundingRect.bottom + valData.marginTop > boundsHeight)\n {\n data.boundingRect.y += boundsHeight - data.boundingRect.bottom - valData.marginTop;\n }\n\n if (data.boundingRect.right + valData.marginLeft > boundsWidth)\n {\n data.boundingRect.x += boundsWidth - data.boundingRect.right - valData.marginLeft;\n }\n\n if (data.boundingRect.top - valData.marginTop < 0)\n {\n data.boundingRect.y += Math.abs(data.boundingRect.top - valData.marginTop);\n }\n\n if (data.boundingRect.left - valData.marginLeft < 0)\n {\n data.boundingRect.x += Math.abs(data.boundingRect.left - valData.marginLeft);\n }\n\n valData.position.left -= initialX - data.boundingRect.x;\n valData.position.top -= initialY - data.boundingRect.y;\n\n return valData.position;\n }\n}\n","import { BasicBounds } from './BasicBounds.js';\nimport { TransformBounds } from './TransformBounds.js';\n\nconst basicWindow = new BasicBounds({ lock: true });\nconst transformWindow = new TransformBounds({ lock: true });\n\nexport { basicWindow, BasicBounds, transformWindow, TransformBounds };\n","import { degToRad, mat4, vec3 } from '@typhonjs-fvtt/runtime/svelte/math';\n\nimport * as constants from '../constants.js';\n\nimport { TransformData } from './TransformData.js';\n\n/** @type {number[]} */\nconst s_SCALE_VECTOR = [1, 1, 1];\n\n/** @type {number[]} */\nconst s_TRANSLATE_VECTOR = [0, 0, 0];\n\n/** @type {Matrix4} */\nconst s_MAT4_RESULT = mat4.create();\n\n/** @type {Matrix4} */\nconst s_MAT4_TEMP = mat4.create();\n\n/** @type {Vector3} */\nconst s_VEC3_TEMP = vec3.create();\n\nexport class Transforms\n{\n /**\n * Stores the transform keys in the order added.\n *\n * @type {string[]}\n */\n #orderList = [];\n\n constructor()\n {\n this._data = {};\n }\n\n /**\n * @returns {boolean} Whether there are active transforms in local data.\n */\n get isActive() { return this.#orderList.length > 0; }\n\n /**\n * @returns {number|undefined} Any local rotateX data.\n */\n get rotateX() { return this._data.rotateX; }\n\n /**\n * @returns {number|undefined} Any local rotateY data.\n */\n get rotateY() { return this._data.rotateY; }\n\n /**\n * @returns {number|undefined} Any local rotateZ data.\n */\n get rotateZ() { return this._data.rotateZ; }\n\n /**\n * @returns {number|undefined} Any local rotateZ scale.\n */\n get scale() { return this._data.scale; }\n\n /**\n * @returns {number|undefined} Any local translateZ data.\n */\n get translateX() { return this._data.translateX; }\n\n /**\n * @returns {number|undefined} Any local translateZ data.\n */\n get translateY() { return this._data.translateY; }\n\n /**\n * @returns {number|undefined} Any local translateZ data.\n */\n get translateZ() { return this._data.translateZ; }\n\n /**\n * Sets the local rotateX data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set rotateX(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.rotateX === void 0) { this.#orderList.push('rotateX'); }\n\n this._data.rotateX = value;\n }\n else\n {\n if (this._data.rotateX !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'rotateX');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.rotateX;\n }\n }\n\n /**\n * Sets the local rotateY data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set rotateY(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.rotateY === void 0) { this.#orderList.push('rotateY'); }\n\n this._data.rotateY = value;\n }\n else\n {\n if (this._data.rotateY !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'rotateY');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.rotateY;\n }\n }\n\n /**\n * Sets the local rotateZ data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set rotateZ(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.rotateZ === void 0) { this.#orderList.push('rotateZ'); }\n\n this._data.rotateZ = value;\n }\n\n else\n {\n if (this._data.rotateZ !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'rotateZ');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.rotateZ;\n }\n }\n\n /**\n * Sets the local scale data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set scale(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.scale === void 0) { this.#orderList.push('scale'); }\n\n this._data.scale = value;\n }\n else\n {\n if (this._data.scale !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'scale');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.scale;\n }\n }\n\n /**\n * Sets the local translateX data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set translateX(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.translateX === void 0) { this.#orderList.push('translateX'); }\n\n this._data.translateX = value;\n }\n\n else\n {\n if (this._data.translateX !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'translateX');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.translateX;\n }\n }\n\n /**\n * Sets the local translateY data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set translateY(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.translateY === void 0) { this.#orderList.push('translateY'); }\n\n this._data.translateY = value;\n }\n\n else\n {\n if (this._data.translateY !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'translateY');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.translateY;\n }\n }\n\n /**\n * Sets the local translateZ data if the value is a finite number otherwise removes the local data.\n *\n * @param {number|null|undefined} value - A value to set.\n */\n set translateZ(value)\n {\n if (Number.isFinite(value))\n {\n if (this._data.translateZ === void 0) { this.#orderList.push('translateZ'); }\n\n this._data.translateZ = value;\n }\n\n else\n {\n if (this._data.translateZ !== void 0)\n {\n const index = this.#orderList.findIndex((entry) => entry === 'translateZ');\n if (index >= 0) { this.#orderList.splice(index, 1); }\n }\n\n delete this._data.translateZ;\n }\n }\n\n /**\n * Returns the matrix3d CSS transform for the given position / transform data.\n *\n * @param {object} [data] - Optional position data otherwise use local stored transform data.\n *\n * @returns {string} The CSS matrix3d string.\n */\n getCSS(data = this._data)\n {\n return `matrix3d(${this.getMat4(data, s_MAT4_RESULT).join(',')})`;\n }\n\n /**\n * Returns the matrix3d CSS transform for the given position / transform data.\n *\n * @param {object} [data] - Optional position data otherwise use local stored transform data.\n *\n * @returns {string} The CSS matrix3d string.\n */\n getCSSOrtho(data = this._data)\n {\n return `matrix3d(${this.getMat4Ortho(data, s_MAT4_RESULT).join(',')})`;\n }\n\n /**\n * Collects all data including a bounding rect, transform matrix, and points array of the given {@link PositionData}\n * instance with the applied local transform data.\n *\n * @param {PositionData} position - The position data to process.\n *\n * @param {TransformData} [output] - Optional TransformData output instance.\n *\n * @param {object} [validationData] - Optional validation data for adjustment parameters.\n *\n * @returns {TransformData} The output TransformData instance.\n */\n getData(position, output = new TransformData(), validationData = {})\n {\n const valWidth = validationData.width ?? 0;\n const valHeight = validationData.height ?? 0;\n const valOffsetTop = validationData.offsetTop ?? validationData.marginTop ?? 0;\n const valOffsetLeft = validationData.offsetLeft ?? validationData.offsetLeft ?? 0;\n\n position.top += valOffsetTop;\n position.left += valOffsetLeft;\n\n const width = Number.isFinite(position.width) ? position.width : valWidth;\n const height = Number.isFinite(position.height) ? position.height : valHeight;\n\n const rect = output.corners;\n\n if (this.hasTransform(position))\n {\n rect[0][0] = rect[0][1] = rect[0][2] = 0;\n rect[1][0] = width;\n rect[1][1] = rect[1][2] = 0;\n rect[2][0] = width;\n rect[2][1] = height;\n rect[2][2] = 0;\n rect[3][0] = 0;\n rect[3][1] = height;\n rect[3][2] = 0;\n\n const matrix = this.getMat4(position, output.mat4);\n\n const translate = s_GET_ORIGIN_TRANSLATION(position.transformOrigin, width, height, output.originTranslations);\n\n if (constants.transformOriginDefault === position.transformOrigin)\n {\n vec3.transformMat4(rect[0], rect[0], matrix);\n vec3.transformMat4(rect[1], rect[1], matrix);\n vec3.transformMat4(rect[2], rect[2], matrix);\n vec3.transformMat4(rect[3], rect[3], matrix);\n }\n else\n {\n vec3.transformMat4(rect[0], rect[0], translate[0]);\n vec3.transformMat4(rect[0], rect[0], matrix);\n vec3.transformMat4(rect[0], rect[0], translate[1]);\n\n vec3.transformMat4(rect[1], rect[1], translate[0]);\n vec3.transformMat4(rect[1], rect[1], matrix);\n vec3.transformMat4(rect[1], rect[1], translate[1]);\n\n vec3.transformMat4(rect[2], rect[2], translate[0]);\n vec3.transformMat4(rect[2], rect[2], matrix);\n vec3.transformMat4(rect[2], rect[2], translate[1]);\n\n vec3.transformMat4(rect[3], rect[3], translate[0]);\n vec3.transformMat4(rect[3], rect[3], matrix);\n vec3.transformMat4(rect[3], rect[3], translate[1]);\n }\n\n rect[0][0] = position.left + rect[0][0];\n rect[0][1] = position.top + rect[0][1];\n rect[1][0] = position.left + rect[1][0];\n rect[1][1] = position.top + rect[1][1];\n rect[2][0] = position.left + rect[2][0];\n rect[2][1] = position.top + rect[2][1];\n rect[3][0] = position.left + rect[3][0];\n rect[3][1] = position.top + rect[3][1];\n }\n else\n {\n rect[0][0] = position.left;\n rect[0][1] = position.top;\n rect[1][0] = position.left + width;\n rect[1][1] = position.top;\n rect[2][0] = position.left + width;\n rect[2][1] = position.top + height;\n rect[3][0] = position.left;\n rect[3][1] = position.top + height;\n\n mat4.identity(output.mat4);\n }\n\n let maxX = Number.MIN_SAFE_INTEGER;\n let maxY = Number.MIN_SAFE_INTEGER;\n let minX = Number.MAX_SAFE_INTEGER;\n let minY = Number.MAX_SAFE_INTEGER;\n\n for (let cntr = 4; --cntr >= 0;)\n {\n if (rect[cntr][0] > maxX) { maxX = rect[cntr][0]; }\n if (rect[cntr][0] < minX) { minX = rect[cntr][0]; }\n if (rect[cntr][1] > maxY) { maxY = rect[cntr][1]; }\n if (rect[cntr][1] < minY) { minY = rect[cntr][1]; }\n }\n\n const boundingRect = output.boundingRect;\n boundingRect.x = minX;\n boundingRect.y = minY;\n boundingRect.width = maxX - minX;\n boundingRect.height = maxY - minY;\n\n position.top -= valOffsetTop;\n position.left -= valOffsetLeft;\n\n return output;\n }\n\n /**\n * Creates a transform matrix based on local data applied in order it was added.\n *\n * If no data object is provided then the source is the local transform data. If another data object is supplied\n * then the stored local transform order is applied then all remaining transform keys are applied. This allows the\n * construction of a transform matrix in advance of setting local data and is useful in collision detection.\n *\n * @param {object} [data] - PositionData instance or local transform data.\n *\n * @param {Matrix4} [output] - The output mat4 instance.\n *\n * @returns {Matrix4} Transform matrix.\n */\n getMat4(data = this._data, output = mat4.create())\n {\n const matrix = mat4.identity(output);\n\n // Bitwise tracks applied transform keys from local transform data.\n let seenKeys = 0;\n\n const orderList = this.#orderList;\n\n // First apply ordered transforms from local transform data.\n for (let cntr = 0; cntr < orderList.length; cntr++)\n {\n const key = orderList[cntr];\n\n switch (key)\n {\n case 'rotateX':\n seenKeys |= constants.transformKeysBitwise.rotateX;\n mat4.multiply(matrix, matrix, mat4.fromXRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateY':\n seenKeys |= constants.transformKeysBitwise.rotateY;\n mat4.multiply(matrix, matrix, mat4.fromYRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateZ':\n seenKeys |= constants.transformKeysBitwise.rotateZ;\n mat4.multiply(matrix, matrix, mat4.fromZRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'scale':\n seenKeys |= constants.transformKeysBitwise.scale;\n s_SCALE_VECTOR[0] = s_SCALE_VECTOR[1] = data[key];\n mat4.multiply(matrix, matrix, mat4.fromScaling(s_MAT4_TEMP, s_SCALE_VECTOR));\n break;\n\n case 'translateX':\n seenKeys |= constants.transformKeysBitwise.translateX;\n s_TRANSLATE_VECTOR[0] = data.translateX;\n s_TRANSLATE_VECTOR[1] = 0;\n s_TRANSLATE_VECTOR[2] = 0;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n\n case 'translateY':\n seenKeys |= constants.transformKeysBitwise.translateY;\n s_TRANSLATE_VECTOR[0] = 0;\n s_TRANSLATE_VECTOR[1] = data.translateY;\n s_TRANSLATE_VECTOR[2] = 0;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n\n case 'translateZ':\n seenKeys |= constants.transformKeysBitwise.translateZ;\n s_TRANSLATE_VECTOR[0] = 0;\n s_TRANSLATE_VECTOR[1] = 0;\n s_TRANSLATE_VECTOR[2] = data.translateZ;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n }\n }\n\n // Now apply any new keys not set in local transform data that have not been applied yet.\n if (data !== this._data)\n {\n for (let cntr = 0; cntr < constants.transformKeys.length; cntr++)\n {\n const key = constants.transformKeys[cntr];\n\n // Reject bad / no data or if the key has already been applied.\n if (data[key] === null || (seenKeys & constants.transformKeysBitwise[key]) > 0) { continue; }\n\n switch (key)\n {\n case 'rotateX':\n mat4.multiply(matrix, matrix, mat4.fromXRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateY':\n mat4.multiply(matrix, matrix, mat4.fromYRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateZ':\n mat4.multiply(matrix, matrix, mat4.fromZRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'scale':\n s_SCALE_VECTOR[0] = s_SCALE_VECTOR[1] = data[key];\n mat4.multiply(matrix, matrix, mat4.fromScaling(s_MAT4_TEMP, s_SCALE_VECTOR));\n break;\n\n case 'translateX':\n s_TRANSLATE_VECTOR[0] = data[key];\n s_TRANSLATE_VECTOR[1] = 0;\n s_TRANSLATE_VECTOR[2] = 0;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n\n case 'translateY':\n s_TRANSLATE_VECTOR[0] = 0;\n s_TRANSLATE_VECTOR[1] = data[key];\n s_TRANSLATE_VECTOR[2] = 0;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n\n case 'translateZ':\n s_TRANSLATE_VECTOR[0] = 0;\n s_TRANSLATE_VECTOR[1] = 0;\n s_TRANSLATE_VECTOR[2] = data[key];\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n break;\n }\n }\n }\n\n return matrix;\n }\n\n /**\n * Provides an orthographic enhancement to convert left / top positional data to a translate operation.\n *\n * This transform matrix takes into account that the remaining operations are , but adds any left / top attributes from passed in data to\n * translate X / Y.\n *\n * If no data object is provided then the source is the local transform data. If another data object is supplied\n * then the stored local transform order is applied then all remaining transform keys are applied. This allows the\n * construction of a transform matrix in advance of setting local data and is useful in collision detection.\n *\n * @param {object} [data] - PositionData instance or local transform data.\n *\n * @param {Matrix4} [output] - The output mat4 instance.\n *\n * @returns {Matrix4} Transform matrix.\n */\n getMat4Ortho(data = this._data, output = mat4.create())\n {\n const matrix = mat4.identity(output);\n\n // Attempt to retrieve values from passed in data otherwise default to 0.\n // Always perform the translation last regardless of order added to local transform data.\n // Add data.left to translateX and data.top to translateY.\n s_TRANSLATE_VECTOR[0] = (data.left ?? 0) + (data.translateX ?? 0);\n s_TRANSLATE_VECTOR[1] = (data.top ?? 0) + (data.translateY ?? 0);\n s_TRANSLATE_VECTOR[2] = data.translateZ ?? 0;\n mat4.multiply(matrix, matrix, mat4.fromTranslation(s_MAT4_TEMP, s_TRANSLATE_VECTOR));\n\n // Scale can also be applied out of order.\n if (data.scale !== null)\n {\n s_SCALE_VECTOR[0] = s_SCALE_VECTOR[1] = data.scale;\n mat4.multiply(matrix, matrix, mat4.fromScaling(s_MAT4_TEMP, s_SCALE_VECTOR));\n }\n\n // Early out if there is not rotation data.\n if (data.rotateX === null && data.rotateY === null && data.rotateZ === null) { return matrix; }\n\n // Rotation transforms must be applied in the order they are added.\n\n // Bitwise tracks applied transform keys from local transform data.\n let seenKeys = 0;\n\n const orderList = this.#orderList;\n\n // First apply ordered transforms from local transform data.\n for (let cntr = 0; cntr < orderList.length; cntr++)\n {\n const key = orderList[cntr];\n\n switch (key)\n {\n case 'rotateX':\n seenKeys |= constants.transformKeysBitwise.rotateX;\n mat4.multiply(matrix, matrix, mat4.fromXRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateY':\n seenKeys |= constants.transformKeysBitwise.rotateY;\n mat4.multiply(matrix, matrix, mat4.fromYRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateZ':\n seenKeys |= constants.transformKeysBitwise.rotateZ;\n mat4.multiply(matrix, matrix, mat4.fromZRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n }\n }\n\n // Now apply any new keys not set in local transform data that have not been applied yet.\n if (data !== this._data)\n {\n for (let cntr = 0; cntr < constants.transformKeys.length; cntr++)\n {\n const key = constants.transformKeys[cntr];\n\n // Reject bad / no data or if the key has already been applied.\n if (data[key] === null || (seenKeys & constants.transformKeysBitwise[key]) > 0) { continue; }\n\n switch (key)\n {\n case 'rotateX':\n mat4.multiply(matrix, matrix, mat4.fromXRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateY':\n mat4.multiply(matrix, matrix, mat4.fromYRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n\n case 'rotateZ':\n mat4.multiply(matrix, matrix, mat4.fromZRotation(s_MAT4_TEMP, degToRad(data[key])));\n break;\n }\n }\n }\n\n return matrix;\n }\n\n /**\n * Tests an object if it contains transform keys and the values are finite numbers.\n *\n * @param {object} data - An object to test for transform data.\n *\n * @returns {boolean} Whether the given PositionData has transforms.\n */\n hasTransform(data)\n {\n for (const key of constants.transformKeys)\n {\n if (Number.isFinite(data[key])) { return true; }\n }\n\n return false;\n }\n\n /**\n * Resets internal data from the given object containing valid transform keys.\n *\n * @param {object} data - An object with transform data.\n */\n reset(data)\n {\n for (const key in data)\n {\n if (constants.transformKeys.includes(key))\n {\n if (Number.isFinite(data[key]))\n {\n this._data[key] = data[key];\n }\n else\n {\n const index = this.#orderList.findIndex((entry) => entry === key);\n if (index >= 0) { this.#orderList.splice(index, 1); }\n\n delete this._data[key];\n }\n }\n }\n }\n}\n\n/**\n * Returns the translations necessary to translate a matrix operation based on the `transformOrigin` parameter of the\n * given position instance. The first entry / index 0 is the pre-translation and last entry / index 1 is the post-\n * translation.\n *\n * This method is used internally, but may be useful if you need the origin translation matrices to transform\n * bespoke points based on any `transformOrigin` set in {@link PositionData}.\n *\n * @param {string} transformOrigin - The transform origin attribute from PositionData.\n *\n * @param {number} width - The PositionData width or validation data width when 'auto'.\n *\n * @param {number} height - The PositionData height or validation data height when 'auto'.\n *\n * @param {Matrix4[]} output - Output Mat4 array.\n *\n * @returns {Matrix4[]} Output Mat4 array.\n */\nfunction s_GET_ORIGIN_TRANSLATION(transformOrigin, width, height, output)\n{\n const vector = s_VEC3_TEMP;\n\n switch (transformOrigin)\n {\n case 'top left':\n vector[0] = vector[1] = 0;\n mat4.fromTranslation(output[0], vector);\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'top center':\n vector[0] = -width * 0.5;\n vector[1] = 0;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width * 0.5;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'top right':\n vector[0] = -width;\n vector[1] = 0;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'center left':\n vector[0] = 0;\n vector[1] = -height * 0.5;\n mat4.fromTranslation(output[0], vector);\n vector[1] = height * 0.5;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case null: // By default null / no transform is center.\n case 'center':\n vector[0] = -width * 0.5;\n vector[1] = -height * 0.5;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width * 0.5;\n vector[1] = height * 0.5;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'center right':\n vector[0] = -width;\n vector[1] = -height * 0.5;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width;\n vector[1] = height * 0.5;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'bottom left':\n vector[0] = 0;\n vector[1] = -height;\n mat4.fromTranslation(output[0], vector);\n vector[1] = height;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'bottom center':\n vector[0] = -width * 0.5;\n vector[1] = -height;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width * 0.5;\n vector[1] = height;\n mat4.fromTranslation(output[1], vector);\n break;\n\n case 'bottom right':\n vector[0] = -width;\n vector[1] = -height;\n mat4.fromTranslation(output[0], vector);\n vector[0] = width;\n vector[1] = height;\n mat4.fromTranslation(output[1], vector);\n break;\n\n // No valid transform origin parameter; set identity.\n default:\n mat4.identity(output[0]);\n mat4.identity(output[1]);\n break;\n }\n\n return output;\n}\n","import { writable } from 'svelte/store';\n\nimport { TransformData } from '../transform/TransformData.js';\nimport { PositionData } from '../PositionData.js';\n\nexport class UpdateElementData\n{\n constructor()\n {\n /**\n * Stores the private data from Position.\n *\n * @type {PositionData}\n */\n this.data = void 0;\n\n /**\n * Provides a copy of local data sent to subscribers.\n *\n * @type {PositionData}\n */\n this.dataSubscribers = new PositionData();\n\n /**\n * Stores the current dimension data used for the readable `dimension` store.\n *\n * @type {{width: number | 'auto', height: number | 'auto'}}\n */\n this.dimensionData = { width: 0, height: 0 };\n\n /**\n * @type {PositionChangeSet}\n */\n this.changeSet = void 0;\n\n /**\n * @type {PositionOptions}\n */\n this.options = void 0;\n\n /**\n * Stores if this Position / update data is queued for update.\n *\n * @type {boolean}\n */\n this.queued = false;\n\n /**\n * @type {StyleCache}\n */\n this.styleCache = void 0;\n\n /**\n * @type {Transforms}\n */\n this.transforms = void 0;\n\n /**\n * Stores the current transform data used for the readable `transform` store. It is only active when there are\n * subscribers to the store or calculateTransform options is true.\n *\n * @type {TransformData}\n */\n this.transformData = new TransformData();\n\n /**\n * @type {(function(PositionData): void)[]}\n */\n this.subscriptions = void 0;\n\n /**\n * @type {Writable<{width: (number|\"auto\"), height: (number|\"auto\")}>}\n */\n this.storeDimension = writable(this.dimensionData);\n\n // When there are subscribers set option to calculate transform updates; set to false when no subscribers.\n\n /**\n * @type {Writable}\n */\n this.storeTransform = writable(this.transformData, () =>\n {\n this.options.transformSubscribed = true;\n return () => this.options.transformSubscribed = false;\n });\n\n /**\n * Stores the queued state for update element processing.\n *\n * @type {boolean}\n */\n this.queued = false;\n\n // Seal data backing readable stores.\n Object.seal(this.dimensionData);\n }\n}\n","import { isWritableStore } from '@typhonjs-fvtt/runtime/svelte/store';\n\n/**\n * Svelte doesn't provide any events for the animate directive.\n *\n * The provided function below wraps a Svelte animate directive function generating bubbling events for start & end of\n * animation.\n *\n * These events are `animate:start` and `animate:end`.\n *\n * This is useful for instance if you are animating several nodes in a scrollable container where the overflow parameter\n * needs to be set to `none` while animating such that the scrollbar is not activated by the animation.\n *\n * Optionally you may also provide a boolean writable store that will be set to true when animation is active. In some\n * cases this leads to an easier implementation for gating on animation state.\n *\n * @example
\n * const isAnimating = writable(false);\n * const flipWithEvents = animateEvents(flip, isAnimating);\n * \n *\n * \n * {#each someData as entry (entry.id)}\n * \n * {/each}\n *\n * @param {(node: Element, { from: DOMRect, to: DOMRect }, params?: *) =>\n * import('svelte/animate').AnimationConfig} fn - A Svelte animation function.\n *\n * @param {import('svelte/store').Writable} [store] - An optional boolean writable store that is set to true\n * when animation is active.\n *\n * @returns {(node: Element, { from: DOMRect, to: DOMRect }, params?: *) =>\n * import('svelte/animate').AnimationConfig} Wrapped animation function.\n */\nfunction animateEvents(fn, store = void 0)\n{\n if (typeof fn !== 'function') { throw new TypeError(`'fn' is not a function.`); }\n if (store !== void 0 && !isWritableStore(store)) { throw new TypeError(`'store' is not a writable store.`); }\n\n // Track a single start / end sequence across all animations.\n let startFired = false;\n let endFired = false;\n\n return (node, animations, params = {}) =>\n {\n const animationConfig = fn(node, animations, params);\n\n // Store any existing tick function.\n const existingTick = animationConfig.tick;\n\n // Use tick callback to fire events only once when t / time is 0 and 1.\n animationConfig.tick = (t, u) =>\n {\n // If there is any tick function then invoke it.\n if (existingTick) { existingTick(t, u); }\n\n if (!startFired && t === 0)\n {\n if (store) { store.set(true); }\n node.dispatchEvent(new CustomEvent('animate:start', { bubbles: true }));\n startFired = true;\n endFired = false;\n }\n\n if (!endFired && t === 1)\n {\n if (store) { store.set(false); }\n node.dispatchEvent(new CustomEvent('animate:end', { bubbles: true }));\n endFired = true;\n startFired = false;\n }\n };\n\n return animationConfig;\n }\n}\n\n/**\n * Awaits `requestAnimationFrame` calls by the counter specified. This allows asynchronous applications for direct /\n * inline style modification amongst other direct animation techniques.\n *\n * @param {number} [cntr=1] - A positive integer greater than 0 for amount of requestAnimationFrames to wait.\n *\n * @returns {Promise} Returns current time equivalent to `performance.now()`.\n */\nasync function nextAnimationFrame(cntr = 1)\n{\n if (!Number.isInteger(cntr) || cntr < 1)\n {\n throw new TypeError(`nextAnimationFrame error: 'cntr' must be a positive integer greater than 0.`);\n }\n\n let currentTime = performance.now();\n for (;--cntr >= 0;)\n {\n currentTime = await new Promise((resolve) => requestAnimationFrame(resolve));\n }\n\n return currentTime;\n}\n\nexport { animateEvents, nextAnimationFrame };\n//# sourceMappingURL=index.js.map\n","import { nextAnimationFrame } from '@typhonjs-fvtt/runtime/svelte/animate';\n\n/**\n * Decouples updates to any parent target HTMLElement inline styles. Invoke {@link Position.elementUpdated} to await\n * on the returned promise that is resolved with the current render time via `nextAnimationFrame` /\n * `requestAnimationFrame`. This allows the underlying data model to be updated immediately while updates to the\n * element are in sync with the browser and potentially in the future be further throttled.\n *\n * @param {HTMLElement} el - The target HTMLElement.\n */\nexport class UpdateElementManager\n{\n static list = [];\n static listCntr = 0;\n\n static updatePromise;\n\n static get promise() { return this.updatePromise; }\n\n /**\n * Potentially adds the given element and internal updateData instance to the list.\n *\n * @param {HTMLElement} el - An HTMLElement instance.\n *\n * @param {UpdateElementData} updateData - An UpdateElementData instance.\n *\n * @returns {Promise} The unified next frame update promise. Returns `currentTime`.\n */\n static add(el, updateData)\n {\n if (this.listCntr < this.list.length)\n {\n const entry = this.list[this.listCntr];\n entry[0] = el;\n entry[1] = updateData;\n }\n else\n {\n this.list.push([el, updateData]);\n }\n\n this.listCntr++;\n updateData.queued = true;\n\n if (!this.updatePromise) { this.updatePromise = this.wait(); }\n\n return this.updatePromise;\n }\n\n /**\n * Await on `nextAnimationFrame` and iterate over list map invoking callback functions.\n *\n * @returns {Promise} The next frame Promise / currentTime from nextAnimationFrame.\n */\n static async wait()\n {\n // Await the next animation frame. In the future this can be extended to multiple frames to divide update rate.\n const currentTime = await nextAnimationFrame();\n\n this.updatePromise = void 0;\n\n for (let cntr = this.listCntr; --cntr >= 0;)\n {\n // Obtain data for entry.\n const entry = this.list[cntr];\n const el = entry[0];\n const updateData = entry[1];\n\n // Clear entry data.\n entry[0] = void 0;\n entry[1] = void 0;\n\n // Reset queued state.\n updateData.queued = false;\n\n // Early out if the element is no longer connected to the DOM / shadow root.\n // if (!el.isConnected || !updateData.changeSet.hasChange()) { continue; }\n if (!el.isConnected) { continue; }\n\n if (updateData.options.ortho)\n {\n s_UPDATE_ELEMENT_ORTHO(el, updateData);\n }\n else\n {\n s_UPDATE_ELEMENT(el, updateData);\n }\n\n // If calculate transform options is enabled then update the transform data and set the readable store.\n if (updateData.options.calculateTransform || updateData.options.transformSubscribed)\n {\n s_UPDATE_TRANSFORM(el, updateData);\n }\n\n // Update all subscribers with changed data.\n this.updateSubscribers(updateData);\n }\n\n this.listCntr = 0;\n\n return currentTime;\n }\n\n /**\n * Potentially immediately updates the given element.\n *\n * @param {HTMLElement} el - An HTMLElement instance.\n *\n * @param {UpdateElementData} updateData - An UpdateElementData instance.\n */\n static immediate(el, updateData)\n {\n // Early out if the element is no longer connected to the DOM / shadow root.\n // if (!el.isConnected || !updateData.changeSet.hasChange()) { continue; }\n if (!el.isConnected) { return; }\n\n if (updateData.options.ortho)\n {\n s_UPDATE_ELEMENT_ORTHO(el, updateData);\n }\n else\n {\n s_UPDATE_ELEMENT(el, updateData);\n }\n\n // If calculate transform options is enabled then update the transform data and set the readable store.\n if (updateData.options.calculateTransform || updateData.options.transformSubscribed)\n {\n s_UPDATE_TRANSFORM(el, updateData);\n }\n\n // Update all subscribers with changed data.\n this.updateSubscribers(updateData);\n }\n\n /**\n * @param {UpdateElementData} updateData - Data change set.\n */\n static updateSubscribers(updateData)\n {\n const data = updateData.data;\n const changeSet = updateData.changeSet;\n\n if (!changeSet.hasChange()) { return; }\n\n // Make a copy of the data.\n const output = updateData.dataSubscribers.copy(data);\n\n const subscriptions = updateData.subscriptions;\n\n // Early out if there are no subscribers.\n if (subscriptions.length > 0)\n {\n for (let cntr = 0; cntr < subscriptions.length; cntr++) { subscriptions[cntr](output); }\n }\n\n // Update dimension data if width / height has changed.\n if (changeSet.width || changeSet.height)\n {\n updateData.dimensionData.width = data.width;\n updateData.dimensionData.height = data.height;\n updateData.storeDimension.set(updateData.dimensionData);\n }\n\n changeSet.set(false);\n }\n}\n\n/**\n * Decouples updates to any parent target HTMLElement inline styles. Invoke {@link Position.elementUpdated} to await\n * on the returned promise that is resolved with the current render time via `nextAnimationFrame` /\n * `requestAnimationFrame`. This allows the underlying data model to be updated immediately while updates to the\n * element are in sync with the browser and potentially in the future be further throttled.\n *\n * @param {HTMLElement} el - The target HTMLElement.\n *\n * @param {UpdateElementData} updateData - Update data.\n */\nfunction s_UPDATE_ELEMENT(el, updateData)\n{\n const changeSet = updateData.changeSet;\n const data = updateData.data;\n\n if (changeSet.left)\n {\n el.style.left = `${data.left}px`;\n }\n\n if (changeSet.top)\n {\n el.style.top = `${data.top}px`;\n }\n\n if (changeSet.zIndex)\n {\n el.style.zIndex = typeof data.zIndex === 'number' ? `${data.zIndex}` : null;\n }\n\n if (changeSet.width)\n {\n el.style.width = typeof data.width === 'number' ? `${data.width}px` : data.width;\n }\n\n if (changeSet.height)\n {\n el.style.height = typeof data.height === 'number' ? `${data.height}px` : data.height;\n }\n\n if (changeSet.transformOrigin)\n {\n // When set to 'center' we can simply set the transform to null which is center by default.\n el.style.transformOrigin = data.transformOrigin === 'center' ? null : data.transformOrigin;\n }\n\n // Update all transforms in order added to transforms object.\n if (changeSet.transform)\n {\n el.style.transform = updateData.transforms.isActive ? updateData.transforms.getCSS() : null;\n }\n}\n\n/**\n * Decouples updates to any parent target HTMLElement inline styles. Invoke {@link Position.elementUpdated} to await\n * on the returned promise that is resolved with the current render time via `nextAnimationFrame` /\n * `requestAnimationFrame`. This allows the underlying data model to be updated immediately while updates to the\n * element are in sync with the browser and potentially in the future be further throttled.\n *\n * @param {HTMLElement} el - The target HTMLElement.\n *\n * @param {UpdateElementData} updateData - Update data.\n */\nfunction s_UPDATE_ELEMENT_ORTHO(el, updateData)\n{\n const changeSet = updateData.changeSet;\n const data = updateData.data;\n\n if (changeSet.zIndex)\n {\n el.style.zIndex = typeof data.zIndex === 'number' ? `${data.zIndex}` : null;\n }\n\n if (changeSet.width)\n {\n el.style.width = typeof data.width === 'number' ? `${data.width}px` : data.width;\n }\n\n if (changeSet.height)\n {\n el.style.height = typeof data.height === 'number' ? `${data.height}px` : data.height;\n }\n\n if (changeSet.transformOrigin)\n {\n // When set to 'center' we can simply set the transform to null which is center by default.\n el.style.transformOrigin = data.transformOrigin === 'center' ? null : data.transformOrigin;\n }\n\n // Update all transforms in order added to transforms object.\n if (changeSet.left || changeSet.top || changeSet.transform)\n {\n el.style.transform = updateData.transforms.getCSSOrtho(data);\n }\n}\n\n/**\n * Updates the applied transform data and sets the readble `transform` store.\n *\n * @param {HTMLElement} el - The target HTMLElement.\n *\n * @param {UpdateElementData} updateData - Update element data.\n */\nfunction s_UPDATE_TRANSFORM(el, updateData)\n{\n s_VALIDATION_DATA.height = updateData.data.height !== 'auto' ? updateData.data.height :\n updateData.styleCache.offsetHeight;\n\n s_VALIDATION_DATA.width = updateData.data.width !== 'auto' ? updateData.data.width :\n updateData.styleCache.offsetWidth;\n\n s_VALIDATION_DATA.marginLeft = updateData.styleCache.marginLeft;\n\n s_VALIDATION_DATA.marginTop = updateData.styleCache.marginTop;\n\n // Get transform data. First set constraints including any margin top / left as offsets and width / height. Used\n // when position width / height is 'auto'.\n updateData.transforms.getData(updateData.data, updateData.transformData, s_VALIDATION_DATA);\n\n updateData.storeTransform.set(updateData.transformData);\n}\n\nconst s_VALIDATION_DATA = {\n height: void 0,\n width: void 0,\n marginLeft: void 0,\n marginTop: void 0\n};\n","import {\n propertyStore,\n subscribeIgnoreFirst } from '@typhonjs-fvtt/runtime/svelte/store';\n\nimport {\n isIterable,\n isObject,\n isPlainObject } from '@typhonjs-fvtt/runtime/svelte/util';\n\nimport { AnimationAPI } from './animation/AnimationAPI.js';\nimport { AnimationGroupAPI } from './animation/AnimationGroupAPI.js';\nimport * as constants from './constants.js';\nimport { convertRelative } from './convertRelative.js';\nimport * as positionInitial from './initial/index.js';\nimport { PositionChangeSet } from './PositionChangeSet.js';\nimport { PositionData } from './PositionData.js';\nimport { PositionStateAPI } from './PositionStateAPI.js';\nimport { StyleCache } from './StyleCache.js';\nimport { TransformData } from './transform/TransformData.js';\nimport { AdapterValidators } from './validators/AdapterValidators.js';\nimport * as positionValidators from './validators/index.js';\nimport { Transforms } from './transform/Transforms.js';\nimport { UpdateElementData } from './update/UpdateElementData.js';\nimport { UpdateElementManager } from './update/UpdateElementManager.js';\n\n/**\n * Provides a store for position following the subscriber protocol in addition to providing individual writable derived\n * stores for each independent variable.\n */\nexport class Position\n{\n /**\n * @type {PositionData}\n */\n #data = new PositionData();\n\n /**\n * Provides the animation API.\n *\n * @type {AnimationAPI}\n */\n #animate = new AnimationAPI(this, this.#data);\n\n /**\n * Stores the style attributes that changed on update.\n *\n * @type {PositionChangeSet}\n */\n #positionChangeSet = new PositionChangeSet();\n\n /**\n * Stores ongoing options that are set in the constructor or by transform store subscription.\n *\n * @type {PositionOptions}\n */\n #options = {\n calculateTransform: false,\n initialHelper: void 0,\n ortho: true,\n transformSubscribed: false\n };\n\n /**\n * The associated parent for positional data tracking. Used in validators.\n *\n * @type {PositionParent}\n */\n #parent;\n\n /**\n * @type {StorePosition}\n */\n #stores;\n\n /**\n * Stores an instance of the computer styles for the target element.\n *\n * @type {StyleCache}\n */\n #styleCache;\n\n /**\n * Stores the subscribers.\n *\n * @type {(function(PositionData): void)[]}\n */\n #subscriptions = [];\n\n /**\n * @type {Transforms}\n */\n #transforms = new Transforms();\n\n /**\n * @type {UpdateElementData}\n */\n #updateElementData;\n\n /**\n * Stores the UpdateElementManager wait promise.\n *\n * @type {Promise}\n */\n #updateElementPromise;\n\n /**\n * @type {AdapterValidators}\n */\n #validators;\n\n /**\n * @type {ValidatorData[]}\n */\n #validatorData;\n\n /**\n * @type {PositionStateAPI}\n */\n #state = new PositionStateAPI(this, this.#data, this.#transforms);\n\n /**\n * @returns {AnimationGroupAPI} Public Animation API.\n */\n static get Animate() { return AnimationGroupAPI; }\n\n /**\n * @returns {{browserCentered?: Centered, Centered?: *}} Initial position helpers.\n */\n static get Initial() { return positionInitial; }\n\n /**\n * Returns TransformData class / constructor.\n *\n * @returns {TransformData} TransformData class / constructor.\n */\n static get TransformData() { return TransformData; }\n\n /**\n * Returns default validators.\n *\n * Note: `basicWindow` and `BasicBounds` will eventually be removed.\n *\n * @returns {{basicWindow?: BasicBounds, transformWindow?: TransformBounds, TransformBounds?: *, BasicBounds?: *}}\n * Available validators.\n */\n static get Validators() { return positionValidators; }\n\n /**\n * Returns a duplicate of a given position instance copying any options and validators.\n *\n * // TODO: Consider more safety over options processing.\n *\n * @param {Position} position - A position instance.\n *\n * @param {PositionOptions} options - Position options.\n *\n * @returns {Position} A duplicate position instance.\n */\n static duplicate(position, options)\n {\n if (!(position instanceof Position)) { throw new TypeError(`'position' is not an instance of Position.`); }\n\n const newPosition = new Position(options);\n\n newPosition.#options = Object.assign({}, position.#options, options);\n newPosition.#validators.add(...position.#validators);\n\n newPosition.set(position.#data);\n\n return newPosition;\n }\n\n /**\n * @param {PositionParent|PositionOptionsAll} [parent] - A potential parent element or object w/ `elementTarget`\n * getter. May also be the PositionOptions object w/ 1 argument.\n *\n * @param {PositionOptionsAll} [options] - Default values.\n */\n constructor(parent, options)\n {\n // Test if `parent` is a plain object; if so treat as options object.\n if (isPlainObject(parent))\n {\n options = parent;\n }\n else\n {\n this.#parent = parent;\n }\n\n const data = this.#data;\n const transforms = this.#transforms;\n\n this.#styleCache = new StyleCache();\n\n const updateData = new UpdateElementData();\n\n updateData.changeSet = this.#positionChangeSet;\n updateData.data = this.#data;\n updateData.options = this.#options;\n updateData.styleCache = this.#styleCache;\n updateData.subscriptions = this.#subscriptions;\n updateData.transforms = this.#transforms;\n\n this.#updateElementData = updateData;\n\n if (typeof options === 'object')\n {\n // Set Position options\n if (typeof options.calculateTransform === 'boolean')\n {\n this.#options.calculateTransform = options.calculateTransform;\n }\n\n if (typeof options.ortho === 'boolean')\n {\n this.#options.ortho = options.ortho;\n }\n\n // Set default values from options.\n\n if (Number.isFinite(options.height) || options.height === 'auto' || options.height === 'inherit' ||\n options.height === null)\n {\n data.height = updateData.dimensionData.height = typeof options.height === 'number' ?\n Math.round(options.height) : options.height;\n }\n\n if (Number.isFinite(options.left) || options.left === null)\n {\n data.left = typeof options.left === 'number' ? Math.round(options.left) : options.left;\n }\n\n if (Number.isFinite(options.maxHeight) || options.maxHeight === null)\n {\n data.maxHeight = typeof options.maxHeight === 'number' ? Math.round(options.maxHeight) : options.maxHeight;\n }\n\n if (Number.isFinite(options.maxWidth) || options.maxWidth === null)\n {\n data.maxWidth = typeof options.maxWidth === 'number' ? Math.round(options.maxWidth) : options.maxWidth;\n }\n\n if (Number.isFinite(options.minHeight) || options.minHeight === null)\n {\n data.minHeight = typeof options.minHeight === 'number' ? Math.round(options.minHeight) : options.minHeight;\n }\n\n if (Number.isFinite(options.minWidth) || options.minWidth === null)\n {\n data.minWidth = typeof options.minWidth === 'number' ? Math.round(options.minWidth) : options.minWidth;\n }\n\n if (Number.isFinite(options.rotateX) || options.rotateX === null)\n {\n transforms.rotateX = data.rotateX = options.rotateX;\n }\n\n if (Number.isFinite(options.rotateY) || options.rotateY === null)\n {\n transforms.rotateY = data.rotateY = options.rotateY;\n }\n\n if (Number.isFinite(options.rotateZ) || options.rotateZ === null)\n {\n transforms.rotateZ = data.rotateZ = options.rotateZ;\n }\n\n if (Number.isFinite(options.scale) || options.scale === null)\n {\n transforms.scale = data.scale = options.scale;\n }\n\n if (Number.isFinite(options.top) || options.top === null)\n {\n data.top = typeof options.top === 'number' ? Math.round(options.top) : options.top;\n }\n\n if (typeof options.transformOrigin === 'string' || options.transformOrigin === null)\n {\n data.transformOrigin = constants.transformOrigins.includes(options.transformOrigin) ?\n options.transformOrigin : null;\n }\n\n if (Number.isFinite(options.translateX) || options.translateX === null)\n {\n transforms.translateX = data.translateX = options.translateX;\n }\n\n if (Number.isFinite(options.translateY) || options.translateY === null)\n {\n transforms.translateY = data.translateY = options.translateY;\n }\n\n if (Number.isFinite(options.translateZ) || options.translateZ === null)\n {\n transforms.translateZ = data.translateZ = options.translateZ;\n }\n\n if (Number.isFinite(options.width) || options.width === 'auto' || options.width === 'inherit' ||\n options.width === null)\n {\n data.width = updateData.dimensionData.width = typeof options.width === 'number' ?\n Math.round(options.width) : options.width;\n }\n\n if (Number.isFinite(options.zIndex) || options.zIndex === null)\n {\n data.zIndex = typeof options.zIndex === 'number' ? Math.round(options.zIndex) : options.zIndex;\n }\n }\n\n this.#stores = {\n // The main properties for manipulating Position.\n height: propertyStore(this, 'height'),\n left: propertyStore(this, 'left'),\n rotateX: propertyStore(this, 'rotateX'),\n rotateY: propertyStore(this, 'rotateY'),\n rotateZ: propertyStore(this, 'rotateZ'),\n scale: propertyStore(this, 'scale'),\n top: propertyStore(this, 'top'),\n transformOrigin: propertyStore(this, 'transformOrigin'),\n translateX: propertyStore(this, 'translateX'),\n translateY: propertyStore(this, 'translateY'),\n translateZ: propertyStore(this, 'translateZ'),\n width: propertyStore(this, 'width'),\n zIndex: propertyStore(this, 'zIndex'),\n\n // Stores that control validation when width / height is not `auto`.\n maxHeight: propertyStore(this, 'maxHeight'),\n maxWidth: propertyStore(this, 'maxWidth'),\n minHeight: propertyStore(this, 'minHeight'),\n minWidth: propertyStore(this, 'minWidth'),\n\n // Readable stores based on updates or from resize observer changes.\n dimension: { subscribe: updateData.storeDimension.subscribe },\n element: { subscribe: this.#styleCache.stores.element.subscribe },\n resizeContentHeight: { subscribe: this.#styleCache.stores.resizeContentHeight.subscribe },\n resizeContentWidth: { subscribe: this.#styleCache.stores.resizeContentWidth.subscribe },\n resizeOffsetHeight: { subscribe: this.#styleCache.stores.resizeOffsetHeight.subscribe },\n resizeOffsetWidth: { subscribe: this.#styleCache.stores.resizeOffsetWidth.subscribe },\n transform: { subscribe: updateData.storeTransform.subscribe },\n\n // Protected store that should only be set by resizeObserver action.\n resizeObserved: this.#styleCache.stores.resizeObserved,\n };\n\n // When resize change from any applied resizeObserver action automatically set data for new validation run.\n // A resizeObserver prop should be set to true for ApplicationShell components or usage of resizeObserver action\n // to monitor for changes. This should only be used on elements that have 'auto' for width or height.\n subscribeIgnoreFirst(this.#stores.resizeObserved, (resizeData) =>\n {\n const parent = this.#parent;\n const el = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n\n // Only invoke set if there is a target element and the resize data has a valid offset width & height.\n if (el instanceof HTMLElement && Number.isFinite(resizeData?.offsetWidth) &&\n Number.isFinite(resizeData?.offsetHeight))\n {\n this.set(data);\n }\n });\n\n this.#stores.transformOrigin.values = constants.transformOrigins;\n\n [this.#validators, this.#validatorData] = new AdapterValidators();\n\n if (options?.initial || options?.positionInitial)\n {\n const initialHelper = options.initial ?? options.positionInitial;\n\n if (typeof initialHelper?.getLeft !== 'function' || typeof initialHelper?.getTop !== 'function')\n {\n throw new Error(\n `'options.initial' position helper does not contain 'getLeft' and / or 'getTop' functions.`);\n }\n\n this.#options.initialHelper = options.initial;\n }\n\n if (options?.validator)\n {\n if (isIterable(options?.validator)) { this.validators.add(...options.validator); }\n else { this.validators.add(options.validator); }\n }\n }\n\n /**\n * Returns the animation API.\n *\n * @returns {AnimationAPI} Animation API.\n */\n get animate()\n {\n return this.#animate;\n }\n\n /**\n * Returns the dimension data for the readable store.\n *\n * @returns {{width: number | 'auto', height: number | 'auto'}} Dimension data.\n */\n get dimension()\n {\n return this.#updateElementData.dimensionData;\n }\n\n /**\n * Returns the current HTMLElement being positioned.\n *\n * @returns {HTMLElement|undefined} Current HTMLElement being positioned.\n */\n get element()\n {\n return this.#styleCache.el;\n }\n\n /**\n * Returns a promise that is resolved on the next element update with the time of the update.\n *\n * @returns {Promise} Promise resolved on element update.\n */\n get elementUpdated()\n {\n return this.#updateElementPromise;\n }\n\n /**\n * Returns the associated {@link PositionParent} instance.\n *\n * @returns {PositionParent} The PositionParent instance.\n */\n get parent() { return this.#parent; }\n\n /**\n * Returns the state API.\n *\n * @returns {PositionStateAPI} Position state API.\n */\n get state() { return this.#state; }\n\n /**\n * Returns the derived writable stores for individual data variables.\n *\n * @returns {StorePosition} Derived / writable stores.\n */\n get stores() { return this.#stores; }\n\n /**\n * Returns the transform data for the readable store.\n *\n * @returns {TransformData} Transform Data.\n */\n get transform()\n {\n return this.#updateElementData.transformData;\n }\n\n /**\n * Returns the validators.\n *\n * @returns {AdapterValidators} validators.\n */\n get validators() { return this.#validators; }\n\n /**\n * Sets the associated {@link PositionParent} instance. Resets the style cache and default data.\n *\n * @param {PositionParent|void} parent - A PositionParent instance.\n */\n set parent(parent)\n {\n if (parent !== void 0 && !(parent instanceof HTMLElement) && !isObject(parent))\n {\n throw new TypeError(`'parent' is not an HTMLElement, object, or undefined.`);\n }\n\n this.#parent = parent;\n\n // Reset any stored default data & the style cache.\n this.#state.remove({ name: '#defaultData' });\n this.#styleCache.reset();\n\n // If a parent is defined then invoke set to update any parent element.\n if (parent) { this.set(this.#data); }\n }\n\n// Data accessors ----------------------------------------------------------------------------------------------------\n\n /**\n * @returns {number|'auto'|'inherit'|null} height\n */\n get height() { return this.#data.height; }\n\n /**\n * @returns {number|null} left\n */\n get left() { return this.#data.left; }\n\n /**\n * @returns {number|null} maxHeight\n */\n get maxHeight() { return this.#data.maxHeight; }\n\n /**\n * @returns {number|null} maxWidth\n */\n get maxWidth() { return this.#data.maxWidth; }\n\n /**\n * @returns {number|null} minHeight\n */\n get minHeight() { return this.#data.minHeight; }\n\n /**\n * @returns {number|null} minWidth\n */\n get minWidth() { return this.#data.minWidth; }\n\n /**\n * @returns {number|null} rotateX\n */\n get rotateX() { return this.#data.rotateX; }\n\n /**\n * @returns {number|null} rotateY\n */\n get rotateY() { return this.#data.rotateY; }\n\n /**\n * @returns {number|null} rotateZ\n */\n get rotateZ() { return this.#data.rotateZ; }\n\n /**\n * @returns {number|null} alias for rotateZ\n */\n get rotation() { return this.#data.rotateZ; }\n\n /**\n * @returns {number|null} scale\n */\n get scale() { return this.#data.scale; }\n\n /**\n * @returns {number|null} top\n */\n get top() { return this.#data.top; }\n\n /**\n * @returns {string} transformOrigin\n */\n get transformOrigin() { return this.#data.transformOrigin; }\n\n /**\n * @returns {number|null} translateX\n */\n get translateX() { return this.#data.translateX; }\n\n /**\n * @returns {number|null} translateY\n */\n get translateY() { return this.#data.translateY; }\n\n /**\n * @returns {number|null} translateZ\n */\n get translateZ() { return this.#data.translateZ; }\n\n /**\n * @returns {number|'auto'|'inherit'|null} width\n */\n get width() { return this.#data.width; }\n\n /**\n * @returns {number|null} z-index\n */\n get zIndex() { return this.#data.zIndex; }\n\n /**\n * @param {number|string|null} height -\n */\n set height(height)\n {\n this.#stores.height.set(height);\n }\n\n /**\n * @param {number|string|null} left -\n */\n set left(left)\n {\n this.#stores.left.set(left);\n }\n\n /**\n * @param {number|string|null} maxHeight -\n */\n set maxHeight(maxHeight)\n {\n this.#stores.maxHeight.set(maxHeight);\n }\n\n /**\n * @param {number|string|null} maxWidth -\n */\n set maxWidth(maxWidth)\n {\n this.#stores.maxWidth.set(maxWidth);\n }\n\n /**\n * @param {number|string|null} minHeight -\n */\n set minHeight(minHeight)\n {\n this.#stores.minHeight.set(minHeight);\n }\n\n /**\n * @param {number|string|null} minWidth -\n */\n set minWidth(minWidth)\n {\n this.#stores.minWidth.set(minWidth);\n }\n\n /**\n * @param {number|string|null} rotateX -\n */\n set rotateX(rotateX)\n {\n this.#stores.rotateX.set(rotateX);\n }\n\n /**\n * @param {number|string|null} rotateY -\n */\n set rotateY(rotateY)\n {\n this.#stores.rotateY.set(rotateY);\n }\n\n /**\n * @param {number|string|null} rotateZ -\n */\n set rotateZ(rotateZ)\n {\n this.#stores.rotateZ.set(rotateZ);\n }\n\n /**\n * @param {number|string|null} rotateZ - alias for rotateZ\n */\n set rotation(rotateZ)\n {\n this.#stores.rotateZ.set(rotateZ);\n }\n\n /**\n * @param {number|string|null} scale -\n */\n set scale(scale)\n {\n this.#stores.scale.set(scale);\n }\n\n /**\n * @param {number|string|null} top -\n */\n set top(top)\n {\n this.#stores.top.set(top);\n }\n\n /**\n * @param {string} transformOrigin -\n */\n set transformOrigin(transformOrigin)\n {\n if (constants.transformOrigins.includes(transformOrigin)) { this.#stores.transformOrigin.set(transformOrigin); }\n }\n\n /**\n * @param {number|string|null} translateX -\n */\n set translateX(translateX)\n {\n this.#stores.translateX.set(translateX);\n }\n\n /**\n * @param {number|string|null} translateY -\n */\n set translateY(translateY)\n {\n this.#stores.translateY.set(translateY);\n }\n\n /**\n * @param {number|string|null} translateZ -\n */\n set translateZ(translateZ)\n {\n this.#stores.translateZ.set(translateZ);\n }\n\n /**\n * @param {number|string|null} width -\n */\n set width(width)\n {\n this.#stores.width.set(width);\n }\n\n /**\n * @param {number|string|null} zIndex -\n */\n set zIndex(zIndex)\n {\n this.#stores.zIndex.set(zIndex);\n }\n\n /**\n * Assigns current position to object passed into method.\n *\n * @param {object|PositionData} [position] - Target to assign current position data.\n *\n * @param {PositionGetOptions} [options] - Defines options for specific keys and substituting null for numeric\n * default values.\n *\n * @returns {PositionData} Passed in object with current position data.\n */\n get(position = {}, options)\n {\n const keys = options?.keys;\n const excludeKeys = options?.exclude;\n const numeric = options?.numeric ?? false;\n\n if (isIterable(keys))\n {\n // Replace any null values potentially with numeric default values.\n if (numeric)\n {\n for (const key of keys) { position[key] = this[key] ?? constants.numericDefaults[key]; }\n }\n else // Accept current values.\n {\n for (const key of keys) { position[key] = this[key]; }\n }\n\n // Remove any excluded keys.\n if (isIterable(excludeKeys))\n {\n for (const key of excludeKeys) { delete position[key]; }\n }\n\n return position;\n }\n else\n {\n const data = Object.assign(position, this.#data);\n\n // Remove any excluded keys.\n if (isIterable(excludeKeys))\n {\n for (const key of excludeKeys) { delete data[key]; }\n }\n\n // Potentially set numeric defaults.\n if (numeric) { constants.setNumericDefaults(data); }\n\n return data;\n }\n }\n\n /**\n * @returns {PositionData} Current position data.\n */\n toJSON()\n {\n return Object.assign({}, this.#data);\n }\n\n /**\n * All calculation and updates of position are implemented in {@link Position}. This allows position to be fully\n * reactive and in control of updating inline styles for the application.\n *\n * Note: the logic for updating position is improved and changes a few aspects from the default\n * {@link Application.setPosition}. The gate on `popOut` is removed, so to ensure no positional application occurs\n * popOut applications can set `this.options.positionable` to false ensuring no positional inline styles are\n * applied.\n *\n * The initial set call on an application with a target element will always set width / height as this is\n * necessary for correct calculations.\n *\n * When a target element is present updated styles are applied after validation. To modify the behavior of set\n * implement one or more validator functions and add them from the application via\n * `this.position.validators.add()`.\n *\n * Updates to any target element are decoupled from the underlying Position data. This method returns this instance\n * that you can then await on the target element inline style update by using {@link Position.elementUpdated}.\n *\n * @param {PositionDataExtended} [position] - Position data to set.\n *\n * @returns {Position} This Position instance.\n */\n set(position = {})\n {\n if (typeof position !== 'object') { throw new TypeError(`Position - set error: 'position' is not an object.`); }\n\n const parent = this.#parent;\n\n // An early out to prevent `set` from taking effect if options `positionable` is false.\n if (parent !== void 0 && typeof parent?.options?.positionable === 'boolean' && !parent?.options?.positionable)\n {\n return this;\n }\n\n // Callers can specify to immediately update an associated element. This is useful if set is called from\n // requestAnimationFrame / rAF. Library integrations like GSAP invoke set from rAF.\n const immediateElementUpdate = position.immediateElementUpdate === true;\n\n const data = this.#data;\n const transforms = this.#transforms;\n\n // Find the target HTML element and verify that it is connected storing it in `el`.\n const targetEl = parent instanceof HTMLElement ? parent : parent?.elementTarget;\n const el = targetEl instanceof HTMLElement && targetEl.isConnected ? targetEl : void 0;\n\n const changeSet = this.#positionChangeSet;\n const styleCache = this.#styleCache;\n\n if (el)\n {\n // Cache the computed styles of the element.\n if (!styleCache.hasData(el))\n {\n styleCache.update(el);\n\n // Add will-change property if not already set in inline or computed styles.\n if (!styleCache.hasWillChange)\n {\n el.style.willChange = this.#options.ortho ? 'transform' : 'top, left, transform';\n }\n\n // Update all properties / clear queued state.\n changeSet.set(true);\n this.#updateElementData.queued = false;\n }\n\n // Converts any relative string position data to numeric inputs.\n convertRelative(position, this);\n\n position = this.#updatePosition(position, parent, el, styleCache);\n\n // Check if a validator cancelled the update.\n if (position === null) { return this; }\n }\n\n if (Number.isFinite(position.left))\n {\n position.left = Math.round(position.left);\n\n if (data.left !== position.left) { data.left = position.left; changeSet.left = true; }\n }\n\n if (Number.isFinite(position.top))\n {\n position.top = Math.round(position.top);\n\n if (data.top !== position.top) { data.top = position.top; changeSet.top = true; }\n }\n\n if (Number.isFinite(position.maxHeight) || position.maxHeight === null)\n {\n position.maxHeight = typeof position.maxHeight === 'number' ? Math.round(position.maxHeight) : null;\n\n if (data.maxHeight !== position.maxHeight) { data.maxHeight = position.maxHeight; changeSet.maxHeight = true; }\n }\n\n if (Number.isFinite(position.maxWidth) || position.maxWidth === null)\n {\n position.maxWidth = typeof position.maxWidth === 'number' ? Math.round(position.maxWidth) : null;\n\n if (data.maxWidth !== position.maxWidth) { data.maxWidth = position.maxWidth; changeSet.maxWidth = true; }\n }\n\n if (Number.isFinite(position.minHeight) || position.minHeight === null)\n {\n position.minHeight = typeof position.minHeight === 'number' ? Math.round(position.minHeight) : null;\n\n if (data.minHeight !== position.minHeight) { data.minHeight = position.minHeight; changeSet.minHeight = true; }\n }\n\n if (Number.isFinite(position.minWidth) || position.minWidth === null)\n {\n position.minWidth = typeof position.minWidth === 'number' ? Math.round(position.minWidth) : null;\n\n if (data.minWidth !== position.minWidth) { data.minWidth = position.minWidth; changeSet.minWidth = true; }\n }\n\n if (Number.isFinite(position.rotateX) || position.rotateX === null)\n {\n if (data.rotateX !== position.rotateX)\n {\n data.rotateX = transforms.rotateX = position.rotateX;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.rotateY) || position.rotateY === null)\n {\n if (data.rotateY !== position.rotateY)\n {\n data.rotateY = transforms.rotateY = position.rotateY;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.rotateZ) || position.rotateZ === null)\n {\n if (data.rotateZ !== position.rotateZ)\n {\n data.rotateZ = transforms.rotateZ = position.rotateZ;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.scale) || position.scale === null)\n {\n position.scale = typeof position.scale === 'number' ? Math.max(0, Math.min(position.scale, 1000)) : null;\n\n if (data.scale !== position.scale)\n {\n data.scale = transforms.scale = position.scale;\n changeSet.transform = true;\n }\n }\n\n if ((typeof position.transformOrigin === 'string' && constants.transformOrigins.includes(\n position.transformOrigin)) || position.transformOrigin === null)\n {\n if (data.transformOrigin !== position.transformOrigin)\n {\n data.transformOrigin = position.transformOrigin;\n changeSet.transformOrigin = true;\n }\n }\n\n if (Number.isFinite(position.translateX) || position.translateX === null)\n {\n if (data.translateX !== position.translateX)\n {\n data.translateX = transforms.translateX = position.translateX;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.translateY) || position.translateY === null)\n {\n if (data.translateY !== position.translateY)\n {\n data.translateY = transforms.translateY = position.translateY;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.translateZ) || position.translateZ === null)\n {\n if (data.translateZ !== position.translateZ)\n {\n data.translateZ = transforms.translateZ = position.translateZ;\n changeSet.transform = true;\n }\n }\n\n if (Number.isFinite(position.zIndex))\n {\n position.zIndex = Math.round(position.zIndex);\n\n if (data.zIndex !== position.zIndex) { data.zIndex = position.zIndex; changeSet.zIndex = true; }\n }\n\n if (Number.isFinite(position.width) || position.width === 'auto' || position.width === 'inherit' ||\n position.width === null)\n {\n position.width = typeof position.width === 'number' ? Math.round(position.width) : position.width;\n\n if (data.width !== position.width) { data.width = position.width; changeSet.width = true; }\n }\n\n if (Number.isFinite(position.height) || position.height === 'auto' || position.height === 'inherit' ||\n position.height === null)\n {\n position.height = typeof position.height === 'number' ? Math.round(position.height) : position.height;\n\n if (data.height !== position.height) { data.height = position.height; changeSet.height = true; }\n }\n\n if (el)\n {\n const defaultData = this.#state.getDefault();\n\n // Set default data after first set operation that has a target element.\n if (typeof defaultData !== 'object')\n {\n this.#state.save({ name: '#defaultData', ...Object.assign({}, data) });\n }\n\n // If `immediateElementUpdate` is true in position data passed to `set` then update the element immediately.\n // This is for rAF based library integrations like GSAP.\n if (immediateElementUpdate)\n {\n UpdateElementManager.immediate(el, this.#updateElementData);\n this.#updateElementPromise = Promise.resolve(performance.now());\n }\n // Else if not queued then queue an update for the next rAF callback.\n else if (!this.#updateElementData.queued)\n {\n this.#updateElementPromise = UpdateElementManager.add(el, this.#updateElementData);\n }\n }\n else\n {\n // Notify main store subscribers.\n UpdateElementManager.updateSubscribers(this.#updateElementData);\n }\n\n return this;\n }\n\n /**\n *\n * @param {function(PositionData): void} handler - Callback function that is invoked on update / changes. Receives\n * a copy of the PositionData.\n *\n * @returns {(function(): void)} Unsubscribe function.\n */\n subscribe(handler)\n {\n this.#subscriptions.push(handler); // add handler to the array of subscribers\n\n handler(Object.assign({}, this.#data)); // call handler with current value\n\n // Return unsubscribe function.\n return () =>\n {\n const index = this.#subscriptions.findIndex((sub) => sub === handler);\n if (index >= 0) { this.#subscriptions.splice(index, 1); }\n };\n }\n\n /**\n * @param {PositionDataExtended} opts -\n *\n * @param {number|null} opts.left -\n *\n * @param {number|null} opts.top -\n *\n * @param {number|null} opts.maxHeight -\n *\n * @param {number|null} opts.maxWidth -\n *\n * @param {number|null} opts.minHeight -\n *\n * @param {number|null} opts.minWidth -\n *\n * @param {number|'auto'|null} opts.width -\n *\n * @param {number|'auto'|null} opts.height -\n *\n * @param {number|null} opts.rotateX -\n *\n * @param {number|null} opts.rotateY -\n *\n * @param {number|null} opts.rotateZ -\n *\n * @param {number|null} opts.scale -\n *\n * @param {string} opts.transformOrigin -\n *\n * @param {number|null} opts.translateX -\n *\n * @param {number|null} opts.translateY -\n *\n * @param {number|null} opts.translateZ -\n *\n * @param {number|null} opts.zIndex -\n *\n * @param {number|null} opts.rotation - alias for rotateZ\n *\n * @param {*} opts.rest -\n *\n * @param {object} parent -\n *\n * @param {HTMLElement} el -\n *\n * @param {StyleCache} styleCache -\n *\n * @returns {null|PositionData} Updated position data or null if validation fails.\n */\n #updatePosition({\n // Directly supported parameters\n left, top, maxWidth, maxHeight, minWidth, minHeight, width, height, rotateX, rotateY, rotateZ, scale,\n transformOrigin, translateX, translateY, translateZ, zIndex,\n\n // Aliased parameters\n rotation,\n\n ...rest\n } = {}, parent, el, styleCache)\n {\n let currentPosition = s_DATA_UPDATE.copy(this.#data);\n\n // Update width if an explicit value is passed, or if no width value is set on the element.\n if (el.style.width === '' || width !== void 0)\n {\n if (width === 'auto' || (currentPosition.width === 'auto' && width !== null))\n {\n currentPosition.width = 'auto';\n width = styleCache.offsetWidth;\n }\n else if (width === 'inherit' || (currentPosition.width === 'inherit' && width !== null))\n {\n currentPosition.width = 'inherit';\n width = styleCache.offsetWidth;\n }\n else\n {\n const newWidth = Number.isFinite(width) ? width : currentPosition.width;\n currentPosition.width = width = Number.isFinite(newWidth) ? Math.round(newWidth) : styleCache.offsetWidth;\n }\n }\n else\n {\n width = Number.isFinite(currentPosition.width) ? currentPosition.width : styleCache.offsetWidth;\n }\n\n // Update height if an explicit value is passed, or if no height value is set on the element.\n if (el.style.height === '' || height !== void 0)\n {\n if (height === 'auto' || (currentPosition.height === 'auto' && height !== null))\n {\n currentPosition.height = 'auto';\n height = styleCache.offsetHeight;\n }\n else if (height === 'inherit' || (currentPosition.height === 'inherit' && height !== null))\n {\n currentPosition.height = 'inherit';\n height = styleCache.offsetHeight;\n }\n else\n {\n const newHeight = Number.isFinite(height) ? height : currentPosition.height;\n currentPosition.height = height = Number.isFinite(newHeight) ? Math.round(newHeight) :\n styleCache.offsetHeight;\n }\n }\n else\n {\n height = Number.isFinite(currentPosition.height) ? currentPosition.height : styleCache.offsetHeight;\n }\n\n // Update left\n if (Number.isFinite(left))\n {\n currentPosition.left = left;\n }\n else if (!Number.isFinite(currentPosition.left))\n {\n // Potentially use any initial position helper if available or set to 0.\n currentPosition.left = typeof this.#options.initialHelper?.getLeft === 'function' ?\n this.#options.initialHelper.getLeft(width) : 0;\n }\n\n // Update top\n if (Number.isFinite(top))\n {\n currentPosition.top = top;\n }\n else if (!Number.isFinite(currentPosition.top))\n {\n // Potentially use any initial position helper if available or set to 0.\n currentPosition.top = typeof this.#options.initialHelper?.getTop === 'function' ?\n this.#options.initialHelper.getTop(height) : 0;\n }\n\n if (Number.isFinite(maxHeight) || maxHeight === null)\n {\n currentPosition.maxHeight = Number.isFinite(maxHeight) ? Math.round(maxHeight) : null;\n }\n\n if (Number.isFinite(maxWidth) || maxWidth === null)\n {\n currentPosition.maxWidth = Number.isFinite(maxWidth) ? Math.round(maxWidth) : null;\n }\n\n if (Number.isFinite(minHeight) || minHeight === null)\n {\n currentPosition.minHeight = Number.isFinite(minHeight) ? Math.round(minHeight) : null;\n }\n\n if (Number.isFinite(minWidth) || minWidth === null)\n {\n currentPosition.minWidth = Number.isFinite(minWidth) ? Math.round(minWidth) : null;\n }\n\n // Update rotate X/Y/Z, scale, z-index\n if (Number.isFinite(rotateX) || rotateX === null) { currentPosition.rotateX = rotateX; }\n if (Number.isFinite(rotateY) || rotateY === null) { currentPosition.rotateY = rotateY; }\n\n // Handle alias for rotateZ. First check if `rotateZ` is valid and different from the current value. Next check if\n // `rotation` is valid and use it for `rotateZ`.\n if (rotateZ !== currentPosition.rotateZ && (Number.isFinite(rotateZ) || rotateZ === null))\n {\n currentPosition.rotateZ = rotateZ;\n }\n else if (rotation !== currentPosition.rotateZ && (Number.isFinite(rotation) || rotation === null))\n {\n currentPosition.rotateZ = rotation;\n }\n\n if (Number.isFinite(translateX) || translateX === null) { currentPosition.translateX = translateX; }\n if (Number.isFinite(translateY) || translateY === null) { currentPosition.translateY = translateY; }\n if (Number.isFinite(translateZ) || translateZ === null) { currentPosition.translateZ = translateZ; }\n\n if (Number.isFinite(scale) || scale === null)\n {\n currentPosition.scale = typeof scale === 'number' ? Math.max(0, Math.min(scale, 1000)) : null;\n }\n\n if (typeof transformOrigin === 'string' || transformOrigin === null)\n {\n currentPosition.transformOrigin = constants.transformOrigins.includes(transformOrigin) ? transformOrigin :\n null;\n }\n\n if (Number.isFinite(zIndex) || zIndex === null)\n {\n currentPosition.zIndex = typeof zIndex === 'number' ? Math.round(zIndex) : zIndex;\n }\n\n const validatorData = this.#validatorData;\n\n // If there are any validators allow them to potentially modify position data or reject the update.\n if (validatorData.length)\n {\n s_VALIDATION_DATA.parent = parent;\n\n s_VALIDATION_DATA.el = el;\n\n s_VALIDATION_DATA.computed = styleCache.computed;\n\n s_VALIDATION_DATA.transforms = this.#transforms;\n\n s_VALIDATION_DATA.height = height;\n\n s_VALIDATION_DATA.width = width;\n\n s_VALIDATION_DATA.marginLeft = styleCache.marginLeft;\n\n s_VALIDATION_DATA.marginTop = styleCache.marginTop;\n\n s_VALIDATION_DATA.maxHeight = styleCache.maxHeight ?? currentPosition.maxHeight;\n\n s_VALIDATION_DATA.maxWidth = styleCache.maxWidth ?? currentPosition.maxWidth;\n\n // Given a parent w/ reactive state and is minimized ignore styleCache min-width/height.\n const isMinimized = parent?.reactive?.minimized ?? false;\n\n // Note the use of || for accessing the style cache as the left hand is ignored w/ falsy values such as '0'.\n s_VALIDATION_DATA.minHeight = isMinimized ? currentPosition.minHeight ?? 0 :\n styleCache.minHeight || (currentPosition.minHeight ?? 0);\n\n s_VALIDATION_DATA.minWidth = isMinimized ? currentPosition.minWidth ?? 0 :\n styleCache.minWidth || (currentPosition.minWidth ?? 0);\n\n for (let cntr = 0; cntr < validatorData.length; cntr++)\n {\n s_VALIDATION_DATA.position = currentPosition;\n s_VALIDATION_DATA.rest = rest;\n currentPosition = validatorData[cntr].validator(s_VALIDATION_DATA);\n\n if (currentPosition === null) { return null; }\n }\n }\n\n // Return the updated position object.\n return currentPosition;\n }\n}\n\nconst s_DATA_UPDATE = new PositionData();\n\n/**\n * @type {ValidationData}\n */\nconst s_VALIDATION_DATA = {\n position: void 0,\n parent: void 0,\n el: void 0,\n computed: void 0,\n transforms: void 0,\n height: void 0,\n width: void 0,\n marginLeft: void 0,\n marginTop: void 0,\n maxHeight: void 0,\n maxWidth: void 0,\n minHeight: void 0,\n minWidth: void 0,\n rest: void 0\n};\n\nObject.seal(s_VALIDATION_DATA);\n\n/**\n * @typedef {object} InitialHelper\n *\n * @property {Function} getLeft - A function that takes the width parameter and returns the left position.\n *\n * @property {Function} getTop - A function that takes the height parameter and returns the top position.\n */\n\n/**\n * @typedef {object} PositionDataExtended\n *\n * @property {number|string|null} [height] -\n *\n * @property {number|string|null} [left] -\n *\n * @property {number|string|null} [maxHeight] -\n *\n * @property {number|string|null} [maxWidth] -\n *\n * @property {number|string|null} [minHeight] -\n *\n * @property {number|string|null} [minWidth] -\n *\n * @property {number|string|null} [rotateX] -\n *\n * @property {number|string|null} [rotateY] -\n *\n * @property {number|string|null} [rotateZ] -\n *\n * @property {number|string|null} [scale] -\n *\n * @property {number|string|null} [top] -\n *\n * @property {string|null} [transformOrigin] -\n *\n * @property {number|string|null} [translateX] -\n *\n * @property {number|string|null} [translateY] -\n *\n * @property {number|string|null} [translateZ] -\n *\n * @property {number|string|null} [width] -\n *\n * @property {number|string|null} [zIndex] -\n *\n * Extended properties -----------------------------------------------------------------------------------------------\n *\n * @property {boolean} [immediateElementUpdate] - When true any associated element is updated immediately.\n *\n * @property {number|null} [rotation] - Alias for `rotateZ`.\n */\n\n/**\n * @typedef {object} PositionGetOptions\n *\n * @property {Iterable} keys - When provided only these keys are copied.\n *\n * @property {Iterable} exclude - When provided these keys are excluded.\n *\n * @property {boolean} numeric - When true any `null` values are converted into defaults.\n */\n\n/**\n * @typedef {object} PositionOptions - Options set in constructor.\n *\n * @property {boolean} calculateTransform - When true always calculate transform data.\n *\n * @property {InitialHelper} initialHelper - Provides a helper for setting initial position data.\n *\n * @property {boolean} ortho - Sets Position to orthographic mode using just transform / matrix3d for positioning.\n *\n * @property {boolean} transformSubscribed - Set to true when there are subscribers to the readable transform store.\n */\n\n/**\n * @typedef {PositionOptions & PositionData} PositionOptionsAll\n */\n\n/**\n * @typedef {HTMLElement | object} PositionParent\n *\n * @property {Function} [elementTarget] - Potentially returns any parent object.\n */\n\n/**\n * @typedef {object} ResizeObserverData\n *\n * @property {number|undefined} contentHeight -\n *\n * @property {number|undefined} contentWidth -\n *\n * @property {number|undefined} offsetHeight -\n *\n * @property {number|undefined} offsetWidth -\n */\n\n/**\n * @typedef {object} StorePosition - Provides individual writable stores for {@link Position}.\n *\n * @property {import('svelte/store').Readable<{width: number, height: number}>} dimension - Readable store for dimension\n * data.\n *\n * @property {import('svelte/store').Readable} element - Readable store for current element.\n *\n * @property {import('svelte/store').Writable} left - Derived store for `left` updates.\n *\n * @property {import('svelte/store').Writable} top - Derived store for `top` updates.\n *\n * @property {import('svelte/store').Writable} width - Derived store for `width` updates.\n *\n * @property {import('svelte/store').Writable} height - Derived store for `height` updates.\n *\n * @property {import('svelte/store').Writable} maxHeight - Derived store for `maxHeight` updates.\n *\n * @property {import('svelte/store').Writable} maxWidth - Derived store for `maxWidth` updates.\n *\n * @property {import('svelte/store').Writable} minHeight - Derived store for `minHeight` updates.\n *\n * @property {import('svelte/store').Writable} minWidth - Derived store for `minWidth` updates.\n *\n * @property {import('svelte/store').Readable} resizeContentHeight - Readable store for `contentHeight`.\n *\n * @property {import('svelte/store').Readable} resizeContentWidth - Readable store for `contentWidth`.\n *\n * @property {import('svelte/store').Writable} resizeObserved - Protected store for resize observer updates.\n *\n * @property {import('svelte/store').Readable} resizeOffsetHeight - Readable store for `offsetHeight`.\n *\n * @property {import('svelte/store').Readable} resizeOffsetWidth - Readable store for `offsetWidth`.\n *\n * @property {import('svelte/store').Writable} rotate - Derived store for `rotate` updates.\n *\n * @property {import('svelte/store').Writable} rotateX - Derived store for `rotateX` updates.\n *\n * @property {import('svelte/store').Writable} rotateY - Derived store for `rotateY` updates.\n *\n * @property {import('svelte/store').Writable} rotateZ - Derived store for `rotateZ` updates.\n *\n * @property {import('svelte/store').Writable} scale - Derived store for `scale` updates.\n *\n * @property {import('svelte/store').Readable} transform - Readable store for transform data.\n *\n * @property {import('svelte/store').Writable} transformOrigin - Derived store for `transformOrigin`.\n *\n * @property {import('svelte/store').Writable} translateX - Derived store for `translateX` updates.\n *\n * @property {import('svelte/store').Writable} translateY - Derived store for `translateY` updates.\n *\n * @property {import('svelte/store').Writable} translateZ - Derived store for `translateZ` updates.\n *\n * @property {import('svelte/store').Writable} zIndex - Derived store for `zIndex` updates.\n */\n\n/**\n * @typedef {object} ValidationData\n *\n * @property {PositionData} position -\n *\n * @property {PositionParent} parent -\n *\n * @property {HTMLElement} el -\n *\n * @property {CSSStyleDeclaration} computed -\n *\n * @property {Transforms} transforms -\n *\n * @property {number} height -\n *\n * @property {number} width -\n *\n * @property {number|undefined} marginLeft -\n *\n * @property {number|undefined} marginTop -\n *\n * @property {number|undefined} maxHeight -\n *\n * @property {number|undefined} maxWidth -\n *\n * @property {number|undefined} minHeight -\n *\n * @property {number|undefined} minWidth -\n *\n * @property {object} rest - The rest of any data submitted to {@link Position.set}\n */\n","import { linear } from \"svelte/easing\";\nimport { lerp } from '@typhonjs-fvtt/runtime/svelte/math';\nimport { isObject } from '@typhonjs-fvtt/runtime/svelte/util';\n\nexport class ApplicationState\n{\n /** @type {ApplicationShellExt} */\n #application;\n\n /** @type {Map} */\n #dataSaved = new Map();\n\n /**\n * @param {ApplicationShellExt} application - The application.\n */\n constructor(application)\n {\n this.#application = application;\n }\n\n /**\n * Returns current application state along with any extra data passed into method.\n *\n * @param {object} [extra] - Extra data to add to application state.\n *\n * @returns {ApplicationData} Passed in object with current application state.\n */\n get(extra = {})\n {\n return Object.assign(extra, {\n position: this.#application?.position?.get(),\n beforeMinimized: this.#application?.position?.state.get({ name: '#beforeMinimized' }),\n options: Object.assign({}, this.#application?.options),\n ui: { minimized: this.#application?.reactive?.minimized }\n });\n }\n\n /**\n * Returns any stored save state by name.\n *\n * @param {string} name - Saved data set name.\n *\n * @returns {ApplicationData} The saved data set.\n */\n getSave({ name })\n {\n if (typeof name !== 'string')\n {\n throw new TypeError(`ApplicationState - getSave error: 'name' is not a string.`);\n }\n\n return this.#dataSaved.get(name);\n }\n\n /**\n * Removes and returns any application state by name.\n *\n * @param {object} options - Options.\n *\n * @param {string} options.name - Name to remove and retrieve.\n *\n * @returns {ApplicationData} Saved application data.\n */\n remove({ name })\n {\n if (typeof name !== 'string') { throw new TypeError(`ApplicationState - remove: 'name' is not a string.`); }\n\n const data = this.#dataSaved.get(name);\n this.#dataSaved.delete(name);\n\n return data;\n }\n\n /**\n * Restores a saved application state returning the data. Several optional parameters are available\n * to control whether the restore action occurs silently (no store / inline styles updates), animates\n * to the stored data, or simply sets the stored data. Restoring via {@link AnimationAPI.to} allows\n * specification of the duration, easing, and interpolate functions along with configuring a Promise to be\n * returned if awaiting the end of the animation.\n *\n * @param {object} params - Parameters\n *\n * @param {string} params.name - Saved data set name.\n *\n * @param {boolean} [params.remove=false] - Remove data set.\n *\n * @param {boolean} [params.async=false] - If animating return a Promise that resolves with any saved data.\n *\n * @param {boolean} [params.animateTo=false] - Animate to restore data.\n *\n * @param {number} [params.duration=0.1] - Duration in seconds.\n *\n * @param {Function} [params.ease=linear] - Easing function.\n *\n * @param {Function} [params.interpolate=lerp] - Interpolation function.\n *\n * @returns {ApplicationData|Promise} Saved application data.\n */\n restore({ name, remove = false, async = false, animateTo = false, duration = 0.1, ease = linear,\n interpolate = lerp })\n {\n if (typeof name !== 'string')\n {\n throw new TypeError(`ApplicationState - restore error: 'name' is not a string.`);\n }\n\n const dataSaved = this.#dataSaved.get(name);\n\n if (dataSaved)\n {\n if (remove) { this.#dataSaved.delete(name); }\n\n if (async)\n {\n return this.set(dataSaved, { async, animateTo, duration, ease, interpolate }).then(() => dataSaved);\n }\n else\n {\n this.set(dataSaved, { async, animateTo, duration, ease, interpolate });\n }\n }\n\n return dataSaved;\n }\n\n /**\n * Saves current application state with the opportunity to add extra data to the saved state.\n *\n * @param {object} options - Options.\n *\n * @param {string} options.name - name to index this saved data.\n *\n * @param {...*} [options.extra] - Extra data to add to saved data.\n *\n * @returns {ApplicationData} Current application data\n */\n save({ name, ...extra })\n {\n if (typeof name !== 'string') { throw new TypeError(`ApplicationState - save error: 'name' is not a string.`); }\n\n const data = this.get(extra);\n\n this.#dataSaved.set(name, data);\n\n return data;\n }\n\n /**\n * Restores a saved application state returning the data. Several optional parameters are available\n * to control whether the restore action occurs silently (no store / inline styles updates), animates\n * to the stored data, or simply sets the stored data. Restoring via {@link AnimationAPI.to} allows\n * specification of the duration, easing, and interpolate functions along with configuring a Promise to be\n * returned if awaiting the end of the animation.\n *\n * Note: If serializing application state any minimized apps will use the before minimized state on initial render\n * of the app as it is currently not possible to render apps with Foundry VTT core API in the minimized state.\n *\n * TODO: THIS METHOD NEEDS TO BE REFACTORED WHEN TRL IS MADE INTO A STANDALONE FRAMEWORK.\n *\n * @param {ApplicationData} data - Saved data set name.\n *\n * @param {object} [opts] - Optional parameters\n *\n * @param {boolean} [opts.async=false] - If animating return a Promise that resolves with any saved data.\n *\n * @param {boolean} [opts.animateTo=false] - Animate to restore data.\n *\n * @param {number} [opts.duration=0.1] - Duration in seconds.\n *\n * @param {Function} [opts.ease=linear] - Easing function.\n *\n * @param {Function} [opts.interpolate=lerp] - Interpolation function.\n *\n * @returns {ApplicationShellExt|Promise} When synchronous the application or Promise when\n * animating resolving with application.\n */\n set(data, { async = false, animateTo = false, duration = 0.1, ease = linear, interpolate = lerp } = {})\n {\n if (!isObject(data))\n {\n throw new TypeError(`ApplicationState - restore error: 'data' is not an object.`);\n }\n\n const application = this.#application;\n\n if (!isObject(data?.position))\n {\n console.warn(`ApplicationState.set warning: 'data.position' is not an object.`);\n return application;\n }\n\n // TODO: TAKE NOTE THAT WE ARE ACCESSING A FOUNDRY APP v1 GETTER HERE TO DETERMINE IF APPLICATION IS RENDERED.\n // TODO: THIS NEEDS TO BE REFACTORED WHEN CONVERTING TRL TO A GENERIC FRAMEWORK.\n const rendered = application.rendered;\n\n if (animateTo && !rendered)\n {\n console.warn(`ApplicationState.set warning: Application is not rendered and 'animateTo' is true.`);\n return application;\n }\n\n // Update data directly with no store or inline style updates.\n if (animateTo) // Animate to saved data.\n {\n // Provide special handling to potentially change transform origin as this parameter is not animated.\n if (data.position.transformOrigin !== application.position.transformOrigin)\n {\n application.position.transformOrigin = data.position.transformOrigin;\n }\n\n if (isObject(data?.ui))\n {\n const minimized = typeof data.ui?.minimized === 'boolean' ? data.ui.minimized : false;\n\n if (application?.reactive?.minimized && !minimized)\n {\n application.maximize({ animate: false, duration: 0 });\n }\n }\n\n const promise = application.position.animate.to(data.position,\n { duration, ease, interpolate }).finished.then((cancelled) =>\n {\n if (cancelled) { return application; }\n\n // Merge in saved options to application.\n if (isObject(data?.options))\n {\n application?.reactive.mergeOptions(data.options);\n }\n\n if (isObject(data?.ui))\n {\n const minimized = typeof data.ui?.minimized === 'boolean' ? data.ui.minimized : false;\n\n // Application is currently minimized and stored state is not, so reset minimized state without\n // animation.\n if (!application?.reactive?.minimized && minimized)\n {\n application.minimize({ animate: false, duration: 0 });\n }\n }\n\n if (isObject(data?.beforeMinimized))\n {\n application.position.state.set({ name: '#beforeMinimized', ...data.beforeMinimized });\n }\n\n return application;\n });\n\n // Return a Promise with the application that resolves after animation ends.\n if (async) { return promise; }\n }\n else\n {\n if (rendered)\n {\n // Merge in saved options to application.\n if (isObject(data?.options))\n {\n application?.reactive.mergeOptions(data.options);\n }\n\n if (isObject(data?.ui))\n {\n const minimized = typeof data.ui?.minimized === 'boolean' ? data.ui.minimized : false;\n\n // Application is currently minimized and stored state is not, so reset minimized state without\n // animation.\n if (application?.reactive?.minimized && !minimized)\n {\n application.maximize({ animate: false, duration: 0 });\n }\n else if (!application?.reactive?.minimized && minimized)\n {\n application.minimize({ animate: false, duration });\n }\n }\n\n if (isObject(data?.beforeMinimized))\n {\n application.position.state.set({ name: '#beforeMinimized', ...data.beforeMinimized });\n }\n\n // Default options is to set data for an immediate update.\n application.position.set(data.position);\n }\n else\n {\n // When not rendered set position to the 'beforeMinimized' data if it exists otherwise set w/ 'position'.\n // Currently w/ Foundry core Application API it is impossible to initially render an app in the minimized\n // state.\n\n let positionData = data.position;\n\n if (isObject(data.beforeMinimized))\n {\n // Take before minimized data.\n positionData = data.beforeMinimized;\n\n // Apply position left / top to before minimized data. This covers the case when an app is minimized,\n // but then moved. This allows restoration of the before minimized parameters w/ the last position\n // location.\n positionData.left = data.position.left;\n positionData.top = data.position.top;\n }\n\n application.position.set(positionData);\n }\n }\n\n return application;\n }\n}\n\n/**\n * @typedef {object} ApplicationData\n *\n * @property {PositionDataExtended} position - Application position.\n *\n * @property {object} beforeMinimized - Any application saved position state for #beforeMinimized\n *\n * @property {object} options - Application options.\n *\n * @property {object} ui - Application UI state.\n */\n","/**\n * Provides a helper class for {@link SvelteApplication} by combining all methods that work on the {@link SvelteData[]}\n * of mounted components. This class is instantiated and can be retrieved by the getter `svelte` via SvelteApplication.\n */\nexport class GetSvelteData\n{\n /**\n * @type {MountedAppShell[]|null[]}\n */\n #applicationShellHolder;\n\n /**\n * @type {SvelteData[]}\n */\n #svelteData;\n\n /**\n * Keep a direct reference to the SvelteData array in an associated {@link SvelteApplication}.\n *\n * @param {MountedAppShell[]|null[]} applicationShellHolder - A reference to the MountedAppShell array.\n *\n * @param {SvelteData[]} svelteData - A reference to the SvelteData array of mounted components.\n */\n constructor(applicationShellHolder, svelteData)\n {\n this.#applicationShellHolder = applicationShellHolder;\n this.#svelteData = svelteData;\n }\n\n /**\n * Returns any mounted {@link MountedAppShell}.\n *\n * @returns {MountedAppShell|null} Any mounted application shell.\n */\n get applicationShell() { return this.#applicationShellHolder[0]; }\n\n /**\n * Returns the indexed Svelte component.\n *\n * @param {number} index -\n *\n * @returns {object} The loaded Svelte component.\n */\n component(index)\n {\n const data = this.#svelteData[index];\n return typeof data === 'object' ? data?.component : void 0;\n }\n\n /**\n * Returns the Svelte component entries iterator.\n *\n * @returns {Generator>} Svelte component entries iterator.\n * @yields\n */\n *componentEntries()\n {\n for (let cntr = 0; cntr < this.#svelteData.length; cntr++)\n {\n yield [cntr, this.#svelteData[cntr].component];\n }\n }\n\n /**\n * Returns the Svelte component values iterator.\n *\n * @returns {Generator} Svelte component values iterator.\n * @yields\n */\n *componentValues()\n {\n for (let cntr = 0; cntr < this.#svelteData.length; cntr++)\n {\n yield this.#svelteData[cntr].component;\n }\n }\n\n /**\n * Returns the indexed SvelteData entry.\n *\n * @param {number} index -\n *\n * @returns {SvelteData} The loaded Svelte config + component.\n */\n data(index)\n {\n return this.#svelteData[index];\n }\n\n /**\n * Returns the {@link SvelteData} instance for a given component.\n *\n * @param {object} component - Svelte component.\n *\n * @returns {SvelteData} - The loaded Svelte config + component.\n */\n dataByComponent(component)\n {\n for (const data of this.#svelteData)\n {\n if (data.component === component) { return data; }\n }\n\n return void 0;\n }\n\n /**\n * Returns the SvelteData entries iterator.\n *\n * @returns {IterableIterator<[number, SvelteData]>} SvelteData entries iterator.\n */\n dataEntries()\n {\n return this.#svelteData.entries();\n }\n\n /**\n * Returns the SvelteData values iterator.\n *\n * @returns {IterableIterator} SvelteData values iterator.\n */\n dataValues()\n {\n return this.#svelteData.values();\n }\n\n /**\n * Returns the length of the mounted Svelte component list.\n *\n * @returns {number} Length of mounted Svelte component list.\n */\n get length()\n {\n return this.#svelteData.length;\n }\n}\n","import {\n isApplicationShell,\n parseSvelteConfig } from '@typhonjs-fvtt/runtime/svelte/util';\n\n/**\n * Instantiates and attaches a Svelte component to the main inserted HTML.\n *\n * @param {object} opts - Optional parameters.\n *\n * @param {object} opts.app - The target application\n *\n * @param {HTMLElement} opts.template - Any HTML template.\n *\n * @param {object} opts.config - Svelte component options\n *\n * @param {Function} opts.elementRootUpdate - A callback to assign to the external context.\n *\n * @returns {SvelteData} The config + instantiated Svelte component.\n */\nexport function loadSvelteConfig({ app, template, config, elementRootUpdate } = {})\n{\n const svelteOptions = typeof config.options === 'object' ? config.options : {};\n\n let target;\n\n // A specific HTMLElement to append Svelte component.\n if (config.target instanceof HTMLElement)\n {\n target = config.target;\n }\n // A string target defines a selector to find in existing HTML.\n else if (template instanceof HTMLElement && typeof config.target === 'string')\n {\n target = template.querySelector(config.target);\n }\n else // No target defined, create a document fragment.\n {\n target = document.createDocumentFragment();\n }\n\n if (target === void 0)\n {\n console.log(\n `%c[TRL] loadSvelteConfig error - could not find target selector, '${config.target}', for config:\\n`,\n 'background: rgb(57,34,34)', config);\n\n throw new Error();\n }\n\n const NewSvelteComponent = config.class;\n\n const svelteConfig = parseSvelteConfig({ ...config, target }, app);\n\n const externalContext = svelteConfig.context.get('external');\n\n // Inject the Foundry application instance and `elementRootUpdate` to the external context.\n externalContext.application = app;\n externalContext.elementRootUpdate = elementRootUpdate;\n\n let eventbus;\n\n // Potentially inject any TyphonJS eventbus and track the proxy in the SvelteData instance.\n if (typeof app._eventbus === 'object' && typeof app._eventbus.createProxy === 'function')\n {\n eventbus = app._eventbus.createProxy();\n externalContext.eventbus = eventbus;\n }\n\n // Create the Svelte component.\n /**\n * @type {import('svelte').SvelteComponent}\n */\n const component = new NewSvelteComponent(svelteConfig);\n\n // Set any eventbus to the config.\n svelteConfig.eventbus = eventbus;\n\n /**\n * @type {HTMLElement}\n */\n let element;\n\n // We can directly get the root element from components which follow the application store contract.\n if (isApplicationShell(component))\n {\n element = component.elementRoot;\n }\n\n // Detect if target is a synthesized DocumentFragment with a child element. Child elements will be present\n // if the Svelte component mounts and renders initial content into the document fragment.\n if (target instanceof DocumentFragment && target.firstElementChild)\n {\n if (element === void 0) { element = target.firstElementChild; }\n template.append(target);\n }\n else if (config.target instanceof HTMLElement && element === void 0)\n {\n if (config.target instanceof HTMLElement && typeof svelteOptions.selectorElement !== 'string')\n {\n console.log(\n `%c[TRL] loadSvelteConfig error - HTMLElement target with no 'selectorElement' defined.\\n` +\n `\\nNote: If configuring an application shell and directly targeting a HTMLElement did you bind an` +\n `'elementRoot' and include ''?\\n` +\n `\\nOffending config:\\n`, 'background: rgb(57,34,34)', config);\n\n throw new Error();\n }\n\n // The target is an HTMLElement so find the Application element from `selectorElement` option.\n element = target.querySelector(svelteOptions.selectorElement);\n\n if (element === null || element === void 0)\n {\n console.log(\n `%c[TRL] loadSvelteConfig error - HTMLElement target with 'selectorElement', '${\n svelteOptions.selectorElement}', not found for config:\\n`,\n 'background: rgb(57,34,34)', config);\n\n throw new Error();\n }\n }\n\n // If the configuration / original target is an HTML element then do not inject HTML.\n const injectHTML = !(config.target instanceof HTMLElement);\n\n return { config: svelteConfig, component, element, injectHTML };\n}\n","import { derived, writable } from \"svelte/store\";\n\nimport {\n propertyStore,\n subscribeIgnoreFirst } from '@typhonjs-fvtt/runtime/svelte/store';\n\nimport {\n deepMerge,\n safeAccess,\n safeSet } from '@typhonjs-fvtt/runtime/svelte/util';\n\n/**\n * Contains the reactive functionality / Svelte stores associated with SvelteApplication.\n */\nexport class SvelteReactive\n{\n /**\n * @type {SvelteApplication}\n */\n #application;\n\n /**\n * @type {boolean}\n */\n #initialized = false;\n\n /**\n * The Application option store which is injected into mounted Svelte component context under the `external` key.\n *\n * @type {StoreAppOptions}\n */\n #storeAppOptions;\n\n /**\n * Stores the update function for `#storeAppOptions`.\n *\n * @type {import('svelte/store').Writable.update}\n */\n #storeAppOptionsUpdate;\n\n /**\n * Stores the UI state data to make it accessible via getters.\n *\n * @type {object}\n */\n #dataUIState;\n\n /**\n * The UI option store which is injected into mounted Svelte component context under the `external` key.\n *\n * @type {StoreUIOptions}\n */\n #storeUIState;\n\n /**\n * Stores the update function for `#storeUIState`.\n *\n * @type {import('svelte/store').Writable.update}\n */\n #storeUIStateUpdate;\n\n /**\n * Stores the unsubscribe functions from local store subscriptions.\n *\n * @type {import('svelte/store').Unsubscriber[]}\n */\n #storeUnsubscribe = [];\n\n /**\n * @param {SvelteApplication} application - The host Foundry application.\n */\n constructor(application)\n {\n this.#application = application;\n }\n\n /**\n * Initializes reactive support. Package private for internal use.\n *\n * @returns {SvelteStores} Internal methods to interact with Svelte stores.\n * @package\n */\n initialize()\n {\n if (this.#initialized) { return; }\n\n this.#initialized = true;\n\n this.#storesInitialize();\n\n return {\n appOptionsUpdate: this.#storeAppOptionsUpdate,\n uiOptionsUpdate: this.#storeUIStateUpdate,\n subscribe: this.#storesSubscribe.bind(this),\n unsubscribe: this.#storesUnsubscribe.bind(this)\n };\n }\n\n// Only reactive getters ---------------------------------------------------------------------------------------------\n\n /**\n * Returns the current dragging UI state.\n *\n * @returns {boolean} Dragging UI state.\n */\n get dragging() { return this.#dataUIState.dragging; }\n\n /**\n * Returns the current minimized UI state.\n *\n * @returns {boolean} Minimized UI state.\n */\n get minimized() { return this.#dataUIState.minimized; }\n\n /**\n * Returns the current resizing UI state.\n *\n * @returns {boolean} Resizing UI state.\n */\n get resizing() { return this.#dataUIState.resizing; }\n\n// Reactive getter / setters -----------------------------------------------------------------------------------------\n\n /**\n * Returns the draggable app option.\n *\n * @returns {boolean} Draggable app option.\n */\n get draggable() { return this.#application?.options?.draggable; }\n\n /**\n * Returns the headerButtonNoClose app option.\n *\n * @returns {boolean} Remove the close the button in header app option.\n */\n get headerButtonNoClose() { return this.#application?.options?.headerButtonNoClose; }\n\n /**\n * Returns the headerButtonNoLabel app option.\n *\n * @returns {boolean} Remove the labels from buttons in header app option.\n */\n get headerButtonNoLabel() { return this.#application?.options?.headerButtonNoLabel; }\n\n /**\n * Returns the headerNoTitleMinimized app option.\n *\n * @returns {boolean} When true removes the header title when minimized.\n */\n get headerNoTitleMinimized() { return this.#application?.options?.headerNoTitleMinimized; }\n\n /**\n * Returns the minimizable app option.\n *\n * @returns {boolean} Minimizable app option.\n */\n get minimizable() { return this.#application?.options?.minimizable; }\n\n /**\n * @inheritDoc\n */\n get popOut() { return this.#application.popOut; }\n\n /**\n * Returns the resizable option.\n *\n * @returns {boolean} Resizable app option.\n */\n get resizable() { return this.#application?.options?.resizable; }\n\n /**\n * Returns the store for app options.\n *\n * @returns {StoreAppOptions} App options store.\n */\n get storeAppOptions() { return this.#storeAppOptions; }\n\n /**\n * Returns the store for UI options.\n *\n * @returns {StoreUIOptions} UI options store.\n */\n get storeUIState() { return this.#storeUIState; }\n\n /**\n * Returns the title accessor from the parent Application class.\n * TODO: Application v2; note that super.title localizes `this.options.title`; IMHO it shouldn't.\n *\n * @returns {string} Title.\n */\n get title() { return this.#application.title; }\n\n /**\n * Sets `this.options.draggable` which is reactive for application shells.\n *\n * @param {boolean} draggable - Sets the draggable option.\n */\n set draggable(draggable)\n {\n if (typeof draggable === 'boolean') { this.setOptions('draggable', draggable); }\n }\n\n /**\n * Sets `this.options.headerButtonNoClose` which is reactive for application shells.\n *\n * @param {boolean} headerButtonNoClose - Sets the headerButtonNoClose option.\n */\n set headerButtonNoClose(headerButtonNoClose)\n {\n if (typeof headerButtonNoClose === 'boolean') { this.setOptions('headerButtonNoClose', headerButtonNoClose); }\n }\n\n /**\n * Sets `this.options.headerButtonNoLabel` which is reactive for application shells.\n *\n * @param {boolean} headerButtonNoLabel - Sets the headerButtonNoLabel option.\n */\n set headerButtonNoLabel(headerButtonNoLabel)\n {\n if (typeof headerButtonNoLabel === 'boolean') { this.setOptions('headerButtonNoLabel', headerButtonNoLabel); }\n }\n\n /**\n * Sets `this.options.headerNoTitleMinimized` which is reactive for application shells.\n *\n * @param {boolean} headerNoTitleMinimized - Sets the headerNoTitleMinimized option.\n */\n set headerNoTitleMinimized(headerNoTitleMinimized)\n {\n if (typeof headerNoTitleMinimized === 'boolean')\n {\n this.setOptions('headerNoTitleMinimized', headerNoTitleMinimized);\n }\n }\n\n /**\n * Sets `this.options.minimizable` which is reactive for application shells that are also pop out.\n *\n * @param {boolean} minimizable - Sets the minimizable option.\n */\n set minimizable(minimizable)\n {\n if (typeof minimizable === 'boolean') { this.setOptions('minimizable', minimizable); }\n }\n\n /**\n * Sets `this.options.popOut` which is reactive for application shells. This will add / remove this application\n * from `ui.windows`.\n *\n * @param {boolean} popOut - Sets the popOut option.\n */\n set popOut(popOut)\n {\n if (typeof popOut === 'boolean') { this.setOptions('popOut', popOut); }\n }\n\n /**\n * Sets `this.options.resizable` which is reactive for application shells.\n *\n * @param {boolean} resizable - Sets the resizable option.\n */\n set resizable(resizable)\n {\n if (typeof resizable === 'boolean') { this.setOptions('resizable', resizable); }\n }\n\n /**\n * Sets `this.options.title` which is reactive for application shells.\n *\n * Note: Will set empty string if title is undefined or null.\n *\n * @param {string|undefined|null} title - Application title; will be localized, so a translation key is fine.\n */\n set title(title)\n {\n if (typeof title === 'string')\n {\n this.setOptions('title', title);\n }\n else if (title === void 0 || title === null)\n {\n this.setOptions('title', '');\n }\n }\n\n /**\n * Provides a way to safely get this applications options given an accessor string which describes the\n * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries\n * to walk.\n *\n * // TODO DOCUMENT the accessor in more detail.\n *\n * @param {string} accessor - The path / key to set. You can set multiple levels.\n *\n * @param {*} [defaultValue] - A default value returned if the accessor is not found.\n *\n * @returns {*} Value at the accessor.\n */\n getOptions(accessor, defaultValue)\n {\n return safeAccess(this.#application.options, accessor, defaultValue);\n }\n\n /**\n * Provides a way to merge `options` into this applications options and update the appOptions store.\n *\n * @param {object} options - The options object to merge with `this.options`.\n */\n mergeOptions(options)\n {\n this.#storeAppOptionsUpdate((instanceOptions) => deepMerge(instanceOptions, options));\n }\n\n /**\n * Provides a way to safely set this applications options given an accessor string which describes the\n * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries\n * to walk.\n *\n * Additionally if an application shell Svelte component is mounted and exports the `appOptions` property then\n * the application options is set to `appOptions` potentially updating the application shell / Svelte component.\n *\n * // TODO DOCUMENT the accessor in more detail.\n *\n * @param {string} accessor - The path / key to set. You can set multiple levels.\n *\n * @param {*} value - Value to set.\n */\n setOptions(accessor, value)\n {\n const success = safeSet(this.#application.options, accessor, value);\n\n // If `this.options` modified then update the app options store.\n if (success)\n {\n this.#storeAppOptionsUpdate(() => this.#application.options);\n }\n }\n\n /**\n * Initializes the Svelte stores and derived stores for the application options and UI state.\n *\n * While writable stores are created the update method is stored in private variables locally and derived Readable\n * stores are provided for essential options which are commonly used.\n *\n * These stores are injected into all Svelte components mounted under the `external` context: `storeAppOptions` and\n * ` storeUIState`.\n */\n #storesInitialize()\n {\n const writableAppOptions = writable(this.#application.options);\n\n // Keep the update function locally, but make the store essentially readable.\n this.#storeAppOptionsUpdate = writableAppOptions.update;\n\n /**\n * Create custom store. The main subscribe method for all app options changes is provided along with derived\n * writable stores for all reactive options.\n *\n * @type {StoreAppOptions}\n */\n const storeAppOptions = {\n subscribe: writableAppOptions.subscribe,\n\n draggable: propertyStore(writableAppOptions, 'draggable'),\n headerButtonNoClose: propertyStore(writableAppOptions, 'headerButtonNoClose'),\n headerButtonNoLabel: propertyStore(writableAppOptions, 'headerButtonNoLabel'),\n headerNoTitleMinimized: propertyStore(writableAppOptions, 'headerNoTitleMinimized'),\n minimizable: propertyStore(writableAppOptions, 'minimizable'),\n popOut: propertyStore(writableAppOptions, 'popOut'),\n resizable: propertyStore(writableAppOptions, 'resizable'),\n title: propertyStore(writableAppOptions, 'title')\n };\n\n Object.freeze(storeAppOptions);\n\n this.#storeAppOptions = storeAppOptions;\n\n this.#dataUIState = {\n dragging: false,\n headerButtons: [],\n minimized: this.#application._minimized,\n resizing: false\n };\n\n // Create a store for UI state data.\n const writableUIOptions = writable(this.#dataUIState);\n\n // Keep the update function locally, but make the store essentially readable.\n this.#storeUIStateUpdate = writableUIOptions.update;\n\n /**\n * @type {StoreUIOptions}\n */\n const storeUIState = {\n subscribe: writableUIOptions.subscribe,\n\n dragging: propertyStore(writableUIOptions, 'dragging'),\n headerButtons: derived(writableUIOptions, ($options, set) => set($options.headerButtons)),\n minimized: derived(writableUIOptions, ($options, set) => set($options.minimized)),\n resizing: propertyStore(writableUIOptions, 'resizing')\n };\n\n Object.freeze(storeUIState);\n\n // Initialize the store with options set in the Application constructor.\n this.#storeUIState = storeUIState;\n }\n\n /**\n * Registers local store subscriptions for app options. `popOut` controls registering this app with `ui.windows`.\n * `zIndex` controls the z-index style of the element root.\n *\n * @see SvelteApplication._injectHTML\n */\n #storesSubscribe()\n {\n // Register local subscriptions.\n\n // Handles updating header buttons to add / remove the close button.\n this.#storeUnsubscribe.push(subscribeIgnoreFirst(this.#storeAppOptions.headerButtonNoClose, (value) =>\n {\n this.updateHeaderButtons({ headerButtonNoClose: value });\n }));\n\n // Handles updating header buttons to add / remove button labels.\n this.#storeUnsubscribe.push(subscribeIgnoreFirst(this.#storeAppOptions.headerButtonNoLabel, (value) =>\n {\n this.updateHeaderButtons({ headerButtonNoLabel: value });\n }));\n\n // Handles adding / removing this application from `ui.windows` when popOut changes.\n this.#storeUnsubscribe.push(subscribeIgnoreFirst(this.#storeAppOptions.popOut, (value) =>\n {\n if (value && this.#application.rendered)\n {\n ui.windows[this.#application.appId] = this.#application;\n }\n else\n {\n delete ui.windows[this.#application.appId];\n }\n }));\n }\n\n /**\n * Unsubscribes from any locally monitored stores.\n *\n * @see SvelteApplication.close\n */\n #storesUnsubscribe()\n {\n this.#storeUnsubscribe.forEach((unsubscribe) => unsubscribe());\n this.#storeUnsubscribe = [];\n }\n\n /**\n * Updates the UI Options store with the current header buttons. You may dynamically add / remove header buttons\n * if using an application shell Svelte component. In either overriding `_getHeaderButtons` or responding to the\n * Hooks fired return a new button array and the uiOptions store is updated and the application shell will render\n * the new buttons.\n *\n * Optionally you can set in the Foundry app options `headerButtonNoClose` to remove the close button and\n * `headerButtonNoLabel` to true and labels will be removed from the header buttons.\n *\n * @param {object} opts - Optional parameters (for internal use)\n *\n * @param {boolean} opts.headerButtonNoClose - The value for `headerButtonNoClose`.\n *\n * @param {boolean} opts.headerButtonNoLabel - The value for `headerButtonNoLabel`.\n */\n updateHeaderButtons({ headerButtonNoClose = this.#application.options.headerButtonNoClose,\n headerButtonNoLabel = this.#application.options.headerButtonNoLabel } = {})\n {\n let buttons = this.#application._getHeaderButtons();\n\n // Remove close button if this.options.headerButtonNoClose is true;\n if (typeof headerButtonNoClose === 'boolean' && headerButtonNoClose)\n {\n buttons = buttons.filter((button) => button.class !== 'close');\n }\n\n // Remove labels if this.options.headerButtonNoLabel is true;\n if (typeof headerButtonNoLabel === 'boolean' && headerButtonNoLabel)\n {\n for (const button of buttons) { button.label = void 0; }\n }\n\n this.#storeUIStateUpdate((options) =>\n {\n options.headerButtons = buttons;\n return options;\n });\n }\n}\n","// import { Position } from '@typhonjs-fvtt/runtime/svelte/store';\nimport { Position } from './position/Position.js';\n\nimport {\n deepMerge,\n hasGetter,\n isApplicationShell,\n isHMRProxy,\n outroAndDestroy } from '@typhonjs-fvtt/runtime/svelte/util';\n\nimport {\n ApplicationState,\n GetSvelteData,\n loadSvelteConfig,\n SvelteReactive } from './internal/index.js';\n\n/**\n * Provides a Svelte aware extension to Application to control the app lifecycle appropriately. You can declaratively\n * load one or more components from `defaultOptions`.\n */\nexport class SvelteApplication extends Application\n{\n /**\n * Stores the first mounted component which follows the application shell contract.\n *\n * @type {MountedAppShell[]|null[]} Application shell.\n */\n #applicationShellHolder = [null];\n\n /**\n * Stores and manages application state for saving / restoring / serializing.\n *\n * @type {ApplicationState}\n */\n #applicationState;\n\n /**\n * Stores the target element which may not necessarily be the main element.\n *\n * @type {HTMLElement}\n */\n #elementTarget = null;\n\n /**\n * Stores the content element which is set for application shells.\n *\n * @type {HTMLElement}\n */\n #elementContent = null;\n\n /**\n * Stores initial z-index from `_renderOuter` to set to target element / Svelte component.\n *\n * @type {number}\n */\n #initialZIndex = 95;\n\n /**\n * Stores on mount state which is checked in _render to trigger onSvelteMount callback.\n *\n * @type {boolean}\n */\n #onMount = false;\n\n /**\n * The position store.\n *\n * @type {Position}\n */\n #position;\n\n /**\n * Contains the Svelte stores and reactive accessors.\n *\n * @type {SvelteReactive}\n */\n #reactive;\n\n /**\n * Stores SvelteData entries with instantiated Svelte components.\n *\n * @type {SvelteData[]}\n */\n #svelteData = [];\n\n /**\n * Provides a helper class that combines multiple methods for interacting with the mounted components tracked in\n * {@link SvelteData}.\n *\n * @type {GetSvelteData}\n */\n #getSvelteData = new GetSvelteData(this.#applicationShellHolder, this.#svelteData);\n\n /**\n * Contains methods to interact with the Svelte stores.\n *\n * @type {SvelteStores}\n */\n #stores;\n\n /**\n * @inheritDoc\n */\n constructor(options = {})\n {\n super(options);\n\n this.#applicationState = new ApplicationState(this);\n\n // Initialize Position with the position object set by Application.\n this.#position = new Position(this, {\n ...this.position,\n ...this.options,\n initial: this.options.positionInitial,\n ortho: this.options.positionOrtho,\n validator: this.options.positionValidator\n });\n\n // Remove old position field.\n delete this.position;\n\n /**\n * Define accessors to retrieve Position by `this.position`.\n *\n * @member {Position} position - Adds accessors to SvelteApplication to get / set the position data.\n *\n * @memberof SvelteApplication#\n */\n Object.defineProperty(this, 'position', {\n get: () => this.#position,\n set: (position) => { if (typeof position === 'object') { this.#position.set(position); } }\n });\n\n this.#reactive = new SvelteReactive(this);\n\n this.#stores = this.#reactive.initialize();\n }\n\n /**\n * Specifies the default options that SvelteApplication supports.\n *\n * @returns {object} options - Application options.\n * @see https://foundryvtt.com/api/Application.html#options\n */\n static get defaultOptions()\n {\n return deepMerge(super.defaultOptions, {\n defaultCloseAnimation: true, // If false the default slide close animation is not run.\n draggable: true, // If true then application shells are draggable.\n headerButtonNoClose: false, // If true then the close header button is removed.\n headerButtonNoLabel: false, // If true then header button labels are removed for application shells.\n headerNoTitleMinimized: false, // If true then header title is hidden when application is minimized.\n minHeight: MIN_WINDOW_HEIGHT, // Assigned to position. Number specifying minimum window height.\n minWidth: MIN_WINDOW_WIDTH, // Assigned to position. Number specifying minimum window width.\n positionable: true, // If false then `position.set` does not take effect.\n positionInitial: Position.Initial.browserCentered, // A helper for initial position placement.\n positionOrtho: true, // When true Position is optimized for orthographic use.\n positionValidator: Position.Validators.transformWindow, // A function providing the default validator.\n transformOrigin: 'top left' // By default, 'top / left' respects rotation when minimizing.\n });\n }\n\n /**\n * Returns the content element if an application shell is mounted.\n *\n * @returns {HTMLElement} Content element.\n */\n get elementContent() { return this.#elementContent; }\n\n /**\n * Returns the target element or main element if no target defined.\n *\n * @returns {HTMLElement} Target element.\n */\n get elementTarget() { return this.#elementTarget; }\n\n /**\n * Returns the reactive accessors & Svelte stores for SvelteApplication.\n *\n * @returns {SvelteReactive} The reactive accessors & Svelte stores.\n */\n get reactive() { return this.#reactive; }\n\n /**\n * Returns the application state manager.\n *\n * @returns {ApplicationState} The application state manager.\n */\n get state() { return this.#applicationState; }\n\n /**\n * Returns the Svelte helper class w/ various methods to access mounted Svelte components.\n *\n * @returns {GetSvelteData} GetSvelteData\n */\n get svelte() { return this.#getSvelteData; }\n\n /**\n * In this case of when a template is defined in app options `html` references the inner HTML / template. However,\n * to activate classic v1 tabs for a Svelte component the element target is passed as an array simulating JQuery as\n * the element is retrieved immediately and the core listeners use standard DOM queries.\n *\n * @inheritDoc\n * @protected\n * @ignore\n */\n _activateCoreListeners(html)\n {\n super._activateCoreListeners(typeof this.options.template === 'string' ? html : [this.#elementTarget]);\n }\n\n /**\n * Provide an override to set this application as the active window regardless of z-index. Changes behaviour from\n * Foundry core. This is important / used for instance in dialog key handling for left / right button selection.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {boolean} [opts.force=false] - Force bring to top; will increment z-index by popOut order.\n *\n */\n bringToTop({ force = false } = {})\n {\n if (force || this.popOut) { super.bringToTop(); }\n\n // If the activeElement is not `document.body` and not contained in this app via elementTarget then blur the\n // current active element and make `document.body`focused. This allows key to close all open apps / windows.\n if (document.activeElement !== document.body && !this.elementTarget.contains(document.activeElement))\n {\n // Blur current active element.\n if (document.activeElement instanceof HTMLElement) { document.activeElement.blur(); }\n\n // Make document body focused.\n document.body.focus();\n }\n\n ui.activeWindow = this;\n }\n\n /**\n * Note: This method is fully overridden and duplicated as Svelte components need to be destroyed manually and the\n * best visual result is to destroy them after the default slide up animation occurs, but before the element\n * is removed from the DOM.\n *\n * If you destroy the Svelte components before the slide up animation the Svelte elements are removed immediately\n * from the DOM. The purpose of overriding ensures the slide up animation is always completed before\n * the Svelte components are destroyed and then the element is removed from the DOM.\n *\n * Close the application and un-register references to it within UI mappings.\n * This function returns a Promise which resolves once the window closing animation concludes\n *\n * @param {object} [options] - Optional parameters.\n *\n * @param {boolean} [options.force] - Force close regardless of render state.\n *\n * @returns {Promise} A Promise which resolves once the application is closed.\n * @ignore\n */\n async close(options = {})\n {\n const states = Application.RENDER_STATES;\n if (!options.force && ![states.RENDERED, states.ERROR].includes(this._state)) { return; }\n\n // Unsubscribe from any local stores.\n this.#stores.unsubscribe();\n\n /**\n * @ignore\n */\n this._state = states.CLOSING;\n\n /**\n * Get the element.\n *\n * @type {HTMLElement}\n */\n const el = this.#elementTarget;\n if (!el) { return this._state = states.CLOSED; }\n\n // Make any window content overflow hidden to avoid any scrollbars appearing in default or Svelte outro\n // transitions.\n const content = el.querySelector('.window-content');\n if (content)\n {\n content.style.overflow = 'hidden';\n\n // Set all children of content to overflow hidden as if there is going to be additional scrolling elements\n // they are likely one level deep.\n for (let cntr = content.children.length; --cntr >= 0;)\n {\n content.children[cntr].style.overflow = 'hidden';\n }\n }\n\n // Dispatch Hooks for closing the base and subclass applications\n for (const cls of this.constructor._getInheritanceChain())\n {\n /**\n * A hook event that fires whenever this Application is closed.\n *\n * @param {Application} app The Application instance being closed\n *\n * @param {jQuery[]} html The application HTML when it is closed\n *\n * @function closeApplication\n *\n * @memberof hookEvents\n */\n Hooks.call(`close${cls.name}`, this, el);\n }\n\n // If options `defaultCloseAnimation` is false then do not execute the standard slide up animation.\n // This allows Svelte components to provide any out transition. Application shells will automatically set\n // `defaultCloseAnimation` based on any out transition set or unset.\n const animate = typeof this.options.defaultCloseAnimation === 'boolean' ? this.options.defaultCloseAnimation :\n true;\n\n if (animate)\n {\n // Set min height for full slide.\n el.style.minHeight = '0';\n\n const { paddingBottom, paddingTop } = globalThis.getComputedStyle(el);\n\n // Slide-up application.\n await el.animate([\n { maxHeight: `${el.clientHeight}px`, paddingTop, paddingBottom },\n { maxHeight: 0, paddingTop: 0, paddingBottom: 0 }\n ], { duration: 250, easing: 'ease-in', fill: 'forwards' }).finished;\n }\n\n // Stores the Promises returned from running outro transitions and destroying each Svelte component.\n const svelteDestroyPromises = [];\n\n // Manually invoke the destroy callbacks for all Svelte components.\n for (const entry of this.#svelteData)\n {\n // Use `outroAndDestroy` to run outro transitions before destroying.\n svelteDestroyPromises.push(outroAndDestroy(entry.component));\n\n // If any proxy eventbus has been added then remove all event registrations from the component.\n const eventbus = entry.config.eventbus;\n if (typeof eventbus === 'object' && typeof eventbus.off === 'function')\n {\n eventbus.off();\n entry.config.eventbus = void 0;\n }\n }\n\n // Await all Svelte components to destroy.\n await Promise.all(svelteDestroyPromises);\n\n // Reset SvelteData like this to maintain reference to GetSvelteData / `this.svelte`.\n this.#svelteData.length = 0;\n\n // Remove element from the DOM. Most SvelteComponents have already removed it.\n el.remove();\n\n // Silently restore any width / height state before minimized as applicable.\n this.position.state.restore({\n name: '#beforeMinimized',\n properties: ['width', 'height'],\n silent: true,\n remove: true\n });\n\n // Clean up data\n this.#applicationShellHolder[0] = null;\n /**\n * @ignore\n */\n this._element = null;\n this.#elementContent = null;\n this.#elementTarget = null;\n delete ui.windows[this.appId];\n /**\n * @ignore\n */\n this._minimized = false;\n /**\n * @ignore\n */\n this._scrollPositions = null;\n this._state = states.CLOSED;\n\n this.#onMount = false;\n\n // Update the minimized UI store options.\n this.#stores.uiOptionsUpdate((storeOptions) => deepMerge(storeOptions, { minimized: this._minimized }));\n }\n\n /**\n * Inject the Svelte components defined in `this.options.svelte`. The Svelte component can attach to the existing\n * pop-out of Application or provide no template and render into a document fragment which is then attached to the\n * DOM.\n *\n * @param {JQuery} html -\n *\n * @inheritDoc\n * @ignore\n */\n _injectHTML(html)\n {\n if (this.popOut && html.length === 0 && Array.isArray(this.options.svelte))\n {\n throw new Error(\n 'SvelteApplication - _injectHTML - A popout app with no template can only support one Svelte component.');\n }\n\n // Make sure the store is updated with the latest header buttons. Also allows filtering buttons before display.\n this.reactive.updateHeaderButtons();\n\n // Create a function to generate a callback for Svelte components to invoke to update the tracked elements for\n // application shells in the rare cases that the main element root changes. The update is only trigged on\n // successive changes of `elementRoot`. Returns a boolean to indicate the element roots are updated.\n const elementRootUpdate = () =>\n {\n let cntr = 0;\n\n return (elementRoot) =>\n {\n if (elementRoot !== null && elementRoot !== void 0 && cntr++ > 0)\n {\n this.#updateApplicationShell();\n return true;\n }\n\n return false;\n };\n };\n\n if (Array.isArray(this.options.svelte))\n {\n for (const svelteConfig of this.options.svelte)\n {\n const svelteData = loadSvelteConfig({\n app: this,\n template: html[0],\n config: svelteConfig,\n elementRootUpdate\n });\n\n if (isApplicationShell(svelteData.component))\n {\n if (this.svelte.applicationShell !== null)\n {\n throw new Error(\n `SvelteApplication - _injectHTML - An application shell is already mounted; offending config:\n ${JSON.stringify(svelteConfig)}`);\n }\n\n this.#applicationShellHolder[0] = svelteData.component;\n\n // If Vite / HMR / svelte_hmr is enabled then add a hook to receive callbacks when the ProxyComponent\n // refreshes. Update the element root accordingly and force an update to Position.\n // See this issue for info about `on_hmr`:\n // https://github.com/sveltejs/svelte-hmr/issues/57\n if (isHMRProxy(svelteData.component) && Array.isArray(svelteData.component?.$$?.on_hmr))\n {\n svelteData.component.$$.on_hmr.push(() => () => this.#updateApplicationShell());\n }\n }\n\n this.#svelteData.push(svelteData);\n }\n }\n else if (typeof this.options.svelte === 'object')\n {\n const svelteData = loadSvelteConfig({\n app: this,\n template: html[0],\n config: this.options.svelte,\n elementRootUpdate\n });\n\n if (isApplicationShell(svelteData.component))\n {\n // A sanity check as shouldn't hit this case as only one component is being mounted.\n if (this.svelte.applicationShell !== null)\n {\n throw new Error(\n `SvelteApplication - _injectHTML - An application shell is already mounted; offending config:\n ${JSON.stringify(this.options.svelte)}`);\n }\n\n this.#applicationShellHolder[0] = svelteData.component;\n\n // If Vite / HMR / svelte_hmr is enabled then add a hook to receive callbacks when the ProxyComponent\n // refreshes. Update the element root accordingly and force an update to Position.\n // See this issue for info about `on_hmr`:\n // https://github.com/sveltejs/svelte-hmr/issues/57\n if (isHMRProxy(svelteData.component) && Array.isArray(svelteData.component?.$$?.on_hmr))\n {\n svelteData.component.$$.on_hmr.push(() => () => this.#updateApplicationShell());\n }\n }\n\n this.#svelteData.push(svelteData);\n }\n\n // Detect if this is a synthesized DocumentFragment.\n const isDocumentFragment = html.length && html[0] instanceof DocumentFragment;\n\n // If any of the Svelte components mounted directly targets an HTMLElement then do not inject HTML.\n let injectHTML = true;\n for (const svelteData of this.#svelteData)\n {\n if (!svelteData.injectHTML) { injectHTML = false; break; }\n }\n if (injectHTML) { super._injectHTML(html); }\n\n if (this.svelte.applicationShell !== null)\n {\n this._element = $(this.svelte.applicationShell.elementRoot);\n\n // Detect if the application shell exports an `elementContent` accessor.\n this.#elementContent = hasGetter(this.svelte.applicationShell, 'elementContent') ?\n this.svelte.applicationShell.elementContent : null;\n\n // Detect if the application shell exports an `elementTarget` accessor.\n this.#elementTarget = hasGetter(this.svelte.applicationShell, 'elementTarget') ?\n this.svelte.applicationShell.elementTarget : null;\n }\n else if (isDocumentFragment) // Set the element of the app to the first child element in order of Svelte components mounted.\n {\n for (const svelteData of this.#svelteData)\n {\n if (svelteData.element instanceof HTMLElement)\n {\n this._element = $(svelteData.element);\n break;\n }\n }\n }\n\n // Potentially retrieve a specific target element if `selectorTarget` is defined otherwise make the target the\n // main element.\n if (this.#elementTarget === null)\n {\n const element = typeof this.options.selectorTarget === 'string' ?\n this._element.find(this.options.selectorTarget) : this._element;\n\n this.#elementTarget = element[0];\n }\n\n // TODO VERIFY THIS CHECK ESPECIALLY `this.#elementTarget.length === 0`.\n if (this.#elementTarget === null || this.#elementTarget === void 0 || this.#elementTarget.length === 0)\n {\n throw new Error(`SvelteApplication - _injectHTML: Target element '${this.options.selectorTarget}' not found.`);\n }\n\n // The initial zIndex may be set in application options or for popOut applications is stored by `_renderOuter`\n // in `this.#initialZIndex`.\n if (typeof this.options.positionable === 'boolean' && this.options.positionable)\n {\n this.#elementTarget.style.zIndex = typeof this.options.zIndex === 'number' ? this.options.zIndex :\n this.#initialZIndex ?? 95;\n }\n\n // Subscribe to local store handling.\n this.#stores.subscribe();\n }\n\n /**\n * Provides a mechanism to update the UI options store for maximized.\n *\n * Note: the sanity check is duplicated from {@link Application.maximize} the store is updated _before_\n * performing the rest of animations. This allows application shells to remove / show any resize handlers\n * correctly. Extra constraint data is stored in a saved position state in {@link SvelteApplication.minimize}\n * to animate the content area.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {boolean} [opts.animate=true] - When true perform default maximizing animation.\n *\n * @param {number} [opts.duration=0.1] - Controls content area animation duration in seconds.\n */\n async maximize({ animate = true, duration = 0.1 } = {})\n {\n if (!this.popOut || [false, null].includes(this._minimized)) { return; }\n\n this._minimized = null;\n\n const durationMS = duration * 1000; // For WAAPI.\n\n // Get content\n const element = this.elementTarget;\n const header = element.querySelector('.window-header');\n const content = element.querySelector('.window-content');\n\n // Get the complete position before minimized. Used to reset min width & height to initial values later.\n const positionBefore = this.position.state.get({ name: '#beforeMinimized' });\n\n // First animate / restore width / async.\n if (animate)\n {\n await this.position.state.restore({\n name: '#beforeMinimized',\n async: true,\n animateTo: true,\n properties: ['width'],\n duration: 0.1\n });\n }\n\n // Reset display none on all children of header.\n for (let cntr = header.children.length; --cntr >= 0;) { header.children[cntr].style.display = null; }\n\n content.style.display = null;\n\n let constraints;\n\n if (animate)\n {\n // Next animate / restore height synchronously and remove key. Retrieve constraints data for slide up animation\n // below.\n ({ constraints } = this.position.state.restore({\n name: '#beforeMinimized',\n animateTo: true,\n properties: ['height'],\n remove: true,\n duration\n }));\n }\n else\n {\n ({ constraints } = this.position.state.remove({ name: '#beforeMinimized' }));\n }\n\n // Slide down content with stored constraints.\n await content.animate([\n { maxHeight: 0, paddingTop: 0, paddingBottom: 0, offset: 0 },\n { ...constraints, offset: 1 },\n { maxHeight: '100%', offset: 1 },\n ], { duration: durationMS, fill: 'forwards' }).finished; // WAAPI in ms.\n\n // Restore previous min width & height from saved data, app options, or default Foundry values.\n this.position.set({\n minHeight: positionBefore.minHeight ?? this.options?.minHeight ?? MIN_WINDOW_HEIGHT,\n minWidth: positionBefore.minWidth ?? this.options?.minWidth ?? MIN_WINDOW_WIDTH,\n });\n\n // Remove inline styles that override any styles assigned to the app.\n element.style.minWidth = null;\n element.style.minHeight = null;\n\n element.classList.remove('minimized');\n\n this._minimized = false;\n\n // Using a 50ms timeout prevents any instantaneous display of scrollbars with the above maximize animation.\n setTimeout(() =>\n {\n content.style.overflow = null;\n\n // Reset all children of content removing overflow hidden.\n for (let cntr = content.children.length; --cntr >= 0;)\n {\n content.children[cntr].style.overflow = null;\n }\n }, 50);\n\n this.#stores.uiOptionsUpdate((options) => deepMerge(options, { minimized: false }));\n }\n\n /**\n * Provides a mechanism to update the UI options store for minimized.\n *\n * Note: the sanity check is duplicated from {@link Application.minimize} the store is updated _before_\n * performing the rest of animations. This allows application shells to remove / show any resize handlers\n * correctly. Extra constraint data is stored in a saved position state in {@link SvelteApplication.minimize}\n * to animate the content area.\n *\n * @param {object} [opts] - Optional parameters\n *\n * @param {boolean} [opts.animate=true] - When true perform default minimizing animation.\n *\n * @param {number} [opts.duration=0.1] - Controls content area animation duration in seconds.\n */\n async minimize({ animate = true, duration = 0.1 } = {})\n {\n if (!this.rendered || !this.popOut || [true, null].includes(this._minimized)) { return; }\n\n this.#stores.uiOptionsUpdate((options) => deepMerge(options, { minimized: true }));\n\n this._minimized = null;\n\n const durationMS = duration * 1000; // For WAAPI.\n\n const element = this.elementTarget;\n\n // Get content\n const header = element.querySelector('.window-header');\n const content = element.querySelector('.window-content');\n\n // Save current max / min height & width.\n const beforeMinWidth = this.position.minWidth;\n const beforeMinHeight = this.position.minHeight;\n\n // Set minimized min width & height for header bar.\n this.position.set({ minWidth: 100, minHeight: 30 });\n\n // Also set inline styles to override any styles scoped to the app.\n element.style.minWidth = '100px';\n element.style.minHeight = '30px';\n\n if (content)\n {\n content.style.overflow = 'hidden';\n\n // Set all children of content to overflow hidden as if there is going to be additional scrolling elements\n // they are likely one level deep.\n for (let cntr = content.children.length; --cntr >= 0;)\n {\n content.children[cntr].style.overflow = 'hidden';\n }\n }\n\n const { paddingBottom, paddingTop } = globalThis.getComputedStyle(content);\n\n // Extra data that is saved with the current position. Used during `maximize`.\n const constraints = {\n maxHeight: `${content.clientHeight}px`,\n paddingTop,\n paddingBottom\n };\n\n // Slide-up content\n if (animate)\n {\n const animation = content.animate([\n constraints,\n { maxHeight: 0, paddingTop: 0, paddingBottom: 0 }\n ], { duration: durationMS, fill: 'forwards' }); // WAAPI in ms.\n\n // Set display style to none when animation finishes.\n animation.finished.then(() => content.style.display = 'none');\n }\n else\n {\n setTimeout(() => content.style.display = 'none', durationMS);\n }\n\n // Save current position state and add the constraint data to use in `maximize`.\n const saved = this.position.state.save({ name: '#beforeMinimized', constraints });\n\n // Set the initial before min width & height.\n saved.minWidth = beforeMinWidth;\n saved.minHeight = beforeMinHeight;\n\n const headerOffsetHeight = header.offsetHeight;\n\n // minHeight needs to be adjusted to header height.\n this.position.minHeight = headerOffsetHeight;\n\n if (animate)\n {\n // First await animation of height upward.\n await this.position.animate.to({ height: headerOffsetHeight }, { duration }).finished;\n }\n\n // Set all header buttons besides close and the window title to display none.\n for (let cntr = header.children.length; --cntr >= 0;)\n {\n const className = header.children[cntr].className;\n\n if (className.includes('window-title') || className.includes('close') ||\n className.includes('keep-minimized'))\n {\n continue;\n }\n\n header.children[cntr].style.display = 'none';\n }\n\n if (animate)\n {\n // Await animation of width to the left / minimum width.\n await this.position.animate.to({ width: MIN_WINDOW_WIDTH }, { duration: 0.1 }).finished;\n }\n\n element.classList.add('minimized');\n\n this._minimized = true;\n }\n\n /**\n * Provides a callback after all Svelte components are initialized.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {HTMLElement} [opts.element] - HTMLElement container for main application element.\n *\n * @param {HTMLElement} [opts.elementContent] - HTMLElement container for content area of application shells.\n *\n * @param {HTMLElement} [opts.elementTarget] - HTMLElement container for main application target element.\n */\n onSvelteMount({ element, elementContent, elementTarget } = {}) {} // eslint-disable-line no-unused-vars\n\n /**\n * Provides a callback after the main application shell is remounted. This may occur during HMR / hot module\n * replacement or directly invoked from the `elementRootUpdate` callback passed to the application shell component\n * context.\n *\n * @param {object} [opts] - Optional parameters.\n *\n * @param {HTMLElement} [opts.element] - HTMLElement container for main application element.\n *\n * @param {HTMLElement} [opts.elementContent] - HTMLElement container for content area of application shells.\n *\n * @param {HTMLElement} [opts.elementTarget] - HTMLElement container for main application target element.\n */\n onSvelteRemount({ element, elementContent, elementTarget } = {}) {} // eslint-disable-line no-unused-vars\n\n /**\n * Override replacing HTML as Svelte components control the rendering process. Only potentially change the outer\n * application frame / title for pop-out applications.\n *\n * @inheritDoc\n * @ignore\n */\n _replaceHTML(element, html) // eslint-disable-line no-unused-vars\n {\n if (!element.length) { return; }\n\n this.reactive.updateHeaderButtons();\n }\n\n /**\n * Provides an override verifying that a new Application being rendered for the first time doesn't have a\n * corresponding DOM element already loaded. This is a check that only occurs when `this._state` is\n * `Application.RENDER_STATES.NONE`. It is useful in particular when SvelteApplication has a static ID\n * explicitly set in `this.options.id` and long intro / outro transitions are assigned. If a new application\n * sharing this static ID attempts to open / render for the first time while an existing DOM element sharing\n * this static ID exists then the initial render is cancelled below rather than crashing later in the render\n * cycle {@link Position.set}.\n *\n * @inheritDoc\n * @protected\n * @ignore\n */\n async _render(force = false, options = {})\n {\n if (this._state === Application.RENDER_STATES.NONE &&\n document.querySelector(`#${this.id}`) instanceof HTMLElement)\n {\n console.warn(`SvelteApplication - _render: A DOM element already exists for CSS ID '${this.id\n }'. Cancelling initial render for new application with appId '${this.appId}'.`);\n\n return;\n }\n\n await super._render(force, options);\n\n if (!this.#onMount)\n {\n this.onSvelteMount({ element: this._element[0], elementContent: this.#elementContent, elementTarget:\n this.#elementTarget });\n\n this.#onMount = true;\n }\n }\n\n /**\n * Render the inner application content. Only render a template if one is defined otherwise provide an empty\n * JQuery element per the core Foundry API.\n *\n * @param {Object} data The data used to render the inner template\n *\n * @returns {Promise.} A promise resolving to the constructed jQuery object\n *\n * @protected\n * @ignore\n */\n async _renderInner(data)\n {\n const html = typeof this.template === 'string' ? await renderTemplate(this.template, data) :\n document.createDocumentFragment();\n\n return $(html);\n }\n\n /**\n * Stores the initial z-index set in `_renderOuter` which is used in `_injectHTML` to set the target element\n * z-index after the Svelte component is mounted.\n *\n * @returns {Promise} Outer frame / unused.\n * @protected\n * @ignore\n */\n async _renderOuter()\n {\n const html = await super._renderOuter();\n this.#initialZIndex = html[0].style.zIndex;\n return html;\n }\n\n /**\n * All calculation and updates of position are implemented in {@link Position.set}. This allows position to be fully\n * reactive and in control of updating inline styles for the application.\n *\n * This method remains for backward compatibility with Foundry. If you have a custom override quite likely you need\n * to update to using the {@link Position.validators} functionality.\n *\n * @param {PositionDataExtended} [position] - Position data.\n *\n * @returns {Position} The updated position object for the application containing the new values\n */\n setPosition(position)\n {\n return this.position.set(position);\n }\n\n /**\n * This method is invoked by the `elementRootUpdate` callback that is added to the external context passed to\n * Svelte components. When invoked it updates the local element roots tracked by SvelteApplication.\n *\n * This method may also be invoked by HMR / hot module replacement via `svelte-hmr`.\n */\n #updateApplicationShell()\n {\n const applicationShell = this.svelte.applicationShell;\n\n if (applicationShell !== null)\n {\n this._element = $(applicationShell.elementRoot);\n\n // Detect if the application shell exports an `elementContent` accessor.\n this.#elementContent = hasGetter(applicationShell, 'elementContent') ?\n applicationShell.elementContent : null;\n\n // Detect if the application shell exports an `elementTarget` accessor.\n this.#elementTarget = hasGetter(applicationShell, 'elementTarget') ?\n applicationShell.elementTarget : null;\n\n if (this.#elementTarget === null)\n {\n const element = typeof this.options.selectorTarget === 'string' ?\n this._element.find(this.options.selectorTarget) : this._element;\n\n this.#elementTarget = element[0];\n }\n\n // The initial zIndex may be set in application options or for popOut applications is stored by `_renderOuter`\n // in `this.#initialZIndex`.\n if (typeof this.options.positionable === 'boolean' && this.options.positionable)\n {\n this.#elementTarget.style.zIndex = typeof this.options.zIndex === 'number' ? this.options.zIndex :\n this.#initialZIndex ?? 95;\n\n super.bringToTop();\n\n // Ensure that new root element has inline position styles set.\n this.position.set(this.position.get());\n }\n\n super._activateCoreListeners([this.#elementTarget]);\n\n this.onSvelteRemount({ element: this._element[0], elementContent: this.#elementContent, elementTarget:\n this.#elementTarget });\n }\n }\n}\n\n/**\n * @typedef {object} SvelteData\n *\n * @property {object} config -\n *\n * @property {import('svelte').SvelteComponent} component -\n *\n * @property {HTMLElement} element -\n *\n * @property {boolean} injectHTML -\n */\n\n/**\n * @typedef {object} SvelteStores\n *\n * @property {import('svelte/store').Writable.update} appOptionsUpdate - Update function for app options store.\n *\n * @property {Function} subscribe - Subscribes to local stores.\n *\n * @property {import('svelte/store').Writable.update} uiOptionsUpdate - Update function for UI options store.\n *\n * @property {Function} unsubscribe - Unsubscribes from local stores.\n */\n","\n\n\n\n{#if Array.isArray(children)}\n {#each children as child}\n \n {/each}\n{:else if warn}\n
Container warning: No children.
\n{/if}\n\n","import { cubicInOut, linear, cubicOut } from '../easing/index.mjs';\nimport { is_function, assign } from '../internal/index.mjs';\n\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n\r\nfunction __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\n\nfunction blur(node, { delay = 0, duration = 400, easing = cubicInOut, amount = 5, opacity = 0 } = {}) {\n const style = getComputedStyle(node);\n const target_opacity = +style.opacity;\n const f = style.filter === 'none' ? '' : style.filter;\n const od = target_opacity * (1 - opacity);\n return {\n delay,\n duration,\n easing,\n css: (_t, u) => `opacity: ${target_opacity - (od * u)}; filter: ${f} blur(${u * amount}px);`\n };\n}\nfunction fade(node, { delay = 0, duration = 400, easing = linear } = {}) {\n const o = +getComputedStyle(node).opacity;\n return {\n delay,\n duration,\n easing,\n css: t => `opacity: ${t * o}`\n };\n}\nfunction fly(node, { delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 } = {}) {\n const style = getComputedStyle(node);\n const target_opacity = +style.opacity;\n const transform = style.transform === 'none' ? '' : style.transform;\n const od = target_opacity * (1 - opacity);\n return {\n delay,\n duration,\n easing,\n css: (t, u) => `\n\t\t\ttransform: ${transform} translate(${(1 - t) * x}px, ${(1 - t) * y}px);\n\t\t\topacity: ${target_opacity - (od * u)}`\n };\n}\nfunction slide(node, { delay = 0, duration = 400, easing = cubicOut } = {}) {\n const style = getComputedStyle(node);\n const opacity = +style.opacity;\n const height = parseFloat(style.height);\n const padding_top = parseFloat(style.paddingTop);\n const padding_bottom = parseFloat(style.paddingBottom);\n const margin_top = parseFloat(style.marginTop);\n const margin_bottom = parseFloat(style.marginBottom);\n const border_top_width = parseFloat(style.borderTopWidth);\n const border_bottom_width = parseFloat(style.borderBottomWidth);\n return {\n delay,\n duration,\n easing,\n css: t => 'overflow: hidden;' +\n `opacity: ${Math.min(t * 20, 1) * opacity};` +\n `height: ${t * height}px;` +\n `padding-top: ${t * padding_top}px;` +\n `padding-bottom: ${t * padding_bottom}px;` +\n `margin-top: ${t * margin_top}px;` +\n `margin-bottom: ${t * margin_bottom}px;` +\n `border-top-width: ${t * border_top_width}px;` +\n `border-bottom-width: ${t * border_bottom_width}px;`\n };\n}\nfunction scale(node, { delay = 0, duration = 400, easing = cubicOut, start = 0, opacity = 0 } = {}) {\n const style = getComputedStyle(node);\n const target_opacity = +style.opacity;\n const transform = style.transform === 'none' ? '' : style.transform;\n const sd = 1 - start;\n const od = target_opacity * (1 - opacity);\n return {\n delay,\n duration,\n easing,\n css: (_t, u) => `\n\t\t\ttransform: ${transform} scale(${1 - (sd * u)});\n\t\t\topacity: ${target_opacity - (od * u)}\n\t\t`\n };\n}\nfunction draw(node, { delay = 0, speed, duration, easing = cubicInOut } = {}) {\n let len = node.getTotalLength();\n const style = getComputedStyle(node);\n if (style.strokeLinecap !== 'butt') {\n len += parseInt(style.strokeWidth);\n }\n if (duration === undefined) {\n if (speed === undefined) {\n duration = 800;\n }\n else {\n duration = len / speed;\n }\n }\n else if (typeof duration === 'function') {\n duration = duration(len);\n }\n return {\n delay,\n duration,\n easing,\n css: (t, u) => `stroke-dasharray: ${t * len} ${u * len}`\n };\n}\nfunction crossfade(_a) {\n var { fallback } = _a, defaults = __rest(_a, [\"fallback\"]);\n const to_receive = new Map();\n const to_send = new Map();\n function crossfade(from, node, params) {\n const { delay = 0, duration = d => Math.sqrt(d) * 30, easing = cubicOut } = assign(assign({}, defaults), params);\n const to = node.getBoundingClientRect();\n const dx = from.left - to.left;\n const dy = from.top - to.top;\n const dw = from.width / to.width;\n const dh = from.height / to.height;\n const d = Math.sqrt(dx * dx + dy * dy);\n const style = getComputedStyle(node);\n const transform = style.transform === 'none' ? '' : style.transform;\n const opacity = +style.opacity;\n return {\n delay,\n duration: is_function(duration) ? duration(d) : duration,\n easing,\n css: (t, u) => `\n\t\t\t\topacity: ${t * opacity};\n\t\t\t\ttransform-origin: top left;\n\t\t\t\ttransform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${t + (1 - t) * dh});\n\t\t\t`\n };\n }\n function transition(items, counterparts, intro) {\n return (node, params) => {\n items.set(params.key, {\n rect: node.getBoundingClientRect()\n });\n return () => {\n if (counterparts.has(params.key)) {\n const { rect } = counterparts.get(params.key);\n counterparts.delete(params.key);\n return crossfade(rect, node, params);\n }\n // if the node is disappearing altogether\n // (i.e. wasn't claimed by the other list)\n // then we need to supply an outro\n items.delete(params.key);\n return fallback && fallback(node, params, intro);\n };\n };\n }\n return [\n transition(to_send, to_receive, false),\n transition(to_receive, to_send, true)\n ];\n}\n\nexport { blur, crossfade, draw, fade, fly, scale, slide };\n","import { linear } from 'svelte/easing';\nimport { lerp } from '@typhonjs-fvtt/runtime/svelte/math';\nimport { fade, slide } from 'svelte/transition';\n\n/**\n * Provides a rotate transition. For options `easing` is applied to to the rotate transition. The default easing is\n * linear.\n *\n * Note: that when reversing the transition that time goes from `1 - 0`, so if specific options are applied for\n * rotating out transition then `end` and `initial` are swapped.\n *\n * @param {HTMLElement} node - The transition node.\n *\n * @param {object} options - Optional parameters.\n *\n * @param {number} [options.delay] - Delay in ms before start of transition.\n *\n * @param {number} [options.duration] - Total transition length in ms.\n *\n * @param {Function} [options.easing=linear] - The easing function to apply to the rotate transition.\n *\n * @param {number} [options.end=0] - End rotation in degrees.\n *\n * @param {number} [options.initial=0] - Initial rotation in degrees.\n *\n * @returns {{duration: number, css: (function(*=): string), delay: number, easing: (x: number) => number}}\n * Transition object.\n */\nfunction rotate(node, options)\n{\n const easingRotate = options.easing ?? linear;\n\n const initialDeg = options.initial ?? 0;\n const endDeg = options.end ?? 0;\n\n return {\n delay: options.delay ?? 0,\n duration: options.duration ?? 500,\n easing: linear,\n css: (t) =>\n {\n const rotateT = easingRotate(t);\n return `transform: rotate(${lerp(initialDeg, endDeg, rotateT)}deg)`;\n }\n };\n}\n\n/**\n * Combines rotate & fade transitions into a single transition. For options `easing` this is applied to both transitions,\n * however if provided `easingRotate` and / or `easingFade` will take precedence. The default easing is linear.\n *\n * Note: that when reversing the transition that time goes from `1 - 0`, so if specific options are applied for\n * rotating out transition then `end` and `initial` are swapped.\n *\n * @param {HTMLElement} node - The transition node.\n *\n * @param {object} options - Optional parameters.\n *\n * @param {number} [options.delay] - Delay in ms before start of transition.\n *\n * @param {number} [options.duration] - Total transition length in ms.\n *\n * @param {Function} [options.easing=linear] - The easing function to apply to both slide & fade transitions.\n *\n * @param {Function} [options.easingFade=linear] - The easing function to apply to the fade transition.\n *\n * @param {Function} [options.easingRotate=linear] - The easing function to apply to the rotate transition.\n *\n * @param {number} [options.end=0] - End rotation in degrees.\n *\n * @param {number} [options.initial=0] - Initial rotation in degrees.\n *\n * @returns {{duration: number, css: (function(*=): string), delay: number, easing: (x: number) => number}}\n * Transition object.\n */\nfunction rotateFade(node, options)\n{\n const easingFade = options.easingFade || options.easing || linear;\n const easingRotate = options.easingRotate || options.easing || linear;\n\n const fadeTransition = fade(node);\n\n const initialDeg = options.initial ?? 0;\n const endDeg = options.end ?? 0;\n\n return {\n delay: options.delay ?? 0,\n duration: options.duration ?? 500,\n easing: linear,\n css: (t) =>\n {\n const fadeT = easingFade(t);\n const rotateT = easingRotate(t);\n\n return `transform: rotate(${lerp(initialDeg, endDeg, rotateT)}deg); ${fadeTransition.css(fadeT, 1 - fadeT)}`;\n }\n };\n}\n\n/**\n * Combines slide & fade transitions into a single transition. For options `easing` this is applied to both transitions,\n * however if provided `easingSlide` and / or `easingFade` will take precedence. The default easing is linear.\n *\n * @param {HTMLElement} node - The transition node.\n *\n * @param {object} options - Optional parameters.\n *\n * @param {number} [options.delay] - Delay in ms before start of transition.\n *\n * @param {number} [options.duration] - Total transition length in ms.\n *\n * @param {Function} [options.easing=linear] - The easing function to apply to both slide & fade transitions.\n *\n * @param {Function} [options.easingFade=linear] - The easing function to apply to the fade transition.\n *\n * @param {Function} [options.easingSlide=linear] - The easing function to apply to the slide transition.\n *\n * @returns {{duration: number, css: (function(*=): string), delay: number, easing: (x: number) => number}}\n * Transition object.\n */\nfunction slideFade(node, options)\n{\n const fadeEasing = options.easingFade || options.easing || linear;\n const slideEasing = options.easingSlide || options.easing || linear;\n\n const fadeTransition = fade(node);\n const slideTransition = slide(node);\n\n return {\n delay: options.delay || 0,\n duration: options.duration || 500,\n easing: linear,\n css: (t) =>\n {\n const fadeT = fadeEasing(t);\n const slideT = slideEasing(t);\n return `${slideTransition.css(slideT, 1 - slideT)}; ${fadeTransition.css(fadeT, 1 - fadeT)}`;\n }\n };\n}\n\n/**\n * Converts a Svelte transition to an animation. Both transitions & animations use the same CSS / styles solution and\n * resulting data so wrap the transition function with the signature of an animation.\n *\n * @param {(node: Element, params?: object) => import('svelte/transition').TransitionConfig} fn - A Svelte transition\n * function.\n *\n * @returns {(node: Element, { from: DOMRect, to: DOMRect }, params?: object) =>\n * import('svelte/transition').TransitionConfig} Transition function converted to an animation.\n */\nfunction toAnimation(fn) {\n return (node, animations, params = {}) => fn(node, params);\n}\n\nconst s_DEFAULT_TRANSITION = () => void 0;\nconst s_DEFAULT_TRANSITION_OPTIONS = {};\n\nexport { rotate, rotateFade, s_DEFAULT_TRANSITION, s_DEFAULT_TRANSITION_OPTIONS, slideFade, toAnimation };\n//# sourceMappingURL=index.js.map\n","\n\n\n\n
\n \n
\n\n\n","import { isUpdatableStore, isWritableStore } from '@typhonjs-fvtt/runtime/svelte/store';\nimport { styleParsePixels, debounce, hasSetter } from '@typhonjs-fvtt/runtime/svelte/util';\nimport { cubicOut } from 'svelte/easing';\n\n/**\n * Provides an action to always blur the element when any pointer up event occurs on the element.\n *\n * @param {HTMLElement} node - The node to handle always blur on pointer up.\n */\nfunction alwaysBlur(node)\n{\n function blur()\n {\n setTimeout(() => { if (document.activeElement === node) { node.blur(); } }, 0);\n }\n\n node.addEventListener('pointerup', blur);\n\n return {\n destroy: () => node.removeEventListener('pointerup', blur)\n };\n}\n\n/**\n * Provides an action to monitor the given HTMLElement node with `ResizeObserver` posting width / height changes\n * to the target in various ways depending on the shape of the target. The target can be one of the following and the\n * precedence order is listed from top to bottom:\n *\n * - has a `resizeObserved` function as attribute; offset then content width / height are passed as parameters.\n * - has a `setContentBounds` function as attribute; content width / height are passed as parameters.\n * - has a `setDimension` function as attribute; offset width / height are passed as parameters.\n * - target is an object; offset and content width / height attributes are directly set on target.\n * - target is a function; the function is invoked with offset then content width / height parameters.\n * - has a writable store `resizeObserved` as an attribute; updated with offset & content width / height.\n * - has an object 'stores' that has a writable store `resizeObserved` as an attribute; updated with offset &\n * content width / height.\n *\n * Note: Svelte currently uses an archaic IFrame based workaround to monitor offset / client width & height changes.\n * A more up to date way to do this is with ResizeObserver. To track when Svelte receives ResizeObserver support\n * monitor this issue: {@link https://github.com/sveltejs/svelte/issues/4233}\n *\n * Can-I-Use: {@link https://caniuse.com/resizeobserver}\n *\n * @param {HTMLElement} node - The node associated with the action.\n *\n * @param {ResizeObserverTarget} target - An object or function to update with observed width & height changes.\n *\n * @returns {{update: Function, destroy: Function}} The action lifecycle methods.\n * @see {@link https://github.com/sveltejs/svelte/issues/4233}\n */\nfunction resizeObserver(node, target)\n{\n ResizeObserverManager.add(node, target);\n\n return {\n update: (newTarget) =>\n {\n ResizeObserverManager.remove(node, target);\n target = newTarget;\n ResizeObserverManager.add(node, target);\n },\n\n destroy: () =>\n {\n ResizeObserverManager.remove(node, target);\n }\n };\n}\n\n/**\n * Provides a function that when invoked with an element updates the cached styles for each subscriber of the element.\n *\n * The style attributes cached to calculate offset height / width include border & padding dimensions. You only need\n * to update the cache if you change border or padding attributes of the element.\n *\n * @param {HTMLElement} el - An HTML element.\n */\nresizeObserver.updateCache = function(el)\n{\n if (!(el instanceof HTMLElement)) { throw new TypeError(`resizeObserverUpdate error: 'el' is not an HTMLElement.`); }\n\n const subscribers = s_MAP.get(el);\n\n if (Array.isArray(subscribers))\n {\n const computed = globalThis.getComputedStyle(el);\n\n // Cache styles first from any inline styles then computed styles defaulting to 0 otherwise.\n // Used to create the offset width & height values from the context box ResizeObserver provides.\n const borderBottom = styleParsePixels(el.style.borderBottom) ?? styleParsePixels(computed.borderBottom) ?? 0;\n const borderLeft = styleParsePixels(el.style.borderLeft) ?? styleParsePixels(computed.borderLeft) ?? 0;\n const borderRight = styleParsePixels(el.style.borderRight) ?? styleParsePixels(computed.borderRight) ?? 0;\n const borderTop = styleParsePixels(el.style.borderTop) ?? styleParsePixels(computed.borderTop) ?? 0;\n const paddingBottom = styleParsePixels(el.style.paddingBottom) ?? styleParsePixels(computed.paddingBottom) ?? 0;\n const paddingLeft = styleParsePixels(el.style.paddingLeft) ?? styleParsePixels(computed.paddingLeft) ?? 0;\n const paddingRight = styleParsePixels(el.style.paddingRight) ?? styleParsePixels(computed.paddingRight) ?? 0;\n const paddingTop = styleParsePixels(el.style.paddingTop) ?? styleParsePixels(computed.paddingTop) ?? 0;\n\n const additionalWidth = borderLeft + borderRight + paddingLeft + paddingRight;\n const additionalHeight = borderTop + borderBottom + paddingTop + paddingBottom;\n\n for (const subscriber of subscribers)\n {\n subscriber.styles.additionalWidth = additionalWidth;\n subscriber.styles.additionalHeight = additionalHeight;\n s_UPDATE_SUBSCRIBER(subscriber, subscriber.contentWidth, subscriber.contentHeight);\n }\n }\n};\n\n// Below is the static ResizeObserverManager ------------------------------------------------------------------------\n\nconst s_MAP = new Map();\n\n/**\n * Provides a static / single instance of ResizeObserver that can notify listeners in different ways.\n *\n * The action, {@link resizeObserver}, utilizes ResizeObserverManager for automatic registration and removal\n * via Svelte.\n */\nclass ResizeObserverManager\n{\n /**\n * Add an HTMLElement and ResizeObserverTarget instance for monitoring. Create cached style attributes for the\n * given element include border & padding dimensions for offset width / height calculations.\n *\n * @param {HTMLElement} el - The element to observe.\n *\n * @param {ResizeObserverTarget} target - A target that contains one of several mechanisms for updating resize data.\n */\n static add(el, target)\n {\n const updateType = s_GET_UPDATE_TYPE(target);\n\n if (updateType === 0)\n {\n throw new Error(`'target' does not match supported ResizeObserverManager update mechanisms.`);\n }\n\n const computed = globalThis.getComputedStyle(el);\n\n // Cache styles first from any inline styles then computed styles defaulting to 0 otherwise.\n // Used to create the offset width & height values from the context box ResizeObserver provides.\n const borderBottom = styleParsePixels(el.style.borderBottom) ?? styleParsePixels(computed.borderBottom) ?? 0;\n const borderLeft = styleParsePixels(el.style.borderLeft) ?? styleParsePixels(computed.borderLeft) ?? 0;\n const borderRight = styleParsePixels(el.style.borderRight) ?? styleParsePixels(computed.borderRight) ?? 0;\n const borderTop = styleParsePixels(el.style.borderTop) ?? styleParsePixels(computed.borderTop) ?? 0;\n const paddingBottom = styleParsePixels(el.style.paddingBottom) ?? styleParsePixels(computed.paddingBottom) ?? 0;\n const paddingLeft = styleParsePixels(el.style.paddingLeft) ?? styleParsePixels(computed.paddingLeft) ?? 0;\n const paddingRight = styleParsePixels(el.style.paddingRight) ?? styleParsePixels(computed.paddingRight) ?? 0;\n const paddingTop = styleParsePixels(el.style.paddingTop) ?? styleParsePixels(computed.paddingTop) ?? 0;\n\n const data = {\n updateType,\n target,\n\n // Stores most recent contentRect.width and contentRect.height values from ResizeObserver.\n contentWidth: 0,\n contentHeight: 0,\n\n // Convenience data for total border & padding for offset width & height calculations.\n styles: {\n additionalWidth: borderLeft + borderRight + paddingLeft + paddingRight,\n additionalHeight: borderTop + borderBottom + paddingTop + paddingBottom\n }\n };\n\n if (s_MAP.has(el))\n {\n const subscribers = s_MAP.get(el);\n subscribers.push(data);\n }\n else\n {\n s_MAP.set(el, [data]);\n }\n\n s_RESIZE_OBSERVER.observe(el);\n }\n\n /**\n * Removes all targets from monitoring when just an element is provided otherwise removes a specific target\n * from the monitoring map. If no more targets remain then the element is removed from monitoring.\n *\n * @param {HTMLElement} el - Element to remove from monitoring.\n *\n * @param {ResizeObserverTarget} [target] - A specific target to remove from monitoring.\n */\n static remove(el, target = void 0)\n {\n const subscribers = s_MAP.get(el);\n if (Array.isArray(subscribers))\n {\n const index = subscribers.findIndex((entry) => entry.target === target);\n if (index >= 0)\n {\n // Update target subscriber with undefined values.\n s_UPDATE_SUBSCRIBER(subscribers[index], void 0, void 0);\n\n subscribers.splice(index, 1);\n }\n\n // Remove element monitoring if last target removed.\n if (subscribers.length === 0)\n {\n s_MAP.delete(el);\n s_RESIZE_OBSERVER.unobserve(el);\n }\n }\n }\n}\n\n/**\n * Defines the various shape / update type of the given target.\n *\n * @type {Record}\n */\nconst s_UPDATE_TYPES = {\n none: 0,\n attribute: 1,\n function: 2,\n resizeObserved: 3,\n setContentBounds: 4,\n setDimension: 5,\n storeObject: 6,\n storesObject: 7\n};\n\nconst s_RESIZE_OBSERVER = new ResizeObserver((entries) =>\n{\n for (const entry of entries)\n {\n const subscribers = s_MAP.get(entry?.target);\n\n if (Array.isArray(subscribers))\n {\n const contentWidth = entry.contentRect.width;\n const contentHeight = entry.contentRect.height;\n\n for (const subscriber of subscribers)\n {\n s_UPDATE_SUBSCRIBER(subscriber, contentWidth, contentHeight);\n }\n }\n }\n});\n\n/**\n * Determines the shape of the target instance regarding valid update mechanisms to set width & height changes.\n *\n * @param {*} target - The target instance.\n *\n * @returns {number} Update type value.\n */\nfunction s_GET_UPDATE_TYPE(target)\n{\n if (target?.resizeObserved instanceof Function) { return s_UPDATE_TYPES.resizeObserved; }\n if (target?.setDimension instanceof Function) { return s_UPDATE_TYPES.setDimension; }\n if (target?.setContentBounds instanceof Function) { return s_UPDATE_TYPES.setContentBounds; }\n\n const targetType = typeof target;\n\n // Does the target have resizeObserved writable store?\n if ((targetType === 'object' || targetType === 'function'))\n {\n if (isUpdatableStore(target.resizeObserved))\n {\n return s_UPDATE_TYPES.storeObject;\n }\n\n // Now check for a child stores object which is a common TRL pattern for exposing stores.\n const stores = target?.stores;\n if (typeof stores === 'object' || typeof stores === 'function')\n {\n if (isUpdatableStore(stores.resizeObserved))\n {\n return s_UPDATE_TYPES.storesObject;\n }\n }\n }\n\n if (targetType === 'object') { return s_UPDATE_TYPES.attribute; }\n\n if (targetType === 'function') { return s_UPDATE_TYPES.function; }\n\n return s_UPDATE_TYPES.none;\n}\n\n/**\n * Updates a subscriber target with given content width & height values. Offset width & height is calculated from\n * the content values + cached styles.\n *\n * @param {object} subscriber - Internal data about subscriber.\n *\n * @param {number|undefined} contentWidth - ResizeObserver contentRect.width value or undefined.\n *\n * @param {number|undefined} contentHeight - ResizeObserver contentRect.height value or undefined.\n */\nfunction s_UPDATE_SUBSCRIBER(subscriber, contentWidth, contentHeight)\n{\n const styles = subscriber.styles;\n\n subscriber.contentWidth = contentWidth;\n subscriber.contentHeight = contentHeight;\n\n const offsetWidth = Number.isFinite(contentWidth) ? contentWidth + styles.additionalWidth : void 0;\n const offsetHeight = Number.isFinite(contentHeight) ? contentHeight + styles.additionalHeight : void 0;\n\n const target = subscriber.target;\n\n switch (subscriber.updateType)\n {\n case s_UPDATE_TYPES.attribute:\n target.contentWidth = contentWidth;\n target.contentHeight = contentHeight;\n target.offsetWidth = offsetWidth;\n target.offsetHeight = offsetHeight;\n break;\n\n case s_UPDATE_TYPES.function:\n target?.(offsetWidth, offsetHeight, contentWidth, contentHeight);\n break;\n\n case s_UPDATE_TYPES.resizeObserved:\n target.resizeObserved?.(offsetWidth, offsetHeight, contentWidth, contentHeight);\n break;\n\n case s_UPDATE_TYPES.setContentBounds:\n target.setContentBounds?.(contentWidth, contentHeight);\n break;\n\n case s_UPDATE_TYPES.setDimension:\n target.setDimension?.(offsetWidth, offsetHeight);\n break;\n\n case s_UPDATE_TYPES.storeObject:\n target.resizeObserved.update((object) =>\n {\n object.contentHeight = contentHeight;\n object.contentWidth = contentWidth;\n object.offsetHeight = offsetHeight;\n object.offsetWidth = offsetWidth;\n\n return object;\n });\n break;\n\n case s_UPDATE_TYPES.storesObject:\n target.stores.resizeObserved.update((object) =>\n {\n object.contentHeight = contentHeight;\n object.contentWidth = contentWidth;\n object.offsetHeight = offsetHeight;\n object.offsetWidth = offsetWidth;\n\n return object;\n });\n break;\n }\n}\n\n/**\n * @typedef {object | Function} ResizeObserverTarget\n *\n * @property {number} [contentHeight] -\n *\n * @property {number} [contentWidth] -\n *\n * @property {number} [offsetHeight] -\n *\n * @property {number} [offsetWidth] -\n *\n * @property {Writable