@ihabdevteam/core 0.15.0 → 0.15.1
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 +165 -165
- package/dist/components.esm.css +1 -1
- package/dist/ihabdevteam-core.cjs.js +12 -12
- package/dist/ihabdevteam-core.d.ts +7 -1
- package/dist/packages/core/src/components/ShortcutBadge.css +10 -4
- package/dist/packages/core/src/components/SoundCompass.css +2 -3
- package/dist/packages/core/src/components/SoundCompass.d.ts +8 -1
- package/dist/packages/core/src/components/SoundCompass.js +14 -8
- package/package.json +1 -1
|
@@ -5108,7 +5108,7 @@ export declare interface SliderProps {
|
|
|
5108
5108
|
export declare function sortToValue(key: string, asc: boolean): string | undefined;
|
|
5109
5109
|
|
|
5110
5110
|
/** @public */
|
|
5111
|
-
export declare function SoundCompass({ speakers, size, viewT, activeSpeakerId, playedIds, selectedId, answerId, showFeedback, clickable, onSelectSpeaker, buttonSize, showIcon, }: SoundCompassProps): JSX.Element;
|
|
5111
|
+
export declare function SoundCompass({ speakers, size, viewT, activeSpeakerId, playedIds, selectedId, answerId, showFeedback, clickable, onSelectSpeaker, buttonSize, showIcon, shortcutAnchor, }: SoundCompassProps): JSX.Element;
|
|
5112
5112
|
|
|
5113
5113
|
export declare interface SoundCompassExam {
|
|
5114
5114
|
/** `<SoundCompass {...bind} />` 로 펼쳐 넣는 제어 props */
|
|
@@ -5183,6 +5183,12 @@ export declare interface SoundCompassProps {
|
|
|
5183
5183
|
buttonSize?: number;
|
|
5184
5184
|
/** 스피커 버튼에 아이콘을 표시할지 여부. false면 숫자만 가운데 표시. 기본 true */
|
|
5185
5185
|
showIcon?: boolean;
|
|
5186
|
+
/**
|
|
5187
|
+
* `speakers[].shortcut` 배지가 버튼의 어느 모서리에 붙을지. 기본 우상단.
|
|
5188
|
+
*
|
|
5189
|
+
* 배지 전부에 같이 걸린다 — 스피커마다 다른 자리에 두면 눈이 규칙을 못 잡는다.
|
|
5190
|
+
*/
|
|
5191
|
+
shortcutAnchor?: ShortcutBadgeAnchor;
|
|
5186
5192
|
}
|
|
5187
5193
|
|
|
5188
5194
|
/**
|
|
@@ -9,29 +9,35 @@
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/* 코너 배치 — 중심이 부모 코너에서 살짝 안쪽(25%)으로 들어오게 얹힌다. */
|
|
12
|
+
/* 배지를 키우려면 `--shortcut-badge-scale` 을 부모에 얹는다.
|
|
13
|
+
**transform 을 따로 걸면 안 된다** — 자리를 잡는 translate 와 같은 속성이라
|
|
14
|
+
뒤에 오는 쪽이 앞의 것을 통째로 지운다. 실제로 그 사고가 났다: SoundCompass 가
|
|
15
|
+
배지에 scale 을 따로 걸었더니 anchor 의 translate 가 사라져 배지가 모서리에
|
|
16
|
+
걸치지 않고 버튼 안으로 들어왔다(실측: 걸침 +6px → -3px). 그래서 배율을
|
|
17
|
+
변수로 받아 **여기 한 곳에서** 합쳐 적는다. */
|
|
12
18
|
.shortcut-badge--top-left {
|
|
13
19
|
position: absolute;
|
|
14
20
|
left: 0;
|
|
15
21
|
top: 0;
|
|
16
|
-
transform: translate(-25%, -25%);
|
|
22
|
+
transform: translate(-25%, -25%) scale(var(--shortcut-badge-scale, 1));
|
|
17
23
|
}
|
|
18
24
|
.shortcut-badge--top-right {
|
|
19
25
|
position: absolute;
|
|
20
26
|
right: 0;
|
|
21
27
|
top: 0;
|
|
22
|
-
transform: translate(25%, -25%);
|
|
28
|
+
transform: translate(25%, -25%) scale(var(--shortcut-badge-scale, 1));
|
|
23
29
|
}
|
|
24
30
|
.shortcut-badge--bottom-left {
|
|
25
31
|
position: absolute;
|
|
26
32
|
left: 0;
|
|
27
33
|
bottom: 0;
|
|
28
|
-
transform: translate(-25%, 25%);
|
|
34
|
+
transform: translate(-25%, 25%) scale(var(--shortcut-badge-scale, 1));
|
|
29
35
|
}
|
|
30
36
|
.shortcut-badge--bottom-right {
|
|
31
37
|
position: absolute;
|
|
32
38
|
right: 0;
|
|
33
39
|
bottom: 0;
|
|
34
|
-
transform: translate(25%, 25%);
|
|
40
|
+
transform: translate(25%, 25%) scale(var(--shortcut-badge-scale, 1));
|
|
35
41
|
}
|
|
36
42
|
/* static — 흐름 안에 배치(별도 규칙 없음, position: static 기본). */
|
|
37
43
|
|
|
@@ -162,9 +162,8 @@
|
|
|
162
162
|
.sound-compass__speaker-shortcut {
|
|
163
163
|
pointer-events: none;
|
|
164
164
|
z-index: 2;
|
|
165
|
-
/*
|
|
166
|
-
|
|
167
|
-
transform-origin: center;
|
|
165
|
+
/* 배율은 `--shortcut-badge-scale` 로 넘긴다. 여기서 transform 을 걸면 배지가
|
|
166
|
+
자리를 잡는 translate 를 지운다 — 같은 속성이라 뒤에 오는 쪽이 이긴다. */
|
|
168
167
|
}
|
|
169
168
|
|
|
170
169
|
.sound-compass__speaker-pos {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ShortcutBadgeAnchor } from './ShortcutBadge';
|
|
1
2
|
import type { SpeakerPos } from '../types/audio';
|
|
2
3
|
import './SoundCompass.css';
|
|
3
4
|
/** @public */
|
|
@@ -37,6 +38,12 @@ export interface SoundCompassProps {
|
|
|
37
38
|
buttonSize?: number;
|
|
38
39
|
/** 스피커 버튼에 아이콘을 표시할지 여부. false면 숫자만 가운데 표시. 기본 true */
|
|
39
40
|
showIcon?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* `speakers[].shortcut` 배지가 버튼의 어느 모서리에 붙을지. 기본 우상단.
|
|
43
|
+
*
|
|
44
|
+
* 배지 전부에 같이 걸린다 — 스피커마다 다른 자리에 두면 눈이 규칙을 못 잡는다.
|
|
45
|
+
*/
|
|
46
|
+
shortcutAnchor?: ShortcutBadgeAnchor;
|
|
40
47
|
}
|
|
41
48
|
/** @public */
|
|
42
|
-
export default function SoundCompass({ speakers, size, viewT, activeSpeakerId, playedIds, selectedId, answerId, showFeedback, clickable, onSelectSpeaker, buttonSize, showIcon, }: SoundCompassProps): import("react").JSX.Element;
|
|
49
|
+
export default function SoundCompass({ speakers, size, viewT, activeSpeakerId, playedIds, selectedId, answerId, showFeedback, clickable, onSelectSpeaker, buttonSize, showIcon, shortcutAnchor, }: SoundCompassProps): import("react").JSX.Element;
|
|
@@ -14,7 +14,7 @@ import ShortcutBadge from './ShortcutBadge';
|
|
|
14
14
|
import './SoundCompass.css';
|
|
15
15
|
const lerp = (a, b, t) => a + (b - a) * t;
|
|
16
16
|
/** @public */
|
|
17
|
-
export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSpeakerId = null, playedIds, selectedId = null, answerId = null, showFeedback = false, clickable = false, onSelectSpeaker, buttonSize = 40, showIcon = true, }) {
|
|
17
|
+
export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSpeakerId = null, playedIds, selectedId = null, answerId = null, showFeedback = false, clickable = false, onSelectSpeaker, buttonSize = 40, showIcon = true, shortcutAnchor = 'top-right', }) {
|
|
18
18
|
const t = Math.max(0, Math.min(1, viewT));
|
|
19
19
|
const CENTER = size / 2;
|
|
20
20
|
// ── 탑뷰 좌표 ──────────────────────────────────────────────────────────
|
|
@@ -152,12 +152,18 @@ export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSp
|
|
|
152
152
|
const state = getSpeakerState(sp);
|
|
153
153
|
const pulse = shouldPulse(sp);
|
|
154
154
|
const baseStyle = {
|
|
155
|
-
// 배지는 24px 고정인데 버튼은
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
// 0.
|
|
159
|
-
//
|
|
160
|
-
|
|
155
|
+
// 배지는 24px 고정인데 버튼은 크게 오간다. 그대로 두면 버튼 대비 비율이
|
|
156
|
+
// 세 배씩 흔들려, 작은 버튼에서는 배지가 버튼을 덮고 큰 버튼에서는
|
|
157
|
+
// 잃어버린다(실측). 버튼과 함께 키운다 — 24/56 이라 묶이지 않는 구간에서는
|
|
158
|
+
// 비율이 0.43 으로 **일정하다**.
|
|
159
|
+
//
|
|
160
|
+
// 상한은 3 이다. 처음엔 1.6 이었는데 buttonSize 89.6px 부터 붙어버려,
|
|
161
|
+
// 104~168px 을 쓰는 소비 앱에서 배지가 0.37 → 0.23 으로 다시 작아졌다.
|
|
162
|
+
// 3 이면 168px 까지 묶이지 않는다. 하한 0.75 는 배지가 읽히는 크기다.
|
|
163
|
+
//
|
|
164
|
+
// 배율은 transform 이 아니라 변수로 넘긴다 — 배지의 anchor 가 같은 속성에
|
|
165
|
+
// translate 를 걸고 있어, 여기서 transform 을 걸면 그것을 지운다.
|
|
166
|
+
['--shortcut-badge-scale']: String(Math.max(0.75, Math.min(3, buttonSize / 56))),
|
|
161
167
|
pointerEvents: (clickable ? 'auto' : 'none'),
|
|
162
168
|
cursor: clickable ? 'pointer' : 'default',
|
|
163
169
|
// 호출된(=idle이 아닌) 스피커를 다른 스피커 위로 끌어올렸다가, 초기화되면 다시 낮춘다
|
|
@@ -169,6 +175,6 @@ export default function SoundCompass({ speakers, size = 300, viewT = 0, activeSp
|
|
|
169
175
|
const iconSize = Math.round(Math.max(10, Math.min(56, BTN * 0.38)));
|
|
170
176
|
const numberSize = Math.round(Math.max(7, Math.min(18, BTN * 0.2)));
|
|
171
177
|
const numberOnlySize = Math.round(Math.max(10, Math.min(56, BTN * 0.4)));
|
|
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:
|
|
178
|
+
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: shortcutAnchor, className: "sound-compass__speaker-shortcut" }))] }, sp.id));
|
|
173
179
|
})] }) }));
|
|
174
180
|
}
|