diff --git a/assets/admin/public/images/header-layout/header_layout_1.png b/assets/admin/public/images/header-layout/header_layout_1.png
new file mode 100644
index 00000000..4e6a0294
Binary files /dev/null and b/assets/admin/public/images/header-layout/header_layout_1.png differ
diff --git a/assets/admin/public/images/header-layout/header_layout_2.png b/assets/admin/public/images/header-layout/header_layout_2.png
new file mode 100644
index 00000000..71b63926
Binary files /dev/null and b/assets/admin/public/images/header-layout/header_layout_2.png differ
diff --git a/assets/admin/public/images/header-layout/header_layout_3.png b/assets/admin/public/images/header-layout/header_layout_3.png
new file mode 100644
index 00000000..ecec0020
Binary files /dev/null and b/assets/admin/public/images/header-layout/header_layout_3.png differ
diff --git a/assets/admin/public/images/header-layout/mobile_header_layout_center.png b/assets/admin/public/images/header-layout/mobile_header_layout_center.png
new file mode 100644
index 00000000..6a7d68c3
Binary files /dev/null and b/assets/admin/public/images/header-layout/mobile_header_layout_center.png differ
diff --git a/assets/admin/public/images/header-layout/mobile_header_layout_left.png b/assets/admin/public/images/header-layout/mobile_header_layout_left.png
new file mode 100644
index 00000000..3574ccc1
Binary files /dev/null and b/assets/admin/public/images/header-layout/mobile_header_layout_left.png differ
diff --git a/assets/admin/src/schema/sections/page-display/index.js b/assets/admin/src/schema/sections/page-display/index.js
index 659a813a..a999be28 100644
--- a/assets/admin/src/schema/sections/page-display/index.js
+++ b/assets/admin/src/schema/sections/page-display/index.js
@@ -3,6 +3,14 @@
* Each key corresponds to a sub-page under the "页面&显示" section.
*/
+/** Theme asset base for layout previews (admin SPA). */
+function themeAsset(path) {
+ const base = (typeof window !== 'undefined' && window.aksrtAdminData && window.aksrtAdminData.themeUri)
+ ? String(window.aksrtAdminData.themeUri).replace(/\/$/, '')
+ : ''
+ return base ? `${base}/${path.replace(/^\//, '')}` : path
+}
+
/** Homepage sort options — keep in sync with AKSRT_Settings_Home_Cms::homepage_allowed_sorts() */
const sortOptions = [
{ label: '最近更新', value: 'modified' },
@@ -79,23 +87,23 @@ export const pageDisplaySchemas = {
{
key: 'header_layout',
label: '电脑端布局',
- type: 'radio',
- default: '2',
+ type: 'image_select',
+ default: '1',
options: [
- { label: '布局 1(经典)', value: '1' },
- { label: '布局 2(内联搜索)', value: '2' },
- { label: '布局 3(紧凑)', value: '3' },
+ { label: '布局 1(经典)', value: '1', image: themeAsset('assets/images/header-layout/header_layout_1.png') },
+ { label: '布局 2(内联搜索)', value: '2', image: themeAsset('assets/images/header-layout/header_layout_2.png') },
+ { label: '布局 3(紧凑)', value: '3', image: themeAsset('assets/images/header-layout/header_layout_3.png') },
],
- help: '不同布局切换导航 DOM 结构',
+ help: '不同布局切换导航 DOM 结构(与 zibll image_select 一致)',
},
{
key: 'mobile_header_layout',
label: '移动端布局',
- type: 'radio',
+ type: 'image_select',
default: 'center',
options: [
- { label: '居中(含搜索按钮)', value: 'center' },
- { label: '靠左', value: 'left' },
+ { label: '居中(含搜索按钮)', value: 'center', image: themeAsset('assets/images/header-layout/mobile_header_layout_center.png') },
+ { label: '靠左', value: 'left', image: themeAsset('assets/images/header-layout/mobile_header_layout_left.png') },
],
},
{
diff --git a/assets/css/frontend/nav/zib-utilities.css b/assets/css/frontend/nav/zib-utilities.css
index 2f2ed681..ba3d1e3c 100644
--- a/assets/css/frontend/nav/zib-utilities.css
+++ b/assets/css/frontend/nav/zib-utilities.css
@@ -130,3 +130,35 @@ body.mobile-navbar-show { overflow: hidden; }
border-radius: 0;
z-index: 998;
}
+
+.navbar-inline-search-panel {
+ position: absolute;
+ left: 0;
+ top: calc(100% + 8px);
+ min-width: 280px;
+ max-width: 360px;
+ padding: 12px;
+ background: var(--main-bg-color, #fff);
+ border-radius: var(--main-radius, 8px);
+ box-shadow: 0 8px 24px rgba(0,0,0,.12);
+ z-index: 1002;
+ display: none;
+}
+.navbar-form .form-group:hover .navbar-inline-search-panel,
+.navbar-form .form-group:focus-within .navbar-inline-search-panel,
+.navbar-inline-search-panel.is-open {
+ display: block;
+ visibility: visible;
+}
+.navbar-inline-search-suggest__item {
+ display: flex;
+ flex-direction: column;
+ padding: 6px 4px;
+ color: inherit;
+ text-decoration: none;
+}
+.navbar-inline-search-suggest__item:hover { color: var(--focus-color); }
+.navbar-inline-search-hots .but { margin: 0 4px 4px 0; }
+.aksrt-sme-field { display: block; margin: 4px 0; }
+.aksrt-sme-field span { display: block; font-size: 12px; color: #646970; }
+.aksrt-sme-card, .aksrt-sme-col { border: 1px solid #dcdcde; padding: 8px; margin: 8px 0; border-radius: 4px; }
diff --git a/assets/images/header-layout/header_layout_1.png b/assets/images/header-layout/header_layout_1.png
new file mode 100644
index 00000000..4e6a0294
Binary files /dev/null and b/assets/images/header-layout/header_layout_1.png differ
diff --git a/assets/images/header-layout/header_layout_2.png b/assets/images/header-layout/header_layout_2.png
new file mode 100644
index 00000000..71b63926
Binary files /dev/null and b/assets/images/header-layout/header_layout_2.png differ
diff --git a/assets/images/header-layout/header_layout_3.png b/assets/images/header-layout/header_layout_3.png
new file mode 100644
index 00000000..ecec0020
Binary files /dev/null and b/assets/images/header-layout/header_layout_3.png differ
diff --git a/assets/images/header-layout/mobile_header_layout_center.png b/assets/images/header-layout/mobile_header_layout_center.png
new file mode 100644
index 00000000..6a7d68c3
Binary files /dev/null and b/assets/images/header-layout/mobile_header_layout_center.png differ
diff --git a/assets/images/header-layout/mobile_header_layout_left.png b/assets/images/header-layout/mobile_header_layout_left.png
new file mode 100644
index 00000000..3574ccc1
Binary files /dev/null and b/assets/images/header-layout/mobile_header_layout_left.png differ
diff --git a/assets/js/admin-nav-menu-senior.js b/assets/js/admin-nav-menu-senior.js
new file mode 100644
index 00000000..a6dadc76
--- /dev/null
+++ b/assets/js/admin-nav-menu-senior.js
@@ -0,0 +1,243 @@
+/**
+ * Nav menu senior submenu visual editors (graphic cards / multi-column).
+ * Enhances WP Appearance → Menus fields for aksrt_menu_options JSON.
+ *
+ * @package AKSRT
+ */
+(function ($) {
+ 'use strict';
+
+ function parseJSON(raw, fallback) {
+ try {
+ var data = JSON.parse(raw || '');
+ return data && typeof data === 'object' ? data : fallback;
+ } catch (e) {
+ return fallback;
+ }
+ }
+
+ function graphicTemplate() {
+ return {
+ arrangement: '',
+ size: 'md',
+ img_scale: 100,
+ items: [{ img: '', title: '', badge: '', badge_class: 'jb-red', link: { url: '', text: '', target: '' } }],
+ };
+ }
+
+ function multiTemplate() {
+ return {
+ columns: [
+ {
+ title: '',
+ icon: '',
+ img_icon: '',
+ link: { url: '', text: '', target: '' },
+ items: [{ title: '', icon: '', img_icon: '', link: { url: '', text: '', target: '' } }],
+ },
+ ],
+ };
+ }
+
+ function field(name, label, value, type) {
+ type = type || 'text';
+ return (
+ '' +
+ label +
+ ' '
+ );
+ }
+
+ function renderGraphicUI($wrap, data) {
+ var html = '
';
+ html += '添加卡片 ';
+ html += '
';
+ (data.items || []).forEach(function (item, i) {
+ html += '
';
+ html += '
卡片 #' + (i + 1) + ' ';
+ html += ' 删除
';
+ html += field('img', '图片 URL', item.img || '');
+ html += field('title', '标题', item.title || '');
+ html += field('badge', '徽章', item.badge || '');
+ html += field('badge_class', '徽章 class', item.badge_class || '');
+ html += field('link.url', '链接', (item.link && item.link.url) || '');
+ html += '
';
+ });
+ html += '
';
+ html += field('size', '尺寸 sm/md/lg/xs', data.size || 'md');
+ html += field('img_scale', '图片比例%', data.img_scale || 100, 'number');
+ $wrap.html(html);
+ }
+
+ function renderMultiUI($wrap, data) {
+ var html = '';
+ html += '添加栏目 ';
+ html += '
';
+ (data.columns || []).forEach(function (col, i) {
+ html += '
';
+ html += '
栏目 #' + (i + 1) + ' ';
+ html += ' 删除栏目
';
+ html += field('title', '栏目标题', col.title || '');
+ html += field('icon', '图标 class', col.icon || '');
+ html += field('link.url', '栏目链接', (col.link && col.link.url) || '');
+ html += '
';
+ (col.items || []).forEach(function (item, j) {
+ html += '
';
+ html += field('items.' + j + '.title', '链接标题', item.title || '');
+ html += field('items.' + j + '.link.url', '链接 URL', (item.link && item.link.url) || '');
+ html += field('items.' + j + '.icon', '图标', item.icon || '');
+ html += '
';
+ });
+ html += '
添加链接 ';
+ html += '
';
+ });
+ html += '
';
+ $wrap.html(html);
+ }
+
+ function readGraphic($wrap) {
+ var data = graphicTemplate();
+ data.size = $wrap.find('[data-name="size"]').val() || 'md';
+ data.img_scale = parseInt($wrap.find('[data-name="img_scale"]').val(), 10) || 100;
+ data.items = [];
+ $wrap.find('.aksrt-sme-card').each(function () {
+ var $c = $(this);
+ data.items.push({
+ img: $c.find('[data-name="img"]').val() || '',
+ title: $c.find('[data-name="title"]').val() || '',
+ badge: $c.find('[data-name="badge"]').val() || '',
+ badge_class: $c.find('[data-name="badge_class"]').val() || '',
+ link: { url: $c.find('[data-name="link.url"]').val() || '', text: '', target: '' },
+ });
+ });
+ return data;
+ }
+
+ function readMulti($wrap) {
+ var data = { columns: [] };
+ $wrap.find('.aksrt-sme-col').each(function () {
+ var $col = $(this);
+ var col = {
+ title: $col.find('[data-name="title"]').first().val() || '',
+ icon: $col.find('[data-name="icon"]').first().val() || '',
+ img_icon: '',
+ link: { url: $col.find('[data-name="link.url"]').first().val() || '', text: '', target: '' },
+ items: [],
+ };
+ $col.find('.aksrt-sme-item').each(function () {
+ var $it = $(this);
+ col.items.push({
+ title: $it.find('input[data-name$=".title"]').val() || '',
+ icon: $it.find('input[data-name$=".icon"]').val() || '',
+ img_icon: '',
+ link: { url: $it.find('input[data-name$=".link.url"]').val() || '', text: '', target: '' },
+ });
+ });
+ data.columns.push(col);
+ });
+ return data;
+ }
+
+ function enhanceItem($item) {
+ if ($item.data('aksrtSme')) return;
+ $item.data('aksrtSme', 1);
+
+ var $graphicTa = $item.find('textarea[name*="[graphic_card_opts_json]"]');
+ var $multiTa = $item.find('textarea[name*="[multi_column_links_opts_json]"]');
+ var $type = $item.find('select[name*="[submenu_type]"]');
+ if (!$graphicTa.length && !$multiTa.length) return;
+
+ var $ui = $('
');
+ $graphicTa.closest('p').before($ui);
+
+ function sync() {
+ var type = $type.val();
+ if (type === 'graphic_card') {
+ $graphicTa.closest('p').hide();
+ $multiTa.closest('p').hide();
+ var g = parseJSON($graphicTa.val(), graphicTemplate());
+ renderGraphicUI($ui, g);
+ $ui.show();
+ } else if (type === 'multi_column_links') {
+ $graphicTa.closest('p').hide();
+ $multiTa.closest('p').hide();
+ var m = parseJSON($multiTa.val(), multiTemplate());
+ renderMultiUI($ui, m);
+ $ui.show();
+ } else {
+ $ui.hide().empty();
+ $graphicTa.closest('p').show();
+ $multiTa.closest('p').show();
+ }
+ }
+
+ $type.on('change', sync);
+ $ui.on('click', '.aksrt-sme-add-card', function (e) {
+ e.preventDefault();
+ var g = readGraphic($ui);
+ g.items.push({ img: '', title: '', badge: '', badge_class: 'jb-red', link: { url: '', text: '', target: '' } });
+ renderGraphicUI($ui, g);
+ });
+ $ui.on('click', '.aksrt-sme-del-card', function (e) {
+ e.preventDefault();
+ $(this).closest('.aksrt-sme-card').remove();
+ });
+ $ui.on('click', '.aksrt-sme-add-col', function (e) {
+ e.preventDefault();
+ var m = readMulti($ui);
+ m.columns.push({
+ title: '',
+ icon: '',
+ img_icon: '',
+ link: { url: '', text: '', target: '' },
+ items: [{ title: '', icon: '', img_icon: '', link: { url: '', text: '', target: '' } }],
+ });
+ renderMultiUI($ui, m);
+ });
+ $ui.on('click', '.aksrt-sme-del-col', function (e) {
+ e.preventDefault();
+ $(this).closest('.aksrt-sme-col').remove();
+ });
+ $ui.on('click', '.aksrt-sme-add-item', function (e) {
+ e.preventDefault();
+ var $col = $(this).closest('.aksrt-sme-col');
+ var m = readMulti($ui);
+ var idx = $col.index();
+ if (m.columns[idx]) {
+ m.columns[idx].items.push({ title: '', icon: '', img_icon: '', link: { url: '', text: '', target: '' } });
+ }
+ renderMultiUI($ui, m);
+ });
+
+ // Before save, write UI → textarea
+ $('#update-nav-menu').on('submit.aksrtSme', function () {
+ var type = $type.val();
+ if (type === 'graphic_card') {
+ $graphicTa.val(JSON.stringify(readGraphic($ui), null, 2));
+ } else if (type === 'multi_column_links') {
+ $multiTa.val(JSON.stringify(readMulti($ui), null, 2));
+ }
+ });
+
+ // Hide raw JSON by default; toggle available via double-click title
+ $graphicTa.closest('p').find('label').attr('title', '双击显示原始 JSON');
+ sync();
+ }
+
+ function boot() {
+ $('#menu-to-edit .menu-item').each(function () {
+ enhanceItem($(this));
+ });
+ }
+
+ $(boot);
+ $(document).on('menu-item-added', function () {
+ setTimeout(boot, 50);
+ });
+})(jQuery);
diff --git a/assets/js/header-inline-search.js b/assets/js/header-inline-search.js
new file mode 100644
index 00000000..75b79f09
--- /dev/null
+++ b/assets/js/header-inline-search.js
@@ -0,0 +1,140 @@
+/**
+ * Enhance layout-2 inline search with AJAX suggestions (aksrt_search_suggestions).
+ * Extends existing panel search without dual systems.
+ */
+(function () {
+ "use strict";
+
+ function initInlineSearchSuggest() {
+ var form = document.querySelector('form[data-aksrt-search-form="inline"]');
+ if (!form || !window.aksrtData || !aksrtData.ajaxUrl) return;
+
+ var input = form.querySelector(".search-input");
+ var group = form.querySelector(".form-group.relative, .form-group");
+ if (!input || !group) return;
+
+ var panel = group.querySelector(".navbar-inline-search-panel");
+ if (!panel) {
+ panel = document.createElement("div");
+ panel.className = "dropdown-menu hover-show-con navbar-inline-search-panel";
+ group.appendChild(panel);
+ }
+
+ var timer = null;
+ var searchConfig = (window.aksrtData && aksrtData.search) || {};
+ var suggestionsEnabled = searchConfig.suggestionsEnabled !== false;
+
+ function typeValue() {
+ var t = form.querySelector('input[name="aksrt_search_type"]');
+ return (t && t.value) || searchConfig.defaultType || "post";
+ }
+
+ function renderItems(items) {
+ var html = "";
+ if (items && items.length) {
+ html += '' + (searchConfig.suggestTitle || "搜索建议") + "
";
+ html += '";
+ }
+ // Keep hot keywords block if present as static sibling content was replaced —
+ // re-append hots from data attribute if we stored them.
+ var hots = form.getAttribute("data-hots");
+ if (hots) {
+ try {
+ var arr = JSON.parse(hots);
+ if (arr && arr.length) {
+ html += '热门搜索
';
+ arr.forEach(function (kw) {
+ html +=
+ '
' +
+ kw +
+ " ";
+ });
+ html += "
";
+ }
+ } catch (e) {}
+ }
+ panel.innerHTML = html || panel.innerHTML;
+ panel.classList.add("is-open");
+ panel.style.display = "block";
+ panel.style.visibility = "visible";
+ }
+
+ // Persist hot keywords for re-render after suggestions
+ var hotLinks = panel.querySelectorAll(".navbar-inline-search-hots a");
+ if (hotLinks.length) {
+ var kws = [];
+ hotLinks.forEach(function (a) {
+ kws.push((a.textContent || "").trim());
+ });
+ form.setAttribute("data-hots", JSON.stringify(kws));
+ }
+
+ function request(q) {
+ if (!suggestionsEnabled || q.length < 2) {
+ // restore hots-only
+ if (form.getAttribute("data-hots")) {
+ renderItems([]);
+ }
+ return;
+ }
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", aksrtData.ajaxUrl, true);
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+ xhr.onload = function () {
+ if (xhr.status < 200 || xhr.status >= 300) return;
+ try {
+ var json = JSON.parse(xhr.responseText);
+ if (json.success && json.data && json.data.items) {
+ renderItems(json.data.items);
+ }
+ } catch (e) {}
+ };
+ xhr.send(
+ "action=aksrt_search_suggestions&nonce=" +
+ encodeURIComponent(aksrtData.nonce) +
+ "&q=" +
+ encodeURIComponent(q) +
+ "&type=" +
+ encodeURIComponent(typeValue())
+ );
+ }
+
+ input.addEventListener("input", function () {
+ var q = (input.value || "").trim();
+ if (timer) clearTimeout(timer);
+ timer = setTimeout(function () {
+ request(q);
+ }, 180);
+ });
+
+ input.addEventListener("focus", function () {
+ panel.style.display = "block";
+ panel.style.visibility = "visible";
+ });
+ }
+
+ if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") {
+ window.AksrtFrontend.register("aksrt-inline-search-suggest", function () {
+ initInlineSearchSuggest();
+ });
+ } else if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", initInlineSearchSuggest);
+ } else {
+ initInlineSearchSuggest();
+ }
+})();
diff --git a/src/AKSRT/Admin/Admin.php b/src/AKSRT/Admin/Admin.php
index a43c365d..004b3384 100644
--- a/src/AKSRT/Admin/Admin.php
+++ b/src/AKSRT/Admin/Admin.php
@@ -132,6 +132,7 @@ class Admin {
'siteUrl' => home_url('/'),
'adminUrl' => admin_url('/'),
'themeVersion' => wp_get_theme()->get('Version') ?: '3.4.0-dev',
+ 'themeUri' => defined('AKSRT_URI') ? AKSRT_URI : get_template_directory_uri(),
'buildOk' => $missing_chunks === [],
]);
diff --git a/src/AKSRT/Admin/NavMenuOptions.php b/src/AKSRT/Admin/NavMenuOptions.php
index 9821a877..283181de 100644
--- a/src/AKSRT/Admin/NavMenuOptions.php
+++ b/src/AKSRT/Admin/NavMenuOptions.php
@@ -14,6 +14,24 @@ class NavMenuOptions {
public static function init(): void {
add_action('wp_nav_menu_item_custom_fields', [self::class, 'render_fields'], 10, 2);
add_action('wp_update_nav_menu_item', [self::class, 'save'], 10, 2);
+ add_action('admin_enqueue_scripts', [self::class, 'enqueue_admin']);
+ }
+
+ public static function enqueue_admin(string $hook): void {
+ if ($hook !== 'nav-menus.php') {
+ return;
+ }
+ $path = get_template_directory() . '/assets/js/admin-nav-menu-senior.js';
+ if (!file_exists($path)) {
+ return;
+ }
+ wp_enqueue_script(
+ 'aksrt-admin-nav-menu-senior',
+ get_template_directory_uri() . '/assets/js/admin-nav-menu-senior.js',
+ ['jquery'],
+ (string) filemtime($path),
+ true
+ );
}
/**
diff --git a/src/AKSRT/Admin/Schema/SchemaPageDisplay.php b/src/AKSRT/Admin/Schema/SchemaPageDisplay.php
index c84290d1..128c727b 100644
--- a/src/AKSRT/Admin/Schema/SchemaPageDisplay.php
+++ b/src/AKSRT/Admin/Schema/SchemaPageDisplay.php
@@ -31,15 +31,8 @@ class SchemaPageDisplay {
['key' => 'header_scroll_down_hide', 'label' => '下滑隐藏导航栏', 'type' => 'switch', 'default' => true],
]],
['key' => 'layout-type', 'title' => '布局类型', 'fields' => [
- ['key' => 'header_layout', 'label' => '桌面端布局', 'type' => 'radio', 'default' => '1', 'options' => [
- ['label' => '布局 1(经典)', 'value' => '1'],
- ['label' => '布局 2(内联搜索)', 'value' => '2'],
- ['label' => '布局 3(紧凑)', 'value' => '3'],
- ]],
- ['key' => 'mobile_header_layout', 'label' => '移动端布局', 'type' => 'radio', 'default' => 'center', 'options' => [
- ['label' => '居中(含搜索按钮)', 'value' => 'center'],
- ['label' => '靠左', 'value' => 'left'],
- ]],
+ ['key' => 'header_layout', 'label' => '桌面端布局', 'type' => 'image_select', 'default' => '1', 'options' => self::header_layout_options()],
+ ['key' => 'mobile_header_layout', 'label' => '移动端布局', 'type' => 'image_select', 'default' => 'center', 'options' => self::mobile_header_layout_options()],
['key' => 'mobile_navbar_align', 'label' => '移动端菜单方向', 'type' => 'radio', 'default' => 'left', 'options' => [
['label' => '顶部(关闭手势)', 'value' => 'top'],
['label' => '左侧滑出', 'value' => 'left'],
@@ -532,4 +525,24 @@ class SchemaPageDisplay {
],
];
}
+
+ /** @return list */
+ private static function header_layout_options(): array {
+ $base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/images/header-layout/' : '';
+ return [
+ ['label' => '布局 1(经典)', 'value' => '1', 'image' => $base . 'header_layout_1.png'],
+ ['label' => '布局 2(内联搜索)', 'value' => '2', 'image' => $base . 'header_layout_2.png'],
+ ['label' => '布局 3(紧凑)', 'value' => '3', 'image' => $base . 'header_layout_3.png'],
+ ];
+ }
+
+ /** @return list */
+ private static function mobile_header_layout_options(): array {
+ $base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/images/header-layout/' : '';
+ return [
+ ['label' => '居中(含搜索按钮)', 'value' => 'center', 'image' => $base . 'mobile_header_layout_center.png'],
+ ['label' => '靠左', 'value' => 'left', 'image' => $base . 'mobile_header_layout_left.png'],
+ ];
+ }
+
}
diff --git a/src/AKSRT/Core/ScriptsPart1b.php b/src/AKSRT/Core/ScriptsPart1b.php
index 8c546af0..50d7a1d6 100644
--- a/src/AKSRT/Core/ScriptsPart1b.php
+++ b/src/AKSRT/Core/ScriptsPart1b.php
@@ -161,7 +161,19 @@ trait ScriptsPart1b {
);
}
- $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
+
+ $inline_search_js = get_template_directory() . '/assets/js/header-inline-search.js';
+ if (file_exists($inline_search_js)) {
+ wp_enqueue_script(
+ 'aksrt-header-inline-search',
+ $base_uri . '/assets/js/header-inline-search.js',
+ [],
+ (string) filemtime($inline_search_js),
+ true
+ );
+ }
+
+$hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
if (file_exists($hmb_js)) {
wp_enqueue_script(
'aksrt-header-newadd',
diff --git a/tools/nav-zibll-acceptance.md b/tools/nav-zibll-acceptance.md
new file mode 100644
index 00000000..48c5cdcd
--- /dev/null
+++ b/tools/nav-zibll-acceptance.md
@@ -0,0 +1,35 @@
+# Top nav zibll 1:1 acceptance checklist
+
+Branch: `worktree-nav-zibll-1to1`
+
+## Desktop
+- [ ] Layout 1: logo | menu | publish/VIP | theme(+lang) | user | search icon
+- [ ] Layout 2: logo | menu | inline search(+hot/suggest) | CTAs | user (no search icon)
+- [ ] Layout 3: logo | CTAs/user | menu right cluster
+- [ ] Fixed `body.nav-fixed` 88px reserve; hero show-slide pull-up
+- [ ] Scroll-down hide / scroll-up show
+- [ ] Submenu hover + chevron; overflow folding "更多"
+- [ ] Publish single vs multi; VIP hover cards gated by switches
+- [ ] User box density + user-card publish type URL
+- [ ] Header theme colors when custom enabled
+- [ ] Language dropdown when i18n enabled + position header/both
+
+## Mobile
+- [ ] center/left header; drawer left/right/top
+- [ ] `body.mobile-navbar-show` open/close + fixed-body + swipe
+- [ ] mobile menus depth 2 + user box + widgets
+- [ ] posts-nav-box TOC on single posts
+
+## Admin
+- [ ] SPA image_select previews for layouts
+- [ ] newposts types multi + VIP switches persist
+- [ ] Appearance → Menus: icon/badge/senior visual editor saves meta
+- [ ] `cd assets/admin && npm run build` after schema changes
+
+## Page/section navs
+- [ ] section-navs builds `.posts-nav-lists` on `[data-nav]` pages
+- [ ] page-navs enqueued on posts-navs template
+
+## Deploy notes
+- Admin `build/` is gitignored — run build on deploy host.
+- PR: open from branch `worktree-nav-zibll-1to1` against main on Gitea.
diff --git a/tools/nav-zibll-contract-report.txt b/tools/nav-zibll-contract-report.txt
new file mode 100644
index 00000000..60a53575
--- /dev/null
+++ b/tools/nav-zibll-contract-report.txt
@@ -0,0 +1 @@
+PASS all nav zibll source contracts