@ait-co/devtools 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -101,7 +101,8 @@ const DEFAULT_STATE = {
101
101
  customWidth: 402,
102
102
  customHeight: 874,
103
103
  frame: false,
104
- aitNavBar: true
104
+ aitNavBar: true,
105
+ aitNavBarType: "partner"
105
106
  }
106
107
  };
107
108
  function generateDeviceId() {
@@ -707,6 +708,22 @@ const PANEL_STYLES = `
707
708
  .ait-navbar-back { padding: 0 8px; font-size: 24px; }
708
709
  .ait-navbar-divider { width: 1px; height: 16px; background: rgba(0, 0, 0, 0.15); }
709
710
 
711
+ /* Game variant: 투명 배경, 우측 actions만 — 풀스크린 게임 캔버스를 가리지 않는다 */
712
+ .ait-navbar.ait-navbar-game {
713
+ background: transparent;
714
+ backdrop-filter: none;
715
+ justify-content: flex-end;
716
+ color: #fff;
717
+ }
718
+ .ait-navbar.ait-navbar-game .ait-navbar-actions {
719
+ background: rgba(0, 0, 0, 0.35);
720
+ color: #fff;
721
+ }
722
+ .ait-navbar.ait-navbar-game .ait-navbar-divider {
723
+ background: rgba(255, 255, 255, 0.3);
724
+ }
725
+ .ait-navbar.ait-navbar-game .ait-navbar-btn:hover { color: #8ab4ff; }
726
+
710
727
  @media (max-width: 720px) {
711
728
  .ait-panel.open {
712
729
  position: fixed;
@@ -1755,7 +1772,11 @@ function removeNavBarElement() {
1755
1772
  }
1756
1773
  /**
1757
1774
  * Apps in Toss host nav bar 렌더. OS status bar 아래에 48px 높이로 쌓인다.
1758
- * 구성: 좌측 뒤로가기(‹), 앱 아이콘 + 이름(`brand.displayName`), 우측 `⋯` + 구분선 + `×`.
1775
+ *
1776
+ * 변형(SDK `webViewProps.type`과 의미 일치):
1777
+ * - `partner` (기본): 흰 배경, 좌측 뒤로가기(‹), 앱 아이콘 + 이름(`brand.displayName`),
1778
+ * 우측 `⋯` + 구분선 + `×`.
1779
+ * - `game`: 투명 배경, 게임 캔버스를 가리지 않도록 우측 `⋯` + 구분선 + `×`만.
1759
1780
  *
1760
1781
  * `env(safe-area-inset-top)`에는 이 높이가 포함되지 않으므로 (공식 SDK 확인),
1761
1782
  * 오버레이는 preset.safeAreaTop만큼 아래로 내려서 그린다.
@@ -1763,23 +1784,14 @@ function removeNavBarElement() {
1763
1784
  * 뒤로가기 버튼은 `__ait:backEvent`를 트리거하고, X 버튼은 `closeView()`를 호출한다.
1764
1785
  * 실제 SDK 이벤트 플러밍을 한 곳에서 검증할 수 있다.
1765
1786
  */
1766
- function renderNavBar(preset, displayName) {
1787
+ function renderNavBar(preset, displayName, type) {
1767
1788
  removeNavBarElement();
1768
1789
  const el = h("div", {
1769
1790
  id: NAV_BAR_ELEMENT_ID,
1770
- className: "ait-navbar",
1791
+ className: `ait-navbar ait-navbar-${type}`,
1771
1792
  "aria-hidden": "true"
1772
1793
  });
1773
1794
  el.style.top = `${preset.safeAreaTop}px`;
1774
- const backBtn = h("button", {
1775
- className: "ait-navbar-btn ait-navbar-back",
1776
- type: "button",
1777
- "aria-label": "Back"
1778
- });
1779
- backBtn.textContent = "‹";
1780
- backBtn.addEventListener("click", () => {
1781
- aitState.trigger("backEvent");
1782
- });
1783
1795
  const moreBtn = h("button", {
1784
1796
  className: "ait-navbar-btn",
1785
1797
  type: "button",
@@ -1795,9 +1807,22 @@ function renderNavBar(preset, displayName) {
1795
1807
  closeBtn.addEventListener("click", () => {
1796
1808
  closeView().catch((err) => console.error("[@ait-co/devtools] navbar close failed:", err));
1797
1809
  });
1798
- const nameSpan = h("span", { className: "ait-navbar-name" });
1799
- nameSpan.textContent = displayName;
1800
- el.append(backBtn, h("div", { className: "ait-navbar-title" }, h("span", { className: "ait-navbar-icon" }), nameSpan), h("div", { className: "ait-navbar-actions" }, moreBtn, h("span", { className: "ait-navbar-divider" }), closeBtn));
1810
+ const actions = h("div", { className: "ait-navbar-actions" }, moreBtn, h("span", { className: "ait-navbar-divider" }), closeBtn);
1811
+ if (type === "game") el.append(actions);
1812
+ else {
1813
+ const backBtn = h("button", {
1814
+ className: "ait-navbar-btn ait-navbar-back",
1815
+ type: "button",
1816
+ "aria-label": "Back"
1817
+ });
1818
+ backBtn.textContent = "‹";
1819
+ backBtn.addEventListener("click", () => {
1820
+ aitState.trigger("backEvent");
1821
+ });
1822
+ const nameSpan = h("span", { className: "ait-navbar-name" });
1823
+ nameSpan.textContent = displayName;
1824
+ el.append(backBtn, h("div", { className: "ait-navbar-title" }, h("span", { className: "ait-navbar-icon" }), nameSpan), actions);
1825
+ }
1801
1826
  document.body.appendChild(el);
1802
1827
  }
1803
1828
  /**
@@ -1869,7 +1894,7 @@ function applyViewport(state) {
1869
1894
  else removeNotchElement();
1870
1895
  if (preset && state.frame && !landscape && preset.safeAreaBottom > 0) renderHomeIndicator();
1871
1896
  else removeHomeIndicator();
1872
- if (preset && state.aitNavBar && !landscape) renderNavBar(preset, aitState.state.brand.displayName);
1897
+ if (preset && state.aitNavBar && !landscape) renderNavBar(preset, aitState.state.brand.displayName, state.aitNavBarType);
1873
1898
  else removeNavBarElement();
1874
1899
  }
1875
1900
  function isViewportPresetId(v) {
@@ -1916,6 +1941,7 @@ function loadViewportFromStorage() {
1916
1941
  if (isValidCustomDimension(obj.customHeight)) next.customHeight = obj.customHeight;
1917
1942
  if (typeof obj.frame === "boolean") next.frame = obj.frame;
1918
1943
  if (typeof obj.aitNavBar === "boolean") next.aitNavBar = obj.aitNavBar;
1944
+ if (obj.aitNavBarType === "partner" || obj.aitNavBarType === "game") next.aitNavBarType = obj.aitNavBarType;
1919
1945
  return next;
1920
1946
  } catch {
1921
1947
  return null;
@@ -2063,6 +2089,16 @@ function renderViewportTab() {
2063
2089
  navBarCheckbox.addEventListener("change", () => {
2064
2090
  aitState.patch("viewport", { aitNavBar: navBarCheckbox.checked });
2065
2091
  });
2092
+ const navBarTypeSelect = h("select", { className: "ait-select" });
2093
+ if (disabled || !vp.aitNavBar) navBarTypeSelect.disabled = true;
2094
+ for (const opt of ["partner", "game"]) {
2095
+ const option = h("option", { value: opt }, opt);
2096
+ if (opt === vp.aitNavBarType) option.selected = true;
2097
+ navBarTypeSelect.appendChild(option);
2098
+ }
2099
+ navBarTypeSelect.addEventListener("change", () => {
2100
+ aitState.patch("viewport", { aitNavBarType: navBarTypeSelect.value });
2101
+ });
2066
2102
  const size = resolveViewportSize(vp);
2067
2103
  const statusEl = h("div", { className: "ait-section" });
2068
2104
  if (vp.preset === "none" || size.width === 0) statusEl.appendChild(h("div", { style: "color:#888;font-size:11px" }, "No viewport constraint — body fills the window."));
@@ -2080,7 +2116,7 @@ function renderViewportTab() {
2080
2116
  const insets = computeSafeAreaInsets(preset, landscape, vp.landscapeSide);
2081
2117
  rows.push(h("div", { className: "ait-status-row" }, h("span", {}, "Safe area"), h("span", { className: "ait-status-value" }, `T${insets.top} R${insets.right} B${insets.bottom} L${insets.left}`)));
2082
2118
  }
2083
- if (vp.aitNavBar && !landscape) rows.push(h("div", { className: "ait-status-row" }, h("span", {}, "AIT nav bar"), h("span", { className: "ait-status-value" }, `48px (excl. SafeArea)`)));
2119
+ if (vp.aitNavBar && !landscape) rows.push(h("div", { className: "ait-status-row" }, h("span", {}, "AIT nav bar"), h("span", { className: "ait-status-value" }, `48px (excl. SafeArea) · ${vp.aitNavBarType}`)));
2084
2120
  for (const row of rows) statusEl.appendChild(row);
2085
2121
  }
2086
2122
  const deviceSection = h("div", { className: "ait-section" }, h("div", { className: "ait-section-title" }, "Device"), h("div", { className: "ait-row" }, h("label", {}, "Preset"), presetSelect), h("div", { className: "ait-row" }, h("label", {}, "Orientation"), orientationSelect));
@@ -2088,7 +2124,7 @@ function renderViewportTab() {
2088
2124
  const notch = getPreset(vp.preset).notch;
2089
2125
  if (notch === "notch" || notch === "dynamic-island") deviceSection.appendChild(h("div", { className: "ait-row" }, h("label", {}, "Notch side"), landscapeSideSelect));
2090
2126
  }
2091
- container.append(deviceSection, customRow, h("div", { className: "ait-section" }, h("div", { className: "ait-section-title" }, "Appearance"), h("div", { className: "ait-row" }, h("label", {}, "Show frame"), frameCheckbox), h("div", { className: "ait-row" }, h("label", {}, "Show Apps in Toss nav bar"), navBarCheckbox)), statusEl);
2127
+ container.append(deviceSection, customRow, h("div", { className: "ait-section" }, h("div", { className: "ait-section-title" }, "Appearance"), h("div", { className: "ait-row" }, h("label", {}, "Show frame"), frameCheckbox), h("div", { className: "ait-row" }, h("label", {}, "Show Apps in Toss nav bar"), navBarCheckbox), h("div", { className: "ait-row" }, h("label", {}, "Nav bar type"), navBarTypeSelect)), statusEl);
2092
2128
  return container;
2093
2129
  }
2094
2130
  //#endregion
@@ -2339,7 +2375,7 @@ function mount() {
2339
2375
  mockBadge.textContent = aitState.state.panelEditable ? "EDIT" : "READ-ONLY";
2340
2376
  refreshPanel();
2341
2377
  });
2342
- const headerRight = h("span", { style: "display:flex;align-items:center;gap:6px" }, mockBadge, h("span", { style: "font-size:11px;color:#666;font-weight:400" }, `v0.1.5`), closeBtn);
2378
+ const headerRight = h("span", { style: "display:flex;align-items:center;gap:6px" }, mockBadge, h("span", { style: "font-size:11px;color:#666;font-weight:400" }, `v0.1.6`), closeBtn);
2343
2379
  const header = h("div", { className: "ait-panel-header" }, h("span", {}, "AIT DevTools"), headerRight);
2344
2380
  tabsEl = h("div", { className: "ait-panel-tabs" });
2345
2381
  for (const tab of TABS) {