v4.0.0: UNIARE 리브랜딩·레이아웃·덱 UX 개선

제품명·헤더 로고 이미지 통일, 덱 이름 변경·조회 수 제거, 썸네일 홀드 미리보기를 누르는 동안만 표시하도록 수정하고 Tailwind CSS를 재빌드했다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-23 11:19:07 +09:00
parent 2228757ea5
commit a281d731a1
32 changed files with 201 additions and 1910 deletions

View File

@@ -1,5 +1,5 @@
/**
* UADECK API 클라이언트
* UNIARE API 클라이언트
*/
const UaDeckApi = (() => {
const TOKEN_KEY = 'uadeck_token';
@@ -10,6 +10,7 @@ const UaDeckApi = (() => {
* @returns {string}
*/
function getBaseUrl() {
if (window.UNIARE_API_BASE) return window.UNIARE_API_BASE;
if (window.UADECK_API_BASE) return window.UADECK_API_BASE;
const { hostname, port, protocol } = window.location;

View File

@@ -1,15 +1,12 @@
/**
* 썸네일 미리보기 확대 (클릭 고정 / 길게 누르기)
* 썸네일 미리보기 확대 (길게 누르는 동안만 표시)
*/
(function initDeckPreviewHold() {
/** @type {HTMLElement|null} */
let overlay = null;
/** @type {number} */
let pressStartAt = 0;
/** @type {boolean} */
let suppressClick = false;
/** @type {number|null} */
let holdTimer = null;
/** @type {number} */
const HOLD_THRESHOLD_MS = 280;
@@ -25,21 +22,11 @@
overlay.setAttribute('aria-modal', 'true');
overlay.innerHTML =
'<div class="deck-preview-hold-box"><img alt="" draggable="false" /></div>';
overlay.addEventListener('click', (e) => {
if (e.target === overlay) hide();
});
document.body.appendChild(overlay);
}
return overlay;
}
/**
* @returns {boolean}
*/
function isVisible() {
return Boolean(overlay && !overlay.classList.contains('hidden'));
}
/**
* @param {string} src
*/
@@ -51,10 +38,16 @@
el.classList.remove('hidden');
}
function clearHoldTimer() {
if (holdTimer !== null) {
window.clearTimeout(holdTimer);
holdTimer = null;
}
}
function hide() {
clearHoldTimer();
if (overlay) overlay.classList.add('hidden');
pressStartAt = 0;
suppressClick = false;
}
/**
@@ -75,6 +68,20 @@
return hold.dataset.previewSrc || '';
}
/**
* @param {PointerEvent} e
* @param {HTMLElement|null} hold
*/
function releaseCapture(e, hold) {
if (hold?.releasePointerCapture && e.pointerId !== undefined) {
try {
hold.releasePointerCapture(e.pointerId);
} catch {
/* ignore */
}
}
}
function initGlobal() {
if (document.documentElement.dataset.deckHoldInit === '1') return;
document.documentElement.dataset.deckHoldInit = '1';
@@ -87,8 +94,11 @@
const src = getPreviewSrc(hold);
if (!src) return;
pressStartAt = Date.now();
show(src);
clearHoldTimer();
holdTimer = window.setTimeout(() => {
holdTimer = null;
show(src);
}, HOLD_THRESHOLD_MS);
if (hold.setPointerCapture && e.pointerId !== undefined) {
try {
@@ -104,32 +114,9 @@
document.addEventListener(
'pointerup',
(e) => {
if (!pressStartAt) return;
const hold = findHoldTarget(e);
if (hold?.releasePointerCapture && e.pointerId !== undefined) {
try {
hold.releasePointerCapture(e.pointerId);
} catch {
/* ignore */
}
}
const heldMs = Date.now() - pressStartAt;
pressStartAt = 0;
if (heldMs >= HOLD_THRESHOLD_MS) {
hide();
suppressClick = true;
window.setTimeout(() => {
suppressClick = false;
}, 0);
} else {
suppressClick = true;
window.setTimeout(() => {
suppressClick = false;
}, 400);
}
releaseCapture(e, hold);
hide();
},
true,
);
@@ -142,25 +129,6 @@
true,
);
document.addEventListener('click', (e) => {
if (suppressClick) return;
const hold = findHoldTarget(e);
if (hold) {
const src = getPreviewSrc(hold);
if (!src) return;
e.preventDefault();
e.stopPropagation();
if (isVisible()) hide();
else show(src);
return;
}
if (isVisible() && e.target === overlay) {
hide();
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') hide();
});