@ihabdevteam/core 0.14.0 → 0.15.0
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.
- package/dist/components.cjs.js +173 -173
- package/dist/components.esm.css +1 -1
- package/dist/ihabdevteam-core.cjs.js +33 -33
- package/dist/ihabdevteam-core.d.ts +10 -0
- package/dist/packages/core/src/components/SoundCompass.css +11 -0
- package/dist/packages/core/src/components/SoundCompass.js +8 -1
- package/dist/packages/core/src/types/audio.d.ts +10 -0
- package/package.json +1 -1
|
@@ -5213,6 +5213,16 @@ export declare interface SpeakerPos {
|
|
|
5213
5213
|
deg: number;
|
|
5214
5214
|
/** 동심원 링 번호 (1=가장 안쪽, 기본값 1) */
|
|
5215
5215
|
row?: number;
|
|
5216
|
+
/**
|
|
5217
|
+
* 이 스피커에 걸린 자판 키. 주면 버튼 모서리에 `ShortcutBadge` 가 얹힌다.
|
|
5218
|
+
*
|
|
5219
|
+
* 키가 모자란 스피커에는 주지 않으면 된다 — 배지도 안 붙는다(예: 27개 배치의
|
|
5220
|
+
* 가운데 층은 13개인데 자판 줄은 9칸이라 넷은 키가 없다).
|
|
5221
|
+
*
|
|
5222
|
+
* 무엇을 눌렀는지 판정하는 일은 부르는 쪽 몫이다. 한글 입력 상태에서는
|
|
5223
|
+
* `event.key` 가 "ㅈ" 이 되므로 `event.code`(늘 `KeyW`)로 보는 편이 안전하다.
|
|
5224
|
+
*/
|
|
5225
|
+
shortcut?: string;
|
|
5216
5226
|
}
|
|
5217
5227
|
|
|
5218
5228
|
/** @public */
|
|
@@ -156,6 +156,17 @@
|
|
|
156
156
|
outline-offset: 2px;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/* 자판 키 배지 — 눌러야 하는 것은 버튼이므로 클릭을 가로채지 않는다.
|
|
160
|
+
상태가 바뀐 스피커가 다른 스피커 위로 올라가도(z-index 10) 배지는 제 버튼
|
|
161
|
+
위에 남아야 하므로 버튼(z-index 1)보다 한 겹 위에 둔다. */
|
|
162
|
+
.sound-compass__speaker-shortcut {
|
|
163
|
+
pointer-events: none;
|
|
164
|
+
z-index: 2;
|
|
165
|
+
/* 모서리에 걸친 채로 자라도록 가운데를 기준으로 키운다. */
|
|
166
|
+
transform: scale(var(--sc-shortcut-scale, 1));
|
|
167
|
+
transform-origin: center;
|
|
168
|
+
}
|
|
169
|
+
|
|
159
170
|
.sound-compass__speaker-pos {
|
|
160
171
|
position: absolute;
|
|
161
172
|
}
|
|
@@ -10,6 +10,7 @@ import Check from 'lucide-react/dist/esm/icons/check.mjs';
|
|
|
10
10
|
import Volume2 from 'lucide-react/dist/esm/icons/volume-2.mjs';
|
|
11
11
|
import User from 'lucide-react/dist/esm/icons/user.mjs';
|
|
12
12
|
import X from 'lucide-react/dist/esm/icons/x.mjs';
|
|
13
|
+
import ShortcutBadge from './ShortcutBadge';
|
|
13
14
|
import './SoundCompass.css';
|
|
14
15
|
const lerp = (a, b, t) => a + (b - a) * t;
|
|
15
16
|
/** @public */
|
|
@@ -151,6 +152,12 @@ export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSp
|
|
|
151
152
|
const state = getSpeakerState(sp);
|
|
152
153
|
const pulse = shouldPulse(sp);
|
|
153
154
|
const baseStyle = {
|
|
155
|
+
// 배지는 24px 고정인데 버튼은 40~112px 을 오간다. 그대로 두면 버튼 대비
|
|
156
|
+
// 0.60배에서 0.21배까지 세 배가 흔들려, 작은 버튼에서는 배지가 버튼을 덮고
|
|
157
|
+
// 큰 버튼에서는 잃어버린다(실측). 버튼과 함께 자라게 하되 양끝을 묶어
|
|
158
|
+
// 0.34~0.45배 안에 머문다. ShortcutBadge 는 style 을 받지 않으므로
|
|
159
|
+
// 감싼 자리에 변수를 얹고 CSS 가 읽어 간다.
|
|
160
|
+
['--sc-shortcut-scale']: String(Math.max(0.75, Math.min(1.6, buttonSize / 56))),
|
|
154
161
|
pointerEvents: (clickable ? 'auto' : 'none'),
|
|
155
162
|
cursor: clickable ? 'pointer' : 'default',
|
|
156
163
|
// 호출된(=idle이 아닌) 스피커를 다른 스피커 위로 끌어올렸다가, 초기화되면 다시 낮춘다
|
|
@@ -162,6 +169,6 @@ export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSp
|
|
|
162
169
|
const iconSize = Math.round(Math.max(10, Math.min(56, BTN * 0.38)));
|
|
163
170
|
const numberSize = Math.round(Math.max(7, Math.min(18, BTN * 0.2)));
|
|
164
171
|
const numberOnlySize = Math.round(Math.max(10, Math.min(56, BTN * 0.4)));
|
|
165
|
-
return (_jsxs("div", { className: "sound-compass__speaker-pos", style: { ...baseStyle, left: x - BTN / 2, top: y - BTN / 2 }, children: [pulse && _jsx("div", { className: "sound-compass__pulse", style: { width: BTN, height: BTN } }), _jsxs("button", { type: "button", tabIndex: clickable ? 0 : -1, "aria-disabled": clickable ? undefined : true, onClick: clickable ? () => onSelectSpeaker?.(sp.id) : undefined, className: `sound-compass__speaker-btn sound-compass__speaker-btn--${state}`, style: { width: BTN, height: BTN }, "aria-label": sp.label, children: [showIcon && getStateIcon(state, iconSize), _jsx("span", { className: "sound-compass__speaker-number", style: { fontSize: showIcon ? numberSize : numberOnlySize }, children: idx + 1 })] })] }, sp.id));
|
|
172
|
+
return (_jsxs("div", { className: "sound-compass__speaker-pos", style: { ...baseStyle, left: x - BTN / 2, top: y - BTN / 2 }, children: [pulse && _jsx("div", { className: "sound-compass__pulse", style: { width: BTN, height: BTN } }), _jsxs("button", { type: "button", tabIndex: clickable ? 0 : -1, "aria-disabled": clickable ? undefined : true, onClick: clickable ? () => onSelectSpeaker?.(sp.id) : undefined, className: `sound-compass__speaker-btn sound-compass__speaker-btn--${state}`, style: { width: BTN, height: BTN }, "aria-label": sp.label, children: [showIcon && getStateIcon(state, iconSize), _jsx("span", { className: "sound-compass__speaker-number", style: { fontSize: showIcon ? numberSize : numberOnlySize }, children: idx + 1 })] }), sp.shortcut && (_jsx(ShortcutBadge, { keys: sp.shortcut, anchor: "top-right", className: "sound-compass__speaker-shortcut" }))] }, sp.id));
|
|
166
173
|
})] }) }));
|
|
167
174
|
}
|
|
@@ -8,4 +8,14 @@ export interface SpeakerPos {
|
|
|
8
8
|
deg: number;
|
|
9
9
|
/** 동심원 링 번호 (1=가장 안쪽, 기본값 1) */
|
|
10
10
|
row?: number;
|
|
11
|
+
/**
|
|
12
|
+
* 이 스피커에 걸린 자판 키. 주면 버튼 모서리에 `ShortcutBadge` 가 얹힌다.
|
|
13
|
+
*
|
|
14
|
+
* 키가 모자란 스피커에는 주지 않으면 된다 — 배지도 안 붙는다(예: 27개 배치의
|
|
15
|
+
* 가운데 층은 13개인데 자판 줄은 9칸이라 넷은 키가 없다).
|
|
16
|
+
*
|
|
17
|
+
* 무엇을 눌렀는지 판정하는 일은 부르는 쪽 몫이다. 한글 입력 상태에서는
|
|
18
|
+
* `event.key` 가 "ㅈ" 이 되므로 `event.code`(늘 `KeyW`)로 보는 편이 안전하다.
|
|
19
|
+
*/
|
|
20
|
+
shortcut?: string;
|
|
11
21
|
}
|