From 9f86429a1252b45c95b7c62fbaa1b82de3723997 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 05 Jan 2026 18:16:07 +0000
Subject: [PATCH] =Complete TaxonomySelector.js and TaxonomyCreator.js refactor

---
 inc/ui/Navigation.php |  170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 166 insertions(+), 4 deletions(-)

diff --git a/inc/ui/Navigation.php b/inc/ui/Navigation.php
index 7988917..16a7e66 100644
--- a/inc/ui/Navigation.php
+++ b/inc/ui/Navigation.php
@@ -30,6 +30,8 @@
 	private bool $hasToggle = false;
 	protected array $defaultItemClasses = [];
 	private int $counter = 0;
+	private bool $isDrawer = false;
+	private bool $drawerCollapsed = true;
 
 	public function __construct(string $id = '') {
 		$this->id = $id ?: 'menu-' . uniqid();
@@ -124,11 +126,19 @@
 		if ($this->isNav) {
 			$html = '<nav id="' . esc_attr($this->id).'"' . $classStr.'>';
 
-			if ($this->hasToggle) {
+			// Drawer toggle or regular toggle
+			if ($this->isDrawer) {
+				$html .= '<button class="toggle main" type="button"
+                aria-expanded="' . ($this->drawerCollapsed ? 'false' : 'true') . '"
+                aria-controls="' . esc_attr($this->id) . '-list">
+                ' . jvbIcon('caret-left') . '
+                <span class="screen-reader-text">Toggle Menu</span>
+            </button>';
+			} elseif ($this->hasToggle) {
 				$html .= '<button class="toggle main" type="button" aria-expanded="false" aria-controls="' . esc_attr($this->id) . '">
-				' . jvbIcon('list') . '
-				<span class="screen-reader-text">Toggle Menu</span>
-			</button>';
+                ' . jvbIcon('list') . '
+                <span class="screen-reader-text">Toggle Menu</span>
+            </button>';
 			}
 		}
 		if (!$this->isNav) {
@@ -154,6 +164,95 @@
 		echo $html;
 		return $html;
 	}
+
+	/**
+	 * Configure as a drawer-style menu
+	 *
+	 * @param bool $collapsed Initial state
+	 * @return self
+	 */
+	public function asDrawer(bool $collapsed = true): self {
+		$this->isDrawer = true;
+		$this->drawerCollapsed = $collapsed;
+		$this->addClass('drawer');
+		if (!$collapsed) {
+			$this->addClass('open');
+		}
+		return $this;
+	}
+
+	public function isDrawer(): bool {
+		return $this->isDrawer;
+	}
+	/**
+	 * Add a section header
+	 *
+	 * @param string $title
+	 * @return MenuSection
+	 */
+	public function addSection(string $title): MenuSection {
+		$section = new MenuSection($title, ++$this->counter);
+		$this->items[] = $section;
+
+		if (!empty($this->defaultItemClasses)) {
+			foreach ($this->defaultItemClasses as $class) {
+				$section->addItemClass($class);
+			}
+		}
+
+		return $section;
+	}
+
+	/**
+	 * Populate menu from array structure
+	 *
+	 * @param array $items Array of menu items
+	 * @return self
+	 */
+	public function populateFromArray(array $items): self {
+		foreach ($items as $item) {
+			// Handle sections
+			if (!empty($item['section'])) {
+				$section = $this->addSection($item['section']);
+				if (!empty($item['items'])) {
+					$this->populateSection($section, $item['items']);
+				}
+				continue;
+			}
+
+			// Handle regular items
+			$menuItem = $this->addItem($item['text'] ?? '', $item['icon'] ?? '');
+
+			if (!empty($item['class'])) {
+				$menuItem->addClass($item['class']);
+			}
+			if (!empty($item['url'])) {
+				$menuItem->url($item['url']);
+			}
+
+			if (!empty($item['submenu'])) {
+				$submenu = $menuItem->submenu();
+				$submenu->populateFromArray($item['submenu']);
+			}
+		}
+
+		return $this;
+	}
+
+	private function populateSection(MenuSection $section, array $items): void {
+		foreach ($items as $item) {
+			$menuItem = $section->addItem($item['text'] ?? '', $item['icon'] ?? null);
+
+			if (!empty($item['url'])) {
+				$menuItem->url($item['url']);
+			}
+
+			if (!empty($item['submenu'])) {
+				$submenu = $menuItem->submenu();
+				$submenu->populateFromArray($item['submenu']);
+			}
+		}
+	}
 }
 
 /**
@@ -324,3 +423,66 @@
 		return $html;
 	}
 }
+
+/**
+ * Menu section with header and items
+ */
+class MenuSection {
+	private int $id;
+	private string $title;
+	private array $items = [];
+	private array $classes = [];
+	private array $defaultItemClasses = [];
+	private int $counter = 0;
+
+	public function __construct(string $title, int $id) {
+		$this->title = $title;
+		$this->id = $id;
+	}
+
+	public function addItem(?string $text = null, ?string $icon = null): MenuItem {
+		$item = new MenuItem(++$this->counter);
+		$this->items[] = $item;
+
+		if ($text) $item->text($text);
+		if ($icon) $item->icon($icon);
+
+		if (!empty($this->defaultItemClasses)) {
+			foreach ($this->defaultItemClasses as $class) {
+				$item->addClass($class);
+			}
+		}
+
+		return $item;
+	}
+
+	public function addClass(string $class): self {
+		$this->classes[] = $class;
+		return $this;
+	}
+
+	public function addItemClass(string $class): self {
+		$this->defaultItemClasses[] = $class;
+		return $this;
+	}
+
+	public function render(): string {
+		if (empty($this->items)) {
+			return '';
+		}
+
+		$classStr = !empty($this->classes) ? ' class="menu-section ' . esc_attr(implode(' ', $this->classes)) . '"' : ' class="menu-section"';
+
+		$html = '<li' . $classStr . '>';
+		$html .= '<span class="section-title">' . esc_html($this->title) . '</span>';
+		$html .= '<ul class="section-items">';
+
+		foreach ($this->items as $item) {
+			$html .= $item->render();
+		}
+
+		$html .= '</ul></li>';
+
+		return $html;
+	}
+}

--
Gitblit v1.10.0