@ihabdevteam/core 0.132.0 → 0.134.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/dist/components.cjs.js +177 -177
  3. package/dist/components.esm.css +1 -1
  4. package/dist/hooks.cjs.js +1 -1
  5. package/dist/i18n.cjs.js +2 -2
  6. package/dist/ihabdevteam-core.cjs.js +182 -182
  7. package/dist/ihabdevteam-core.d.ts +8 -13
  8. package/dist/packages/core/src/components/BarChart.js +2 -2
  9. package/dist/packages/core/src/components/BottomNav.js +3 -3
  10. package/dist/packages/core/src/components/Breadcrumb.js +5 -1
  11. package/dist/packages/core/src/components/BulkBar.js +1 -1
  12. package/dist/packages/core/src/components/ChoiceChips.js +1 -1
  13. package/dist/packages/core/src/components/CodeBox.js +1 -1
  14. package/dist/packages/core/src/components/DatePicker.js +16 -3
  15. package/dist/packages/core/src/components/Dialog.js +32 -9
  16. package/dist/packages/core/src/components/Dropdown.js +13 -3
  17. package/dist/packages/core/src/components/FileUpload.js +8 -7
  18. package/dist/packages/core/src/components/FilterPanel.js +8 -5
  19. package/dist/packages/core/src/components/FilterSectionInfo.js +1 -1
  20. package/dist/packages/core/src/components/Header.css +2 -0
  21. package/dist/packages/core/src/components/Header.js +4 -1
  22. package/dist/packages/core/src/components/HearingDeviceInfo.js +1 -1
  23. package/dist/packages/core/src/components/LandingHeader.js +18 -1
  24. package/dist/packages/core/src/components/PageTitle.js +1 -1
  25. package/dist/packages/core/src/components/Pagination.js +6 -3
  26. package/dist/packages/core/src/components/Panel.d.ts +1 -1
  27. package/dist/packages/core/src/components/Panel.js +4 -1
  28. package/dist/packages/core/src/components/PanelRow.js +3 -3
  29. package/dist/packages/core/src/components/PassCard/passCardProduct.js +6 -0
  30. package/dist/packages/core/src/components/PaymentPlan.d.ts +6 -0
  31. package/dist/packages/core/src/components/PaymentPlan.js +6 -4
  32. package/dist/packages/core/src/components/Popup/DeviceSideTable.js +2 -2
  33. package/dist/packages/core/src/components/Popup/LoadTablePopup.js +2 -2
  34. package/dist/packages/core/src/components/Popup/Popup.js +15 -3
  35. package/dist/packages/core/src/components/Popup/SaveTablePopup.js +1 -1
  36. package/dist/packages/core/src/components/Popup/TrainingResultPopup.js +1 -1
  37. package/dist/packages/core/src/components/Popup/WordDataUpdatePopup.js +3 -3
  38. package/dist/packages/core/src/components/PromoBanner.js +1 -1
  39. package/dist/packages/core/src/components/SegmentedControl.js +1 -1
  40. package/dist/packages/core/src/components/SideNav.js +2 -2
  41. package/dist/packages/core/src/components/SoundCompass.js +10 -1
  42. package/dist/packages/core/src/components/Table.js +2 -2
  43. package/dist/packages/core/src/components/Tabs.js +7 -2
  44. package/dist/packages/core/src/components/Tooltip/MenuTooltip.js +8 -3
  45. package/dist/packages/core/src/components/Tooltip/TextBoxTooltip.js +1 -1
  46. package/dist/packages/core/src/components/Tooltip/Tooltip.js +13 -5
  47. package/dist/packages/core/src/components/Training/NoiseSettingsTooltip.js +1 -1
  48. package/dist/packages/core/src/components/Training/TrainingBlock.js +1 -1
  49. package/dist/packages/core/src/components/Training/TrainingBlockButton.js +1 -1
  50. package/dist/packages/core/src/components/Training/TrainingCardGroup.js +1 -1
  51. package/dist/packages/core/src/components/Training/TrainingPagePopup.js +51 -23
  52. package/dist/packages/core/src/components/Training/TrainingPagePopupBottom.js +1 -1
  53. package/dist/packages/core/src/components/Training/TrainingPagePopupTitle.js +1 -1
  54. package/dist/packages/core/src/components/Training/TrainingStepAudioPlayer.js +26 -5
  55. package/dist/packages/core/src/components/Training/TrainingStepConfirm.js +1 -1
  56. package/dist/packages/core/src/components/Training/TrainingStepConfirmWithText.js +2 -2
  57. package/dist/packages/core/src/components/Training/TrainingStepOrderList.js +1 -1
  58. package/dist/packages/core/src/components/Training/TrainingStepTextBox.js +1 -1
  59. package/dist/packages/core/src/components/Training/TrainingStepTitle.js +1 -1
  60. package/dist/packages/core/src/components/Training/TrainingWordCard.js +11 -6
  61. package/dist/packages/core/src/components/Training/useAudioPreview.js +7 -3
  62. package/dist/packages/core/src/components/Training/useNoiseFade.js +22 -1
  63. package/dist/packages/core/src/components/Training/useTTSPlayback.js +9 -0
  64. package/dist/packages/core/src/components/UpdateAlert.js +1 -1
  65. package/dist/packages/core/src/components/Word/PhonemeSelectBlock.js +2 -2
  66. package/dist/packages/core/src/components/Word/WordSearchResultBlock.js +6 -5
  67. package/dist/packages/core/src/components/Word/WordTableBlock.js +2 -2
  68. package/dist/packages/core/src/components/Word/WordTableButton.js +1 -1
  69. package/dist/packages/core/src/components/WordTable.js +6 -6
  70. package/dist/packages/core/src/components/useToastLifecycle.js +8 -1
  71. package/dist/packages/core/src/hooks/useAnchoredMenu.js +10 -9
  72. package/dist/packages/core/src/hooks/useDocumentTitle.d.ts +0 -11
  73. package/dist/packages/core/src/hooks/useDocumentTitle.js +16 -3
  74. package/dist/packages/core/src/hooks/useFocusTrap.js +6 -2
  75. package/dist/packages/core/src/hooks/useWordTrainingFilter.js +9 -4
  76. package/dist/packages/core/src/hooks/wordTrainingFilterModel.d.ts +1 -1
  77. package/dist/packages/core/src/hooks/wordTrainingFilterModel.js +7 -2
  78. package/dist/packages/core/src/i18n/locales/en.json +11 -0
  79. package/dist/packages/core/src/i18n/locales/ko.json +11 -0
  80. package/dist/packages/core/src/utils/audioPeaks.js +13 -5
  81. package/dist/packages/core/src/utils/csv.js +3 -1
  82. package/dist/packages/core/src/utils/format.js +17 -1
  83. package/dist/packages/core/src/utils/koreanPronunciation.js +7 -0
  84. package/dist/packages/core/src/utils/koreanSyllable.js +2 -1
  85. package/dist/packages/core/src/utils/pressable.js +4 -0
  86. package/dist/packages/core/src/utils/savedWordTables.js +2 -1
  87. package/dist/packages/core/src/utils/textSort.d.ts +0 -10
  88. package/dist/packages/core/src/utils/textSort.js +7 -2
  89. package/dist/packages/core/src/utils/wordTrainingPool.d.ts +7 -0
  90. package/dist/packages/core/src/utils/wordTrainingPool.js +30 -0
  91. package/dist/packages/core/src/utils/wordTrainingRuntime.js +55 -17
  92. package/dist/packages/core/src/version.d.ts +1 -1
  93. package/dist/packages/core/src/version.js +1 -1
  94. package/dist/utils.cjs.js +2 -2
  95. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,135 @@ All notable changes to this project will be documented in this file.
7
7
  > 적은 글이라, 지금 이름으로 고쳐 놓으면 그 시절에 그 이름으로 받은 사람이
8
8
  > 제 이야기를 못 찾는다.
9
9
 
10
+ ## 0.134.0
11
+
12
+ 0.133.0 뒤 2차 검수 판이다 — 소리방향성(SoundCompass)·단어 기능·레이아웃/결제를 새로 훑었다. 항목마다 시험을 붙이고 고친 줄을
13
+ 되돌리면 붉어지는 것을 확인했다. 걷은 것은 없다. **새 선택 prop 하나**(`PaymentPlanTier.onceOnly` — 안 주면 전과 같음)과 사전 열쇠
14
+ `soundCompass.state.*`·`breadcrumb.ariaLabel` 을 더했다.
15
+
16
+ ### 소비자에게 먼저
17
+
18
+ - **말귀 `admin/src/libs/phone.test.ts` "고치는 대상이 실재한다" 가 붉어진다 — 의도다.** 코어 `formatPhone` 이 050X·0303 을 네 자리
19
+ 앞자리로 끊는다. 시험에 적힌 대로 `formatPhoneKr` 을 걷어도 된다.
20
+ - **영어 결제 화면을 고치려면 말귀 `paymentProducts` 의 오픈 특가 tier 에 `onceOnly: true`** 를 넣는다(아래 PaymentPlan). 안 넣으면
21
+ 한국어 화면은 전과 같고 영어 화면만 그대로 남는다.
22
+ - SoundCompass 스피커 단추 이름이 상태를 붙인다("13, 정답"). 이름으로 찾는 시험은 고친다(지금 소비자 시험엔 없음).
23
+ - 모바일 Header 햄버거 단추 이름이 읽지 않은 알림이 있을 때 "메뉴 열기, N개".
24
+
25
+ ### 바뀜 — 훈련
26
+
27
+ - **실단어 생성기가 필터를 따른다**: MERGE_2/3_PHONEMES·DROP_FINAL_CONSONANT_FROM_1SYLL·REMOVE_CONSONANT_AND_IDENTIFY_PHONEME 가
28
+ 난이도 등급·단어 구성(초성/중성/종성·음절 수)을 무시해 초성 ㄱ·1등급으로 설정해도 '카·라·파…' 가 나왔다. CHANGE_1_SYLL_IN_2/3SYLL 은
29
+ 등급이 빠졌다. `buildUsablePool` 과 같은 정답 거르개를 건다 — 조건에 맞는 단어가 없으면 빈 결과(카드 비활성)가 된다.
30
+ - **SAME_OR_DIFF**: 같음·다름이 늘 교대(같음·다름·같음…)라 듣지 않고도 맞힐 수 있었고 같은 단어가 반복됐다 — 절반씩 섞고 겹치지 않게.
31
+ - **단어 훈련 필터**: 글자↔발음 보기를 오가면 종성 선택이 대표음으로 바뀌어(ㅅ → ㄷ, ㄳ → ㄱ) 훈련 대상이 달라진 채 저장되던 것.
32
+ `resetKey` 초기화가 `defaultImageOnly` 를 무시하던 것.
33
+ - **useTTSPlayback**: Chrome·Safari 는 cancel() 한 발화에도 end 를 내 **정지가 문항 완료로** 세졌고, 떠난 뒤 온 end 가 완료를 알렸다.
34
+ - **useNoiseFade**: 소음 종류를 바꾸는 150ms 안에 다른 페이드가 끼면 표시·파형은 새 종류인데 **소리는 이전 파일**이던 것.
35
+ - **발음 추천**: 받침 ㅎ(ㄶ·ㅀ) 뒤 ㅅ(표준발음법 제12항 2) — 놓소 → 노쏘, 많소 → 만쏘(전에는 녿쏘·만소).
36
+
37
+ ### 바뀜 — 소리방향성
38
+
39
+ - **SoundCompass**: 스피커 상태(소리 나는 중·들음·정답·오답)가 색과 이름 없는 아이콘으로만 보여 낭독기는 번호만 읽었다 —
40
+ 이름에 붙이고(`soundCompass.state.*`), 고른 칸은 `aria-pressed`.
41
+
42
+ ### 바뀜 — 오버레이·레이아웃
43
+
44
+ - **Dialog**: 스크롤 잠금을 제 손으로 되돌려 Popup 과 엇갈리면 스크롤이 일찍 풀리거나 **영영 굳던** 것(공유 카운터로), 인라인 `onClose`
45
+ 로 다시 그려질 때마다 ESC 스택 맨 위로 끼어들던 것, `closeOnEscape={false}` 인데 Esc 가 아래 팝업을 닫던 것(이제 삼킨다), 판 안에서
46
+ 누르고 바탕에서 떼면 닫히던 것. (지금 소비자 넷 모두 Dialog 를 쓰지 않는다.)
47
+ - **Header 모바일 햄버거**: 알림이 메뉴 안에만 있어 열어 봐야 새 알림을 알았다 — SideNav 알림과 같은 원형 배지, 이름에 수.
48
+ - **MenuTooltip**: 항목 배지 수가 단추 이름에서 빠져 "알림" 으로만 읽혔다(BottomNav 더보기·Header 유틸 메뉴).
49
+ - **pressable**(LandingBottomSticky·Calendar 방문 표시·LoadTablePopup): 안에 든 단추에서 누른 Enter 를 바깥 자리가 가로채 그 단추의
50
+ click 을 막던 것.
51
+ - **LandingHeader**: 서랍이 Esc 로 닫히지 않던 것, 넓은 화면을 거쳐 돌아오면 서랍이 다시 펼쳐지던 것.
52
+ - **Pagination**: 범위 밖 쪽(page > totalPages)에서 '이전' 이 범위 안으로 돌아오지 않던 것. **Panel** `empty`: 자식이 `false` 면 안 뜨던 것.
53
+ - **WordSearchResultBlock**: 결과 수가 같은 다른 검색이면 보던 쪽 번호가 남던 것 — 검색어가 바뀌면 1쪽.
54
+ - PromoBanner·TrainingStepTextBox 단추에 `htmlType="button"`. Breadcrumb `aria-label` 이 영어 'breadcrumb' 으로 박혀 있던 것(`breadcrumb.ariaLabel`).
55
+
56
+ ### 바뀜 — 결제·표시
57
+
58
+ - **PaymentPlan `tier.onceOnly`(새 선택 prop)**: 계정당 1회 tier 를 라벨의 '오픈 특가' 로만 판정해, 영어 화면에서 이미 산 특가 카드가 남고
59
+ **정가 30일권을 살 길이 없었다.** 주면 그것으로 판정한다(안 주면 예전처럼 라벨). 무료 판정도 '무료'·'0원' 글자만 봐 '₩0' 을 놓쳤다 —
60
+ 숫자가 모두 0 인 가격은 무료.
61
+ - **derivePassCard**: 영어 상품 이름('Open Special 30-Day Plan')에서 기간을 못 뽑아 영어 랜딩 요금 카드에 이름 전체가 큰 글씨로 찍혔다.
62
+ - **formatPhone**: 050X 안심번호·0303 은 앞자리 네 자리(`0507-1234-5678` 이 마지막 자리를 잃은 채 검증을 통과했다), 대표번호 여덟 자리는
63
+ 4-4(`1588-1234`).
64
+ - **duplicateTable**: 사본이 설명·검색 구성·묶음을 잃던 것.
65
+
66
+ ### 고치지 않은 것 — 결정이 필요하다
67
+
68
+ - **SoundCompass 화면 번호**가 스피커 id 가 아니라 배열 순번(idx+1)이다. 소리방향성은 `label=String(id)` 를 넘겨 낭독기 이름(13)과 화면
69
+ 숫자(7)가 어긋나고, 같은 앱의 격자 배치(id 표시)와도 다르다. 검사 화면에 보이는 숫자를 바꾸는 일이라 두었다.
70
+ - **useWordTrainingFilter `wordCount`** 가 품사·어종 필터를 반영하지 않는다 — 생성 런타임이 품사·어종을 모르는 구조라 따로 설계가 필요하다.
71
+ - **결과 캐시**가 같은 조건이면 세션 내내 같은 문제 세트를 돌려준다 — 성능을 위한 것인지 의도 확인이 필요하다.
72
+ - **useEditableList**: 편집 중에 온 서버 목록을 버린다 — 방금 저장한 편집과 어느 쪽이 이겨야 하는지 정해야 한다.
73
+
74
+ ## 0.133.0
75
+
76
+ 2026-09-14 저녁 검수 판이다 — 오버레이·입력·훅·유틸을 네 갈래로 훑어 **실제로 재현된** 결함만 고쳤다. 항목마다 시험을 붙이고,
77
+ 고친 줄을 되돌리면 그 시험이 붉어지는 것을 확인했다. 걷은 prop·타입·열쇠는 없다(새 prop 도 없다).
78
+
79
+ ### 바뀜 — Esc 는 맨 위 하나만 닫는다
80
+
81
+ - **앵커 메뉴**(`useAnchoredMenu` — DatePicker·BottomNav 더보기·Header 메뉴)와 **Tooltip**(onClose 있는 떠 있는 툴팁)의 Esc 가
82
+ Popup 과 **같은 공유 ESC 스택**에 오른다. 전에는 document 에서 따로 들어, 팝업 안 달력·툴팁에서 Esc 한 번에 **팝업까지** 닫혔다
83
+ (말귀 어드민 쿠폰 생성 팝업 — 입력이 날아갔다). 달력 안 연월 Dropdown 의 Esc 도 달력까지 닫던 것이 멎는다.
84
+ - **TrainingPagePopup**: Esc 를 판 keydown 에서만 들어 문제 글·그림을 눌러 포커스가 body 로 가면 Esc 가 먹지 않았다 — 공유 스택으로.
85
+ 훈련 창이 다른 팝업 위에 있을 때 가려진 팝업이 닫히던 것도 멎는다.
86
+
87
+ ### 바뀜 — 포커스
88
+
89
+ - **Popup**: 닫으면서 다음 창을 열면(미리보기 → 삭제 확인) 닫힘 애니메이션 뒤 **뒤 화면의 여는 단추로 포커스를 빼앗던** 것.
90
+ 포커스가 그 창 안이거나 body 일 때만 되돌린다.
91
+ - **Popup Tab 가둠**: 판 자체(본문 글자를 누르면 판이 받는다)에 포커스가 있을 때 Shift+Tab 이 뒤 화면으로 나가던 것, 닫히지 않는
92
+ 바탕(`closeOnBackdrop={false}` 등)을 누르면 포커스가 body 로 떨어져 가둠이 풀리던 것.
93
+ - **TrainingPagePopup**: 첫 칸 포커스가 `onBack` 이 바뀔 때마다 다시 돌아 **훈련 중 포커스를 첫 칸으로 끌어오던** 것 — 마운트 때 한 번만.
94
+ 닫히면 연 곳으로 포커스를 되돌린다.
95
+ - **Dropdown**: Tab 으로 트리거를 떠나면 메뉴를 닫는다(열린 채 남아 화살표·Enter 가 안 가던 죽은 메뉴). 열린 동안 부모가 `options` 를
96
+ 새 배열로 넘겨도 화살표로 옮긴 가리킴이 선택값 자리로 튀지 않는다.
97
+ - **DatePicker**: 오늘·활성일이 min/max 밖이라 꺼져 있으면 격자에 Tab 자리가 없어 키보드로 들어갈 수 없던 것 — 켜진 날이 받는다.
98
+ - **Tabs**: 첫 탭이 꺼져 있거나 `value` 가 items 에 없으면 켜진 첫 탭을 고르고 Tab 자리를 준다.
99
+
100
+ ### 바뀜 — 폼 안에서 제출되던 단추(113곳)
101
+
102
+ 코어가 제 안에서 그리는 `Button` 113곳에 `htmlType="button"`. Button 은 htmlType 이 없으면 type 을 붙이지 않아(앱 로그인 폼이 그
103
+ 기본값으로 제출하므로 **기본값은 그대로**) 앱이 Pagination·SegmentedControl·FilterPanel·ChoiceChips 등을 `<form>` 안에 두면 누를 때마다
104
+ 폼이 제출됐다. `test/noSubmitButtonsInCore` 가 소스를 훑어 지킨다.
105
+
106
+ ### 바뀜 — 입력
107
+
108
+ - **FilterPanel** `display:'segmented'`(allOption 없음): 고른 것이 없는데 첫 보기가 골라진 것처럼 보이던 것.
109
+ - **FileUpload** 비제어 모드: `onRemove` 를 주면 뺀 파일이 목록에 남던 것 — 알림은 onRemove 한 번(전과 같음), 보이는 목록은 줄인다.
110
+
111
+ ### 바뀜 — 훈련·소리
112
+
113
+ - **소음 설정**: 저장된 설정을 **불러오기 전에** 바꾸면 `enabled:false` 초기값 위에 합쳐 곧바로 저장돼 **다음 판부터 소음이 꺼졌고**,
114
+ 늦게 온 불러오기가 그 변경을 덮었다. 불러오기 전 변경은 모아 두었다가 불러온 값 위에 얹어 한 번 저장한다.
115
+ - **TrainingStepAudioPlayer**: 불러오는 중 다음 문항으로 넘기거나 팝업을 닫아도 흐름이 돌아 **떼어진 `<audio>` 에서 이전 문장이 끝까지
116
+ 울리던** 것. 쓸 소스를 하나도 못 얻으면 'load' 에 갇혀 듣기 단추가 사라지던 것 — 알리고 누를 수 있는 상태로.
117
+ - **TrainingWordCard**: 카드가 번호 key 로 재사용될 때 새 낱말의 URL 을 받기 전·못 받았을 때 **이전 낱말 소리**가 나던 것.
118
+ - **한 음소 바꾸기**(`CHANGE_1_PHONEME_IN_1SYLL`·`2SYLL`): 오답끼리·정답과 소리가 같은 보기(낮·낯)를 거르고, 철자가 두 자리 이상 다른
119
+ 발음 대립쌍(같이↔가지)은 바꾼 단어로 쓰지 않는다('같이에서 같을 가로' 가 되어 문제 글과 정답이 어긋났다).
120
+ - **useAudioPreview**: 코드 없는 훈련으로 바뀌어도 이전 훈련 주소로 미리듣기가 나던 것.
121
+ - **computePeaksFromUrl**: 디코딩 실패·채널 없음에서 AudioContext 를 닫지 않던 것(파형 실패마다 하나씩 남음), `ok:false` 응답도 디코딩하던 것.
122
+
123
+ ### 바뀜 — 훅·유틸
124
+
125
+ - **useDocumentTitle**: 화면이 겹쳐 떠 있다가 먼저 붙은 쪽이 나중에 떠나면 뒤 화면의 제목을 지우던 것 — 건 제목을 쌓아 남은 맨 위로
126
+ 돌린다(말귀 CustomersPage 의 우회는 그대로 두어도 된다).
127
+ - **Toast**(useToastLifecycle): 보이는 중 문구를 바꾼 뒤 떠나면 타이머가 살아 **떠난 뒤 `onClose`** 가 불리던 것.
128
+ - **escapeCsvField**: 숫자 값(음수·환불 금액)에 탭을 붙여 엑셀이 글자 칸으로 읽던 것. 글자 `'-2+3'` 은 그대로 막는다.
129
+ - **칸순**(ListPopup 정렬): 글자로 온 숫자('10'·'9')를 글자로 견주던 것, NaN 이 비교를 흐트러뜨리던 것.
130
+ - **matchesWordQuery**: 영문을 대소문자 구분해 'apple' 로 'Apple' 을 못 찾던 것.
131
+
132
+ ### 소비자에게
133
+
134
+ - **Dropdown 을 시험에서 열고 다른 요소로 포커스를 옮기면 메뉴가 닫힌다.** 항목은 click 으로 고르면 그대로 된다.
135
+ - 훈련 러너에서 Esc 는 **포커스가 어디 있든** 훈련 창을 닫는다(맨 위 팝업일 때). 판에 keyDown 을 쏘던 시험은 그대로 통과한다.
136
+ - 고치지 않은 것: 조사 `pickIga` 등이 숫자 끝('Step 1')에서 기본값 '가' 를 쓰는 것 — `사과(1)` 같은 동음이의 번호를 위해 숫자를 건너뛰도록
137
+ 시험(josaFormat)이 정해 두었다.
138
+
10
139
  ## 0.132.0
11
140
 
12
141
  말귀가 "스타일 오버라이드 없도록 모두 정리" 하다 코어에 길이 없어 못 걷은 덮음 여섯을 prop 으로 연 판이다.