diff --git a/api/api.php b/api/api.php
new file mode 100644
index 0000000..fd9b4d2
--- /dev/null
+++ b/api/api.php
@@ -0,0 +1,102 @@
+getConf();
+
+ $db = new PDO("sqlite:" . $config["DB_PATH"]);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ return $db;
+ }
+
+ public function checkAuth() {
+ if ($this->checkLogin()) {
+ return true;
+ }elseif (isset($_SERVER["HTTP_X_API_KEY"])) {
+ $key = $_SERVER["HTTP_X_API_KEY"];
+
+ $db = $this->getDB();
+
+ $sql = "SELECT * FROM api_keys WHERE key = :key";
+
+ $stmt = $db->prepare($sql);
+
+ $stmt->execute([":key" => $key]);
+
+ $result = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($result) {
+ $user_id = $result["user_id"];
+
+ $sql = "SELECT username FROM users WHERE id = :id";
+ $stmt = $db->prepare($sql);
+
+ $stmt->execute([":id" => $user_id]);
+ $result = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ $username = $result["username"];
+
+ $this->api_keys[$key] = $username;
+
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+ }
+
+ public function getUser() {
+ if ($this->checkLogin()) {
+ return $_COOKIE["username"];
+ }elseif (isset($_SERVER["HTTP_X_API_KEY"])) {
+ $key = $_SERVER["HTTP_X_API_KEY"];
+ if (isset($this->api_keys[$key])) {
+ return $this->api_keys[$key];
+ }
+ }
+ }
+
+ public function checkLogin() {
+ if (!isset($_COOKIE["session_id"]) || !isset($_COOKIE["device_id"]) || !isset($_COOKIE["username"])) {
+ return false;
+ }
+
+ $config = $this->getConf();
+
+ $json = json_decode(file_get_contents($config["PATH"] . "/tmp/user_sessions/" . $_COOKIE["username"] . ".json"), true);
+
+ if (!isset($json[$_COOKIE["device_id"]])) {
+ return false;
+ }
+
+ $device = $json[$_COOKIE["device_id"]];
+
+ if ($device["session_id"] !== $_COOKIE["session_id"]) {
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/api/login/getcookies.php b/api/login/getcookies.php
index c47647d..cd5124e 100644
--- a/api/login/getcookies.php
+++ b/api/login/getcookies.php
@@ -27,9 +27,9 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$session["session_id"] = $mcServ->generateSessionID();
$device_id = rand(1, 999);
- $json[$device_id] = json_encode($session);
+ $json[$device_id] = $session;
- file_put_contents($config["PATH"] . "/tmp/user_sessions/" . $admin_user . ".json", json_encode($json));
+ file_put_contents($config["PATH"] . "/tmp/user_sessions/" . $user . ".json", json_encode($json));
setcookie("session_id", $session["session_id"], time() + 3600, "/");
setcookie("device_id", $device_id, time() + 3600, "/");
diff --git a/api/setup/setup.php b/api/setup/setup.php
index e442508..cbe774e 100755
--- a/api/setup/setup.php
+++ b/api/setup/setup.php
@@ -66,7 +66,7 @@ $device_id = rand(1, 999);
$json[$device_id] = json_encode($session);
$json["array"] = true;
-mkdir($config["PATH"] . "/tmp/user_sessions", 0700, true);
+mkdir($config["PATH"] . "/tmp/user_sessions", 0755, true);
file_put_contents($config["PATH"] . "/tmp/user_sessions/" . $admin_user . ".json", json_encode($json));
diff --git a/api/users/info.php b/api/users/info.php
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/api/users/info.php
@@ -0,0 +1 @@
+checkAuth()) {
+ die('{"status":500, "error:"Unauthorized"}');
+}
+
+$db = $api->getDB();
+
+$sql = "SELECT * FROM users";
+$stmt = $db->query($sql);
+
+$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+$users= [];
+
+foreach($result as $user_res) {
+ $user["name"] = $user_res["username"];
+ $user["mail"] = $user_res["mail"];
+
+ $users[] = $user;
+}
+
+$json["status"] = 200;
+$json["users"] = $users;
+
+echo json_encode($json);
+?>
\ No newline at end of file
diff --git a/front/panel/index.php b/front/panel/index.php
index 97e1c74..3463f06 100644
--- a/front/panel/index.php
+++ b/front/panel/index.php
@@ -4,7 +4,7 @@ require "../../main.php";
$mcServ = new mcServ();
if ($mcServ->checkLogin()) {
- header("Location: /admin/home.php");
+ header("Location: /panel/home.php");
exit;
}else{
header("Location: /login.php");
diff --git a/front/panel/test/404.html b/front/panel/test/404.html
new file mode 100755
index 0000000..79d20bf
--- /dev/null
+++ b/front/panel/test/404.html
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+ 404 Error Page | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+

+
+
+
+
+
+
+
+ ERROR
+
+
+

+

+
+
+ We can’t seem to find the page you are looking for!
+
+
+
+ Back to Home Page
+
+
+
+
+ © - TailAdmin
+
+
+
+
+
+
diff --git a/front/panel/test/alerts.html b/front/panel/test/alerts.html
new file mode 100755
index 0000000..ba682da
--- /dev/null
+++ b/front/panel/test/alerts.html
@@ -0,0 +1,1586 @@
+
+
+
+
+
+
+ Alerts | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Success Alert
+
+
+
+
+
+
+
+
+
+
+ Success Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+ Success Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+
+
+
+
+
+
+
+
+ Warning Alert
+
+
+
+
+
+
+
+
+
+
+ Warning Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+ Warning Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+
+
+
+
+
+
+
+
+ Error Alert
+
+
+
+
+
+
+
+
+
+
+ Error Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+ Error Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+
+
+
+
+
+
+
+
+ Info Alert
+
+
+
+
+
+
+
+
+
+
+ Success Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+ Success Message
+
+
+
+ You can insert a description for the message here.The text relates to
+ the action that has been performed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/avatars.html b/front/panel/test/avatars.html
new file mode 100755
index 0000000..2e6e3eb
--- /dev/null
+++ b/front/panel/test/avatars.html
@@ -0,0 +1,1534 @@
+
+
+
+
+
+
+ Avatars | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default Avatar
+
+
+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+ Avatar with online indicator
+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+ Avatar with Offline indicator
+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+ Avatar with busy indicator
+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/badge.html b/front/panel/test/badge.html
new file mode 100755
index 0000000..0d97c36
--- /dev/null
+++ b/front/panel/test/badge.html
@@ -0,0 +1,2053 @@
+
+
+
+
+
+
+ Badge | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ With Light Background
+
+
+
+
+
+
+ Primary
+
+
+
+
+ Success
+
+
+
+
+ Error
+
+
+
+
+ Warning
+
+
+
+
+ Info
+
+
+
+
+ Light
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+ With Solid Background
+
+
+
+
+
+
+ Primary
+
+
+
+
+ Success
+
+
+
+
+ Error
+
+
+
+
+ Warning
+
+
+
+
+ Info
+
+
+
+
+ Light
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+ Light Background with Left Icon
+
+
+
+
+
+
+
+
+ Primary
+
+
+
+
+
+ Success
+
+
+
+
+
+
+ Error
+
+
+
+
+
+
+ Warning
+
+
+
+
+
+
+ Info
+
+
+
+
+
+
+ Light
+
+
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+ Solid Background with Left Icon
+
+
+
+
+
+
+
+
+ Primary
+
+
+
+
+
+
+ Success
+
+
+
+
+
+
+ Error
+
+
+
+
+
+
+ Warning
+
+
+
+
+
+
+ Info
+
+
+
+
+
+
+ Light
+
+
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+ Light Background with Right Icon
+
+
+
+
+
+
+ Primary
+
+
+
+
+
+
+ Success
+
+
+
+
+
+
+ Error
+
+
+
+
+
+
+ Warning
+
+
+
+
+
+
+ Info
+
+
+
+
+
+
+ Light
+
+
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+
+
+ Solid Background with Right Icon
+
+
+
+
+
+
+ Primary
+
+
+
+
+
+
+ Success
+
+
+
+
+
+
+ Error
+
+
+
+
+
+
+ Warning
+
+
+
+
+
+
+ Info
+
+
+
+
+
+
+ Light
+
+
+
+
+
+
+ Dark
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/bar-chart.html b/front/panel/test/bar-chart.html
new file mode 100755
index 0000000..80a6558
--- /dev/null
+++ b/front/panel/test/bar-chart.html
@@ -0,0 +1,1231 @@
+
+
+
+
+
+
+ Bar Chart | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bar Chart 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/basic-tables.html b/front/panel/test/basic-tables.html
new file mode 100755
index 0000000..fe916b3
--- /dev/null
+++ b/front/panel/test/basic-tables.html
@@ -0,0 +1,1611 @@
+
+
+
+
+
+
+
+ Basic Tables | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Basic Table 1
+
+
+
+
+
+
+
+
+
+
+ |
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+ 
+
+
+
+
+ Lindsey Curtis
+
+
+ Web Designer
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ 
+
+
+
+
+ Kaiya George
+
+
+ Project Manager
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ 
+
+
+ 
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ 
+
+
+
+
+ Zain Geidt
+
+
+ Content Writer
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ 
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ 
+
+
+
+
+ Abram Schleifer
+
+
+ Digital Marketer
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ 
+
+
+
+
+ Carla George
+
+
+ Front-end Developer
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/blank.html b/front/panel/test/blank.html
new file mode 100755
index 0000000..a300113
--- /dev/null
+++ b/front/panel/test/blank.html
@@ -0,0 +1,1230 @@
+
+
+
+
+
+
+
+ Blank Page | TailAdmin - Tailwind CSS Admin Dashboard Template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Card Title Here
+
+
+
+ Start putting content on grids or panels, you can also use
+ different combinations of grids.
Please check out the
+ dashboard and other pages
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/front/panel/test/bundle.js b/front/panel/test/bundle.js
new file mode 100755
index 0000000..b5af8eb
--- /dev/null
+++ b/front/panel/test/bundle.js
@@ -0,0 +1,504 @@
+/*
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
+ * This devtool is neither made for production nor for readable output files.
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
+ * or disable the default devtool with "devtool: false".
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
+ */
+/******/ (() => { // webpackBootstrap
+/******/ var __webpack_modules__ = ({
+
+/***/ "./node_modules/@alpinejs/persist/dist/module.esm.js":
+/*!***********************************************************!*\
+ !*** ./node_modules/@alpinejs/persist/dist/module.esm.js ***!
+ \***********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ module_default),\n/* harmony export */ persist: () => (/* binding */ src_default)\n/* harmony export */ });\n// packages/persist/src/index.js\nfunction src_default(Alpine) {\n let persist = () => {\n let alias;\n let storage;\n try {\n storage = localStorage;\n } catch (e) {\n console.error(e);\n console.warn(\"Alpine: $persist is using temporary storage since localStorage is unavailable.\");\n let dummy = /* @__PURE__ */ new Map();\n storage = {\n getItem: dummy.get.bind(dummy),\n setItem: dummy.set.bind(dummy)\n };\n }\n return Alpine.interceptor((initialValue, getter, setter, path, key) => {\n let lookup = alias || `_x_${path}`;\n let initial = storageHas(lookup, storage) ? storageGet(lookup, storage) : initialValue;\n setter(initial);\n Alpine.effect(() => {\n let value = getter();\n storageSet(lookup, value, storage);\n setter(value);\n });\n return initial;\n }, (func) => {\n func.as = (key) => {\n alias = key;\n return func;\n }, func.using = (target) => {\n storage = target;\n return func;\n };\n });\n };\n Object.defineProperty(Alpine, \"$persist\", { get: () => persist() });\n Alpine.magic(\"persist\", persist);\n Alpine.persist = (key, { get, set }, storage = localStorage) => {\n let initial = storageHas(key, storage) ? storageGet(key, storage) : get();\n set(initial);\n Alpine.effect(() => {\n let value = get();\n storageSet(key, value, storage);\n set(value);\n });\n };\n}\nfunction storageHas(key, storage) {\n return storage.getItem(key) !== null;\n}\nfunction storageGet(key, storage) {\n let value = storage.getItem(key, storage);\n if (value === void 0)\n return;\n return JSON.parse(value);\n}\nfunction storageSet(key, value, storage) {\n storage.setItem(key, JSON.stringify(value));\n}\n\n// packages/persist/builds/module.js\nvar module_default = src_default;\n\n\n\n//# sourceURL=webpack://tailadmin-free/./node_modules/@alpinejs/persist/dist/module.esm.js?");
+
+/***/ }),
+
+/***/ "./node_modules/alpinejs/dist/module.esm.js":
+/*!**************************************************!*\
+ !*** ./node_modules/alpinejs/dist/module.esm.js ***!
+ \**************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Alpine: () => (/* binding */ src_default),\n/* harmony export */ \"default\": () => (/* binding */ module_default)\n/* harmony export */ });\n// packages/alpinejs/src/scheduler.js\nvar flushPending = false;\nvar flushing = false;\nvar queue = [];\nvar lastFlushedIndex = -1;\nfunction scheduler(callback) {\n queueJob(callback);\n}\nfunction queueJob(job) {\n if (!queue.includes(job))\n queue.push(job);\n queueFlush();\n}\nfunction dequeueJob(job) {\n let index = queue.indexOf(job);\n if (index !== -1 && index > lastFlushedIndex)\n queue.splice(index, 1);\n}\nfunction queueFlush() {\n if (!flushing && !flushPending) {\n flushPending = true;\n queueMicrotask(flushJobs);\n }\n}\nfunction flushJobs() {\n flushPending = false;\n flushing = true;\n for (let i = 0; i < queue.length; i++) {\n queue[i]();\n lastFlushedIndex = i;\n }\n queue.length = 0;\n lastFlushedIndex = -1;\n flushing = false;\n}\n\n// packages/alpinejs/src/reactivity.js\nvar reactive;\nvar effect;\nvar release;\nvar raw;\nvar shouldSchedule = true;\nfunction disableEffectScheduling(callback) {\n shouldSchedule = false;\n callback();\n shouldSchedule = true;\n}\nfunction setReactivityEngine(engine) {\n reactive = engine.reactive;\n release = engine.release;\n effect = (callback) => engine.effect(callback, { scheduler: (task) => {\n if (shouldSchedule) {\n scheduler(task);\n } else {\n task();\n }\n } });\n raw = engine.raw;\n}\nfunction overrideEffect(override) {\n effect = override;\n}\nfunction elementBoundEffect(el) {\n let cleanup2 = () => {\n };\n let wrappedEffect = (callback) => {\n let effectReference = effect(callback);\n if (!el._x_effects) {\n el._x_effects = /* @__PURE__ */ new Set();\n el._x_runEffects = () => {\n el._x_effects.forEach((i) => i());\n };\n }\n el._x_effects.add(effectReference);\n cleanup2 = () => {\n if (effectReference === void 0)\n return;\n el._x_effects.delete(effectReference);\n release(effectReference);\n };\n return effectReference;\n };\n return [wrappedEffect, () => {\n cleanup2();\n }];\n}\nfunction watch(getter, callback) {\n let firstTime = true;\n let oldValue;\n let effectReference = effect(() => {\n let value = getter();\n JSON.stringify(value);\n if (!firstTime) {\n queueMicrotask(() => {\n callback(value, oldValue);\n oldValue = value;\n });\n } else {\n oldValue = value;\n }\n firstTime = false;\n });\n return () => release(effectReference);\n}\n\n// packages/alpinejs/src/mutation.js\nvar onAttributeAddeds = [];\nvar onElRemoveds = [];\nvar onElAddeds = [];\nfunction onElAdded(callback) {\n onElAddeds.push(callback);\n}\nfunction onElRemoved(el, callback) {\n if (typeof callback === \"function\") {\n if (!el._x_cleanups)\n el._x_cleanups = [];\n el._x_cleanups.push(callback);\n } else {\n callback = el;\n onElRemoveds.push(callback);\n }\n}\nfunction onAttributesAdded(callback) {\n onAttributeAddeds.push(callback);\n}\nfunction onAttributeRemoved(el, name, callback) {\n if (!el._x_attributeCleanups)\n el._x_attributeCleanups = {};\n if (!el._x_attributeCleanups[name])\n el._x_attributeCleanups[name] = [];\n el._x_attributeCleanups[name].push(callback);\n}\nfunction cleanupAttributes(el, names) {\n if (!el._x_attributeCleanups)\n return;\n Object.entries(el._x_attributeCleanups).forEach(([name, value]) => {\n if (names === void 0 || names.includes(name)) {\n value.forEach((i) => i());\n delete el._x_attributeCleanups[name];\n }\n });\n}\nfunction cleanupElement(el) {\n el._x_effects?.forEach(dequeueJob);\n while (el._x_cleanups?.length)\n el._x_cleanups.pop()();\n}\nvar observer = new MutationObserver(onMutate);\nvar currentlyObserving = false;\nfunction startObservingMutations() {\n observer.observe(document, { subtree: true, childList: true, attributes: true, attributeOldValue: true });\n currentlyObserving = true;\n}\nfunction stopObservingMutations() {\n flushObserver();\n observer.disconnect();\n currentlyObserving = false;\n}\nvar queuedMutations = [];\nfunction flushObserver() {\n let records = observer.takeRecords();\n queuedMutations.push(() => records.length > 0 && onMutate(records));\n let queueLengthWhenTriggered = queuedMutations.length;\n queueMicrotask(() => {\n if (queuedMutations.length === queueLengthWhenTriggered) {\n while (queuedMutations.length > 0)\n queuedMutations.shift()();\n }\n });\n}\nfunction mutateDom(callback) {\n if (!currentlyObserving)\n return callback();\n stopObservingMutations();\n let result = callback();\n startObservingMutations();\n return result;\n}\nvar isCollecting = false;\nvar deferredMutations = [];\nfunction deferMutations() {\n isCollecting = true;\n}\nfunction flushAndStopDeferringMutations() {\n isCollecting = false;\n onMutate(deferredMutations);\n deferredMutations = [];\n}\nfunction onMutate(mutations) {\n if (isCollecting) {\n deferredMutations = deferredMutations.concat(mutations);\n return;\n }\n let addedNodes = [];\n let removedNodes = /* @__PURE__ */ new Set();\n let addedAttributes = /* @__PURE__ */ new Map();\n let removedAttributes = /* @__PURE__ */ new Map();\n for (let i = 0; i < mutations.length; i++) {\n if (mutations[i].target._x_ignoreMutationObserver)\n continue;\n if (mutations[i].type === \"childList\") {\n mutations[i].removedNodes.forEach((node) => {\n if (node.nodeType !== 1)\n return;\n if (!node._x_marker)\n return;\n removedNodes.add(node);\n });\n mutations[i].addedNodes.forEach((node) => {\n if (node.nodeType !== 1)\n return;\n if (removedNodes.has(node)) {\n removedNodes.delete(node);\n return;\n }\n if (node._x_marker)\n return;\n addedNodes.push(node);\n });\n }\n if (mutations[i].type === \"attributes\") {\n let el = mutations[i].target;\n let name = mutations[i].attributeName;\n let oldValue = mutations[i].oldValue;\n let add2 = () => {\n if (!addedAttributes.has(el))\n addedAttributes.set(el, []);\n addedAttributes.get(el).push({ name, value: el.getAttribute(name) });\n };\n let remove = () => {\n if (!removedAttributes.has(el))\n removedAttributes.set(el, []);\n removedAttributes.get(el).push(name);\n };\n if (el.hasAttribute(name) && oldValue === null) {\n add2();\n } else if (el.hasAttribute(name)) {\n remove();\n add2();\n } else {\n remove();\n }\n }\n }\n removedAttributes.forEach((attrs, el) => {\n cleanupAttributes(el, attrs);\n });\n addedAttributes.forEach((attrs, el) => {\n onAttributeAddeds.forEach((i) => i(el, attrs));\n });\n for (let node of removedNodes) {\n if (addedNodes.some((i) => i.contains(node)))\n continue;\n onElRemoveds.forEach((i) => i(node));\n }\n for (let node of addedNodes) {\n if (!node.isConnected)\n continue;\n onElAddeds.forEach((i) => i(node));\n }\n addedNodes = null;\n removedNodes = null;\n addedAttributes = null;\n removedAttributes = null;\n}\n\n// packages/alpinejs/src/scope.js\nfunction scope(node) {\n return mergeProxies(closestDataStack(node));\n}\nfunction addScopeToNode(node, data2, referenceNode) {\n node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];\n return () => {\n node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);\n };\n}\nfunction closestDataStack(node) {\n if (node._x_dataStack)\n return node._x_dataStack;\n if (typeof ShadowRoot === \"function\" && node instanceof ShadowRoot) {\n return closestDataStack(node.host);\n }\n if (!node.parentNode) {\n return [];\n }\n return closestDataStack(node.parentNode);\n}\nfunction mergeProxies(objects) {\n return new Proxy({ objects }, mergeProxyTrap);\n}\nvar mergeProxyTrap = {\n ownKeys({ objects }) {\n return Array.from(\n new Set(objects.flatMap((i) => Object.keys(i)))\n );\n },\n has({ objects }, name) {\n if (name == Symbol.unscopables)\n return false;\n return objects.some(\n (obj) => Object.prototype.hasOwnProperty.call(obj, name) || Reflect.has(obj, name)\n );\n },\n get({ objects }, name, thisProxy) {\n if (name == \"toJSON\")\n return collapseProxies;\n return Reflect.get(\n objects.find(\n (obj) => Reflect.has(obj, name)\n ) || {},\n name,\n thisProxy\n );\n },\n set({ objects }, name, value, thisProxy) {\n const target = objects.find(\n (obj) => Object.prototype.hasOwnProperty.call(obj, name)\n ) || objects[objects.length - 1];\n const descriptor = Object.getOwnPropertyDescriptor(target, name);\n if (descriptor?.set && descriptor?.get)\n return descriptor.set.call(thisProxy, value) || true;\n return Reflect.set(target, name, value);\n }\n};\nfunction collapseProxies() {\n let keys = Reflect.ownKeys(this);\n return keys.reduce((acc, key) => {\n acc[key] = Reflect.get(this, key);\n return acc;\n }, {});\n}\n\n// packages/alpinejs/src/interceptor.js\nfunction initInterceptors(data2) {\n let isObject2 = (val) => typeof val === \"object\" && !Array.isArray(val) && val !== null;\n let recurse = (obj, basePath = \"\") => {\n Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, { value, enumerable }]) => {\n if (enumerable === false || value === void 0)\n return;\n if (typeof value === \"object\" && value !== null && value.__v_skip)\n return;\n let path = basePath === \"\" ? key : `${basePath}.${key}`;\n if (typeof value === \"object\" && value !== null && value._x_interceptor) {\n obj[key] = value.initialize(data2, path, key);\n } else {\n if (isObject2(value) && value !== obj && !(value instanceof Element)) {\n recurse(value, path);\n }\n }\n });\n };\n return recurse(data2);\n}\nfunction interceptor(callback, mutateObj = () => {\n}) {\n let obj = {\n initialValue: void 0,\n _x_interceptor: true,\n initialize(data2, path, key) {\n return callback(this.initialValue, () => get(data2, path), (value) => set(data2, path, value), path, key);\n }\n };\n mutateObj(obj);\n return (initialValue) => {\n if (typeof initialValue === \"object\" && initialValue !== null && initialValue._x_interceptor) {\n let initialize = obj.initialize.bind(obj);\n obj.initialize = (data2, path, key) => {\n let innerValue = initialValue.initialize(data2, path, key);\n obj.initialValue = innerValue;\n return initialize(data2, path, key);\n };\n } else {\n obj.initialValue = initialValue;\n }\n return obj;\n };\n}\nfunction get(obj, path) {\n return path.split(\".\").reduce((carry, segment) => carry[segment], obj);\n}\nfunction set(obj, path, value) {\n if (typeof path === \"string\")\n path = path.split(\".\");\n if (path.length === 1)\n obj[path[0]] = value;\n else if (path.length === 0)\n throw error;\n else {\n if (obj[path[0]])\n return set(obj[path[0]], path.slice(1), value);\n else {\n obj[path[0]] = {};\n return set(obj[path[0]], path.slice(1), value);\n }\n }\n}\n\n// packages/alpinejs/src/magics.js\nvar magics = {};\nfunction magic(name, callback) {\n magics[name] = callback;\n}\nfunction injectMagics(obj, el) {\n let memoizedUtilities = getUtilities(el);\n Object.entries(magics).forEach(([name, callback]) => {\n Object.defineProperty(obj, `$${name}`, {\n get() {\n return callback(el, memoizedUtilities);\n },\n enumerable: false\n });\n });\n return obj;\n}\nfunction getUtilities(el) {\n let [utilities, cleanup2] = getElementBoundUtilities(el);\n let utils = { interceptor, ...utilities };\n onElRemoved(el, cleanup2);\n return utils;\n}\n\n// packages/alpinejs/src/utils/error.js\nfunction tryCatch(el, expression, callback, ...args) {\n try {\n return callback(...args);\n } catch (e) {\n handleError(e, el, expression);\n }\n}\nfunction handleError(error2, el, expression = void 0) {\n error2 = Object.assign(\n error2 ?? { message: \"No error message given.\" },\n { el, expression }\n );\n console.warn(`Alpine Expression Error: ${error2.message}\n\n${expression ? 'Expression: \"' + expression + '\"\\n\\n' : \"\"}`, el);\n setTimeout(() => {\n throw error2;\n }, 0);\n}\n\n// packages/alpinejs/src/evaluator.js\nvar shouldAutoEvaluateFunctions = true;\nfunction dontAutoEvaluateFunctions(callback) {\n let cache = shouldAutoEvaluateFunctions;\n shouldAutoEvaluateFunctions = false;\n let result = callback();\n shouldAutoEvaluateFunctions = cache;\n return result;\n}\nfunction evaluate(el, expression, extras = {}) {\n let result;\n evaluateLater(el, expression)((value) => result = value, extras);\n return result;\n}\nfunction evaluateLater(...args) {\n return theEvaluatorFunction(...args);\n}\nvar theEvaluatorFunction = normalEvaluator;\nfunction setEvaluator(newEvaluator) {\n theEvaluatorFunction = newEvaluator;\n}\nfunction normalEvaluator(el, expression) {\n let overriddenMagics = {};\n injectMagics(overriddenMagics, el);\n let dataStack = [overriddenMagics, ...closestDataStack(el)];\n let evaluator = typeof expression === \"function\" ? generateEvaluatorFromFunction(dataStack, expression) : generateEvaluatorFromString(dataStack, expression, el);\n return tryCatch.bind(null, el, expression, evaluator);\n}\nfunction generateEvaluatorFromFunction(dataStack, func) {\n return (receiver = () => {\n }, { scope: scope2 = {}, params = [] } = {}) => {\n let result = func.apply(mergeProxies([scope2, ...dataStack]), params);\n runIfTypeOfFunction(receiver, result);\n };\n}\nvar evaluatorMemo = {};\nfunction generateFunctionFromString(expression, el) {\n if (evaluatorMemo[expression]) {\n return evaluatorMemo[expression];\n }\n let AsyncFunction = Object.getPrototypeOf(async function() {\n }).constructor;\n let rightSideSafeExpression = /^[\\n\\s]*if.*\\(.*\\)/.test(expression.trim()) || /^(let|const)\\s/.test(expression.trim()) ? `(async()=>{ ${expression} })()` : expression;\n const safeAsyncFunction = () => {\n try {\n let func2 = new AsyncFunction(\n [\"__self\", \"scope\"],\n `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`\n );\n Object.defineProperty(func2, \"name\", {\n value: `[Alpine] ${expression}`\n });\n return func2;\n } catch (error2) {\n handleError(error2, el, expression);\n return Promise.resolve();\n }\n };\n let func = safeAsyncFunction();\n evaluatorMemo[expression] = func;\n return func;\n}\nfunction generateEvaluatorFromString(dataStack, expression, el) {\n let func = generateFunctionFromString(expression, el);\n return (receiver = () => {\n }, { scope: scope2 = {}, params = [] } = {}) => {\n func.result = void 0;\n func.finished = false;\n let completeScope = mergeProxies([scope2, ...dataStack]);\n if (typeof func === \"function\") {\n let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));\n if (func.finished) {\n runIfTypeOfFunction(receiver, func.result, completeScope, params, el);\n func.result = void 0;\n } else {\n promise.then((result) => {\n runIfTypeOfFunction(receiver, result, completeScope, params, el);\n }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);\n }\n }\n };\n}\nfunction runIfTypeOfFunction(receiver, value, scope2, params, el) {\n if (shouldAutoEvaluateFunctions && typeof value === \"function\") {\n let result = value.apply(scope2, params);\n if (result instanceof Promise) {\n result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));\n } else {\n receiver(result);\n }\n } else if (typeof value === \"object\" && value instanceof Promise) {\n value.then((i) => receiver(i));\n } else {\n receiver(value);\n }\n}\n\n// packages/alpinejs/src/directives.js\nvar prefixAsString = \"x-\";\nfunction prefix(subject = \"\") {\n return prefixAsString + subject;\n}\nfunction setPrefix(newPrefix) {\n prefixAsString = newPrefix;\n}\nvar directiveHandlers = {};\nfunction directive(name, callback) {\n directiveHandlers[name] = callback;\n return {\n before(directive2) {\n if (!directiveHandlers[directive2]) {\n console.warn(String.raw`Cannot find directive \\`${directive2}\\`. \\`${name}\\` will use the default order of execution`);\n return;\n }\n const pos = directiveOrder.indexOf(directive2);\n directiveOrder.splice(pos >= 0 ? pos : directiveOrder.indexOf(\"DEFAULT\"), 0, name);\n }\n };\n}\nfunction directiveExists(name) {\n return Object.keys(directiveHandlers).includes(name);\n}\nfunction directives(el, attributes, originalAttributeOverride) {\n attributes = Array.from(attributes);\n if (el._x_virtualDirectives) {\n let vAttributes = Object.entries(el._x_virtualDirectives).map(([name, value]) => ({ name, value }));\n let staticAttributes = attributesOnly(vAttributes);\n vAttributes = vAttributes.map((attribute) => {\n if (staticAttributes.find((attr) => attr.name === attribute.name)) {\n return {\n name: `x-bind:${attribute.name}`,\n value: `\"${attribute.value}\"`\n };\n }\n return attribute;\n });\n attributes = attributes.concat(vAttributes);\n }\n let transformedAttributeMap = {};\n let directives2 = attributes.map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName)).filter(outNonAlpineAttributes).map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride)).sort(byPriority);\n return directives2.map((directive2) => {\n return getDirectiveHandler(el, directive2);\n });\n}\nfunction attributesOnly(attributes) {\n return Array.from(attributes).map(toTransformedAttributes()).filter((attr) => !outNonAlpineAttributes(attr));\n}\nvar isDeferringHandlers = false;\nvar directiveHandlerStacks = /* @__PURE__ */ new Map();\nvar currentHandlerStackKey = Symbol();\nfunction deferHandlingDirectives(callback) {\n isDeferringHandlers = true;\n let key = Symbol();\n currentHandlerStackKey = key;\n directiveHandlerStacks.set(key, []);\n let flushHandlers = () => {\n while (directiveHandlerStacks.get(key).length)\n directiveHandlerStacks.get(key).shift()();\n directiveHandlerStacks.delete(key);\n };\n let stopDeferring = () => {\n isDeferringHandlers = false;\n flushHandlers();\n };\n callback(flushHandlers);\n stopDeferring();\n}\nfunction getElementBoundUtilities(el) {\n let cleanups = [];\n let cleanup2 = (callback) => cleanups.push(callback);\n let [effect3, cleanupEffect] = elementBoundEffect(el);\n cleanups.push(cleanupEffect);\n let utilities = {\n Alpine: alpine_default,\n effect: effect3,\n cleanup: cleanup2,\n evaluateLater: evaluateLater.bind(evaluateLater, el),\n evaluate: evaluate.bind(evaluate, el)\n };\n let doCleanup = () => cleanups.forEach((i) => i());\n return [utilities, doCleanup];\n}\nfunction getDirectiveHandler(el, directive2) {\n let noop = () => {\n };\n let handler4 = directiveHandlers[directive2.type] || noop;\n let [utilities, cleanup2] = getElementBoundUtilities(el);\n onAttributeRemoved(el, directive2.original, cleanup2);\n let fullHandler = () => {\n if (el._x_ignore || el._x_ignoreSelf)\n return;\n handler4.inline && handler4.inline(el, directive2, utilities);\n handler4 = handler4.bind(handler4, el, directive2, utilities);\n isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler4) : handler4();\n };\n fullHandler.runCleanups = cleanup2;\n return fullHandler;\n}\nvar startingWith = (subject, replacement) => ({ name, value }) => {\n if (name.startsWith(subject))\n name = name.replace(subject, replacement);\n return { name, value };\n};\nvar into = (i) => i;\nfunction toTransformedAttributes(callback = () => {\n}) {\n return ({ name, value }) => {\n let { name: newName, value: newValue } = attributeTransformers.reduce((carry, transform) => {\n return transform(carry);\n }, { name, value });\n if (newName !== name)\n callback(newName, name);\n return { name: newName, value: newValue };\n };\n}\nvar attributeTransformers = [];\nfunction mapAttributes(callback) {\n attributeTransformers.push(callback);\n}\nfunction outNonAlpineAttributes({ name }) {\n return alpineAttributeRegex().test(name);\n}\nvar alpineAttributeRegex = () => new RegExp(`^${prefixAsString}([^:^.]+)\\\\b`);\nfunction toParsedDirectives(transformedAttributeMap, originalAttributeOverride) {\n return ({ name, value }) => {\n let typeMatch = name.match(alpineAttributeRegex());\n let valueMatch = name.match(/:([a-zA-Z0-9\\-_:]+)/);\n let modifiers = name.match(/\\.[^.\\]]+(?=[^\\]]*$)/g) || [];\n let original = originalAttributeOverride || transformedAttributeMap[name] || name;\n return {\n type: typeMatch ? typeMatch[1] : null,\n value: valueMatch ? valueMatch[1] : null,\n modifiers: modifiers.map((i) => i.replace(\".\", \"\")),\n expression: value,\n original\n };\n };\n}\nvar DEFAULT = \"DEFAULT\";\nvar directiveOrder = [\n \"ignore\",\n \"ref\",\n \"data\",\n \"id\",\n \"anchor\",\n \"bind\",\n \"init\",\n \"for\",\n \"model\",\n \"modelable\",\n \"transition\",\n \"show\",\n \"if\",\n DEFAULT,\n \"teleport\"\n];\nfunction byPriority(a, b) {\n let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type;\n let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type;\n return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB);\n}\n\n// packages/alpinejs/src/utils/dispatch.js\nfunction dispatch(el, name, detail = {}) {\n el.dispatchEvent(\n new CustomEvent(name, {\n detail,\n bubbles: true,\n // Allows events to pass the shadow DOM barrier.\n composed: true,\n cancelable: true\n })\n );\n}\n\n// packages/alpinejs/src/utils/walk.js\nfunction walk(el, callback) {\n if (typeof ShadowRoot === \"function\" && el instanceof ShadowRoot) {\n Array.from(el.children).forEach((el2) => walk(el2, callback));\n return;\n }\n let skip = false;\n callback(el, () => skip = true);\n if (skip)\n return;\n let node = el.firstElementChild;\n while (node) {\n walk(node, callback, false);\n node = node.nextElementSibling;\n }\n}\n\n// packages/alpinejs/src/utils/warn.js\nfunction warn(message, ...args) {\n console.warn(`Alpine Warning: ${message}`, ...args);\n}\n\n// packages/alpinejs/src/lifecycle.js\nvar started = false;\nfunction start() {\n if (started)\n warn(\"Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems.\");\n started = true;\n if (!document.body)\n warn(\"Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `
+