@hjmds/design-contracts 1.6.0 → 1.8.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/THIRD_PARTY_NOTICES.md +58 -0
- package/dist/agreement.d.ts +3 -3
- package/dist/agreement.js +1 -1
- package/dist/agreement.js.map +1 -1
- package/dist/asset.d.ts +1 -1
- package/dist/asset.js +1 -1
- package/dist/asset.js.map +1 -1
- package/dist/base-recipes.d.ts +12 -12
- package/dist/base-recipes.d.ts.map +1 -1
- package/dist/base-recipes.js +15 -14
- package/dist/base-recipes.js.map +1 -1
- package/dist/behaviors.d.ts +1 -1
- package/dist/catalog.d.ts +417 -561
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +138 -90
- package/dist/catalog.js.map +1 -1
- package/dist/command-palette.d.ts +3 -3
- package/dist/component-contracts.d.ts +4 -4
- package/dist/component-contracts.d.ts.map +1 -1
- package/dist/component-contracts.js +5 -4
- package/dist/component-contracts.js.map +1 -1
- package/dist/component-definitions.d.ts +1 -4
- package/dist/component-definitions.d.ts.map +1 -1
- package/dist/component-definitions.js +1 -4
- package/dist/component-definitions.js.map +1 -1
- package/dist/component-recipes.d.ts +76 -83
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +29 -49
- package/dist/component-recipes.js.map +1 -1
- package/dist/component-references.d.ts +0 -15
- package/dist/component-references.d.ts.map +1 -1
- package/dist/component-references.js +0 -3
- package/dist/component-references.js.map +1 -1
- package/dist/data-table.d.ts +3 -3
- package/dist/data-table.js +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/date-picker.d.ts +2 -2
- package/dist/icon-button-recipe.d.ts +2 -2
- package/dist/icon-button-recipe.js +1 -1
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/image.d.ts +2 -2
- package/dist/image.js +2 -2
- package/dist/image.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/thinking-orb/braid.d.ts +3 -0
- package/dist/internal/thinking-orb/braid.d.ts.map +1 -0
- package/dist/internal/thinking-orb/braid.js +47 -0
- package/dist/internal/thinking-orb/braid.js.map +1 -0
- package/dist/internal/thinking-orb/core.d.ts +60 -0
- package/dist/internal/thinking-orb/core.d.ts.map +1 -0
- package/dist/internal/thinking-orb/core.js +86 -0
- package/dist/internal/thinking-orb/core.js.map +1 -0
- package/dist/internal/thinking-orb/lattice.d.ts +5 -0
- package/dist/internal/thinking-orb/lattice.d.ts.map +1 -0
- package/dist/internal/thinking-orb/lattice.js +187 -0
- package/dist/internal/thinking-orb/lattice.js.map +1 -0
- package/dist/internal/thinking-orb/morph.d.ts +3 -0
- package/dist/internal/thinking-orb/morph.d.ts.map +1 -0
- package/dist/internal/thinking-orb/morph.js +127 -0
- package/dist/internal/thinking-orb/morph.js.map +1 -0
- package/dist/internal/thinking-orb/orbits.d.ts +3 -0
- package/dist/internal/thinking-orb/orbits.d.ts.map +1 -0
- package/dist/internal/thinking-orb/orbits.js +68 -0
- package/dist/internal/thinking-orb/orbits.js.map +1 -0
- package/dist/internal/thinking-orb/presets.d.ts +21 -0
- package/dist/internal/thinking-orb/presets.d.ts.map +1 -0
- package/dist/internal/thinking-orb/presets.js +77 -0
- package/dist/internal/thinking-orb/presets.js.map +1 -0
- package/dist/internal/thinking-orb/profiles.d.ts +8 -0
- package/dist/internal/thinking-orb/profiles.d.ts.map +1 -0
- package/dist/internal/thinking-orb/profiles.js +158 -0
- package/dist/internal/thinking-orb/profiles.js.map +1 -0
- package/dist/internal/thinking-orb/registry.d.ts +9 -0
- package/dist/internal/thinking-orb/registry.d.ts.map +1 -0
- package/dist/internal/thinking-orb/registry.js +27 -0
- package/dist/internal/thinking-orb/registry.js.map +1 -0
- package/dist/internal/thinking-orb/ribbon.d.ts +3 -0
- package/dist/internal/thinking-orb/ribbon.d.ts.map +1 -0
- package/dist/internal/thinking-orb/ribbon.js +87 -0
- package/dist/internal/thinking-orb/ribbon.js.map +1 -0
- package/dist/internal/thinking-orb/types.d.ts +15 -0
- package/dist/internal/thinking-orb/types.d.ts.map +1 -0
- package/dist/internal/thinking-orb/types.js +4 -0
- package/dist/internal/thinking-orb/types.js.map +1 -0
- package/dist/internal/thinking-orb/web.d.ts +3 -0
- package/dist/internal/thinking-orb/web.d.ts.map +1 -0
- package/dist/internal/thinking-orb/web.js +92 -0
- package/dist/internal/thinking-orb/web.js.map +1 -0
- package/dist/masonry.d.ts +17 -0
- package/dist/masonry.d.ts.map +1 -0
- package/dist/masonry.js +18 -0
- package/dist/masonry.js.map +1 -0
- package/dist/menubar.d.ts +3 -3
- package/dist/menubar.js +1 -1
- package/dist/menubar.js.map +1 -1
- package/dist/number-field.d.ts +2 -2
- package/dist/otp-field.d.ts +1 -1
- package/dist/password-field.d.ts +2 -2
- package/dist/popover.d.ts +7 -8
- package/dist/popover.d.ts.map +1 -1
- package/dist/popover.js +2 -0
- package/dist/popover.js.map +1 -1
- package/dist/qr-code-recipe.d.ts +7 -0
- package/dist/qr-code-recipe.d.ts.map +1 -0
- package/dist/qr-code-recipe.js +2 -0
- package/dist/qr-code-recipe.js.map +1 -0
- package/dist/qr-code.d.ts +16 -0
- package/dist/qr-code.d.ts.map +1 -0
- package/dist/qr-code.js +37 -0
- package/dist/qr-code.js.map +1 -0
- package/dist/semantic-colors.d.ts +1 -1
- package/dist/semantic-colors.js +1 -1
- package/dist/semantic-colors.js.map +1 -1
- package/dist/showcase.d.ts +5 -1
- package/dist/showcase.d.ts.map +1 -1
- package/dist/showcase.js +51 -13
- package/dist/showcase.js.map +1 -1
- package/dist/sidebar.d.ts +3 -3
- package/dist/sidebar.js +1 -1
- package/dist/sidebar.js.map +1 -1
- package/dist/tag.d.ts +4 -4
- package/dist/tag.js +3 -3
- package/dist/tag.js.map +1 -1
- package/dist/tags-input.d.ts +3 -3
- package/dist/tags-input.js +1 -1
- package/dist/tags-input.js.map +1 -1
- package/dist/text-formats.d.ts +2 -2
- package/dist/text-formats.js +2 -2
- package/dist/text-formats.js.map +1 -1
- package/dist/thinking-orb-recipe.d.ts +15 -0
- package/dist/thinking-orb-recipe.d.ts.map +1 -0
- package/dist/thinking-orb-recipe.js +9 -0
- package/dist/thinking-orb-recipe.js.map +1 -0
- package/dist/thinking-orb.d.ts +25 -0
- package/dist/thinking-orb.d.ts.map +1 -0
- package/dist/thinking-orb.js +40 -0
- package/dist/thinking-orb.js.map +1 -0
- package/dist/toast-liquid.d.ts +116 -0
- package/dist/toast-liquid.d.ts.map +1 -0
- package/dist/toast-liquid.js +100 -0
- package/dist/toast-liquid.js.map +1 -0
- package/dist/toast.d.ts +7 -1
- package/dist/toast.d.ts.map +1 -1
- package/dist/toast.js +5 -0
- package/dist/toast.js.map +1 -1
- package/dist/toggle-group.d.ts +2 -2
- package/dist/toggle-group.js +3 -3
- package/dist/toggle-group.js.map +1 -1
- package/dist/transfer-list.d.ts +3 -3
- package/dist/transfer-list.js +1 -1
- package/dist/transfer-list.js.map +1 -1
- package/dist/tree.d.ts +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/virtual-list.d.ts +13 -0
- package/dist/virtual-list.d.ts.map +1 -0
- package/dist/virtual-list.js +13 -0
- package/dist/virtual-list.js.map +1 -0
- package/docs/anchor.md +5 -4
- package/docs/ant-design-coverage.md +2 -2
- package/docs/architecture.md +6 -2
- package/docs/authoring-brief.md +3 -2
- package/docs/bottom-navigation.md +7 -6
- package/docs/breadcrumb.md +5 -2
- package/docs/calendar.md +6 -3
- package/docs/carousel.md +2 -2
- package/docs/cascader.md +6 -0
- package/docs/catalog-cleanup.md +7 -0
- package/docs/catalog-decision-status.md +3 -3
- package/docs/catalog-freeze.json +9 -7
- package/docs/collapsible.md +12 -0
- package/docs/command-palette.md +5 -3
- package/docs/consumer-policy.md +29 -12
- package/docs/context-menu.md +12 -2
- package/docs/data-table.md +11 -6
- package/docs/date-picker.md +6 -4
- package/docs/date-range.md +4 -2
- package/docs/description-list.md +8 -9
- package/docs/dialog.md +39 -0
- package/docs/expansion-roadmap.md +11 -7
- package/docs/file-picker.md +5 -3
- package/docs/form.md +16 -4
- package/docs/generated/component-maturity.md +88 -91
- package/docs/generated/renderer-evidence.json +1848 -1023
- package/docs/generated/renderer-evidence.md +153 -145
- package/docs/generated/showcase-manifest.json +431 -497
- package/docs/layout.md +8 -9
- package/docs/library-gap-analysis.md +1 -1
- package/docs/masonry.md +11 -0
- package/docs/mentions.md +14 -7
- package/docs/optional-adapters.md +106 -0
- package/docs/otp-field.md +2 -1
- package/docs/pagination.md +4 -1
- package/docs/password-field.md +2 -1
- package/docs/popover.md +9 -6
- package/docs/promotion-candidates.md +2 -1
- package/docs/qr-code.md +11 -65
- package/docs/react-native-completion.md +1 -1
- package/docs/result.md +8 -5
- package/docs/screen-chrome.md +2 -1
- package/docs/sheet.md +16 -3
- package/docs/showcase.md +10 -2
- package/docs/side-panel.md +12 -6
- package/docs/sidebar.md +3 -0
- package/docs/splitter.md +6 -6
- package/docs/stable-core.md +72 -0
- package/docs/stable-promotion.md +47 -43
- package/docs/tags-input.md +5 -2
- package/docs/theme-palette.md +27 -0
- package/docs/thinking-orb.md +124 -0
- package/docs/timeline.md +2 -3
- package/docs/toast.md +6 -0
- package/docs/tooltip.md +2 -1
- package/docs/tour.md +14 -8
- package/docs/transfer-list.md +24 -21
- package/docs/tree-select.md +2 -1
- package/docs/tree.md +12 -7
- package/docs/upload-item.md +7 -3
- package/docs/virtual-list.md +10 -67
- package/package.json +30 -3
- package/docs/app-provider.md +0 -50
- package/docs/border-beam.md +0 -66
- package/docs/chart.md +0 -33
- package/docs/utility.md +0 -53
package/docs/layout.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
**먼저 뺀 것 — 이미 다른 컴포넌트가 소유한다.** 헤더 크롬은 이미
|
|
9
9
|
`TopBar`(adaptive, beta), 푸터 내비게이션은 이미 `BottomNavigation`(adaptive,
|
|
10
|
-
|
|
10
|
+
stable)이다. `Layout`이 그 콘텐츠나 상태를 다시 계약하면 두 곳이 같은 것을
|
|
11
11
|
소유하게 된다 — DataTable이 Pagination/LoadMore를 소유하지 않고 합성하기로 한
|
|
12
12
|
것과 같은 실수를 피한다. `Layout`은 **header/footer가 있다는 사실**만 알고
|
|
13
13
|
(`hasHeader?`/`hasFooter?`), 그 안의 내용은 모른다.
|
|
@@ -73,11 +73,10 @@ Web의 `footer` slot은 `Layout`이 `<footer>` contentinfo를 정확히 한 번
|
|
|
73
73
|
렌더링하거나 요구하지 않는다. `skipLinkLabel` Native prop은 이전 호출부 호환을
|
|
74
74
|
위해 deprecated 상태로만 남아 있다.
|
|
75
75
|
|
|
76
|
-
**현재
|
|
77
|
-
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
승격 전까지 명시적인 debt로 남는다.
|
|
76
|
+
**현재 검증.** 공통 descriptor를 직접 소비하는 first-party Web/RN renderer가 실제
|
|
77
|
+
landmark, source order, overlay adapter를 검증한다. Web Chromium test는 skip-link가 첫
|
|
78
|
+
Tab 대상이고 Enter로 `main`에 초점을 옮기는지 확인하며, 두 renderer의 scenario matrix는
|
|
79
|
+
긴 본문·접근성·dark·200% 글자·RTL·reduced-motion을 검사한다. Native는 skip-link를
|
|
80
|
+
렌더링하지 않고 region 순서·접근성 속성을 검사한다. 따라서 keyboard proof는 Web에만
|
|
81
|
+
요구한다. 실제 제품 shell의 VoiceOver/TalkBack 및 기기 검증은 제품 릴리스 QA에서 다루며
|
|
82
|
+
공용 Layout의 stable 상태를 막지 않는다.
|
|
@@ -77,7 +77,7 @@ control의 `accessibilityLabel`/`accessibilityHint`가 canonical 번역이다.
|
|
|
77
77
|
된다. `Section` + `List` 조합으로 충분하고, 그 조합이 부족하다는 실측이 나오면 그때
|
|
78
78
|
`Section`의 축으로 검토한다.
|
|
79
79
|
- `Chart`: **토큰만 채택한다.** 렌더러는 만들지 않고 계열 팔레트·축·격자·범례 토큰만
|
|
80
|
-
고정한다. 근거는 [
|
|
80
|
+
고정한다. 근거는 [catalog-cleanup.md](./catalog-cleanup.md).
|
|
81
81
|
|
|
82
82
|
## 후속 검토
|
|
83
83
|
|
package/docs/masonry.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Masonry
|
|
2
|
+
|
|
3
|
+
2026-09-29: 사용자가 미구현 기능 완성을 요청해 높이가 다른 카드를 배치하는 Web/Native
|
|
4
|
+
렌더러를 추가했다. `width`, `columns`, `gap`, `getItemHeight(item, itemWidth)`를 명시한다.
|
|
5
|
+
컨테이너 측정과 콘텐츠 높이는 소비 화면이 소유한다. 임의 높이 콘텐츠를 추정해 겹치게
|
|
6
|
+
만드는 대신 확정한 높이로 가장 짧은 열에 순서대로 배치한다. DOM/Native 읽기 순서는
|
|
7
|
+
입력 순서 그대로이며 RTL은 위치만 반전한다. 긴 문구·큰 글자를 사용할 때 높이도 함께
|
|
8
|
+
재계산해야 한다. 빈 목록은 `empty`로 표현하고 중복 키·잘못된 크기는 거부한다.
|
|
9
|
+
|
|
10
|
+
진입점: `@hjmds/react/masonry`, `@hjmds/react-native/masonry`.
|
|
11
|
+
공통 geometry: `@hjmds/design-contracts/components/masonry`.
|
package/docs/mentions.md
CHANGED
|
@@ -79,12 +79,13 @@ popover가 이미 겪는 것과 같은 종류의 렌더러 문제다.
|
|
|
79
79
|
|
|
80
80
|
## 검증 화면
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
이 조사 당시 제품 채택은 미확인이었다. 2026-09-29부터 제품 채택은 관측으로 분리하며,
|
|
83
|
+
현재 성숙도는 catalog와 [승격 기준](stable-promotion.md)을 따른다.
|
|
83
84
|
|
|
84
|
-
##
|
|
85
|
+
## Renderer 성숙도 (2026-09-29)
|
|
85
86
|
|
|
86
|
-
`@hjmds/react/mentions`의 `Mentions`가 이 모듈을
|
|
87
|
-
|
|
87
|
+
`@hjmds/react/mentions`와 `@hjmds/react-native/mentions`의 `Mentions`가 이 모듈을
|
|
88
|
+
실행하며 양 surface 모두 stable이다.
|
|
88
89
|
|
|
89
90
|
- **새 목록 계약을 만들지 않았다.** 팝업은 Combobox의 listbox 어휘(`role="listbox"`/
|
|
90
91
|
`option`, `aria-activedescendant`, 방향키·Enter·Escape)를 그대로 쓰고, 이 모듈은
|
|
@@ -95,6 +96,12 @@ Native `planned`다.
|
|
|
95
96
|
캐럿 위치가 이미 사라진다.
|
|
96
97
|
- **필터·로딩은 제품 소유다.** 후보 목록과 빈 문구를 제품이 넘기고, renderer는 활성 match를
|
|
97
98
|
`onMentionQueryChange`로 알린다.
|
|
98
|
-
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
- Native `onMentionQueryChange`는 commit effect 이후 호출해, 부모가 후보 상태를 갱신해도
|
|
100
|
+
render-phase update를 일으키지 않는다. 후보 영역은 `list` 역할과 제품 제공 label을 갖고,
|
|
101
|
+
각 press action은 후보 이름으로 노출된다.
|
|
102
|
+
- Web과 Native 모두 긴 visible field label을 실제 renderer matrix에서 검증한다. Web은
|
|
103
|
+
component browser test에서 토큰 탐지, 중간 커서 삽입, Arrow 순환, Enter/Escape, pointer,
|
|
104
|
+
empty state를 확인한다. Native host-action test는 중간 커서 범위 치환, trailing text 보존,
|
|
105
|
+
query callback이 commit 이후 전달되는 것과 이름 있는 후보 action을 확인한다.
|
|
106
|
+
- IME 조합과 후보 필터링/loading은 플랫폼·제품 소유 흐름이다. 이 package 검증은 실제
|
|
107
|
+
iOS/Android IME, VoiceOver/TalkBack 동작 또는 제품 adapter를 실행했다고 주장하지 않는다.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Optional presentation adapters
|
|
2
|
+
|
|
3
|
+
2026-09-29: the user requested all six shortlisted libraries, explicitly allowing platform-specific
|
|
4
|
+
adoption. These are opt-in extensions, not six new canonical components or a stable promotion.
|
|
5
|
+
The canonical Statistic/Menu/Sheet/KeyboardAvoiding APIs remain available without additional peers.
|
|
6
|
+
ContextMenu's canonical Native status remains unsupported until the OS adapter has device evidence.
|
|
7
|
+
ImageViewer and all native adapters are experimental pending device/assistive-technology checks.
|
|
8
|
+
|
|
9
|
+
## Entry points and ownership
|
|
10
|
+
|
|
11
|
+
| Package entry | Exports | Platform | Upstream MIT dependency |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| `@hjmds/react/statistic-motion` | AnimatedStatistic | Web | @number-flow/react 0.6.2 |
|
|
14
|
+
| `@hjmds/react/menu-morph` | MorphingMenu | Web | bloom-menu 0.1.0, framer-motion 13.4.4 |
|
|
15
|
+
| `@hjmds/react-native/image-viewer` | ImageViewer | Native | react-native-zoom-toolkit 5.1.1 |
|
|
16
|
+
| `@hjmds/react-native/keyboard-controller` | KeyboardMotionProvider, KeyboardDock, KeyboardFormScrollView | Native | react-native-keyboard-controller 1.22.5 |
|
|
17
|
+
| `@hjmds/react-native/sheet-gesture` | GestureSheetProvider, GestureSheet, GestureSheetInput | Native | @gorhom/bottom-sheet 5.2.14 |
|
|
18
|
+
| `@hjmds/react-native/context-menu-native` | NativeContextMenu | Native | zeego 3.0.6 |
|
|
19
|
+
|
|
20
|
+
All upstream code remains in versioned dependencies with its original notices. No upstream source
|
|
21
|
+
was copied into HJM. Fixed optional peer versions match the inspected npm tarballs, rather than
|
|
22
|
+
claiming compatibility with untested major releases. Typecheck dependencies and showcase dependencies
|
|
23
|
+
are exact too. The upstream source repositories are:
|
|
24
|
+
[NumberFlow](https://github.com/barvian/number-flow), [Bloom](https://github.com/joshpuckett/bloom),
|
|
25
|
+
[Zoom Toolkit](https://github.com/Glazzes/react-native-zoom-toolkit),
|
|
26
|
+
[Keyboard Controller](https://github.com/kirillzyusko/react-native-keyboard-controller),
|
|
27
|
+
[Bottom Sheet](https://github.com/gorhom/react-native-bottom-sheet), [Zeego](https://github.com/nandorojo/zeego).
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
Import only the optional entry you use; none is re-exported from the root. Install the matching
|
|
32
|
+
optional peer(s) from the table in that consuming app. The base entries do not require them.
|
|
33
|
+
For native zoom/sheet, also install Gesture Handler 2.32.0, Reanimated 4.5.1 and Worklets 0.10.1
|
|
34
|
+
and configure the host's GestureHandlerRootView/Reanimated setup. Keyboard Controller requires
|
|
35
|
+
Reanimated and a KeyboardMotionProvider at the app root. Do not nest providers per field.
|
|
36
|
+
|
|
37
|
+
The Expo 57/RN 0.86 showcase uses Zeego 3.0.6 with menu 1.2.2,
|
|
38
|
+
ios-context-menu 3.2.1 and ios-utilities 5.2.0. Same-major iOS overrides avoid the
|
|
39
|
+
old Folly pin; the checked-in Android Kotlin API and iOS Fabric/availability patches
|
|
40
|
+
are required for this host. Installing HJM does not apply workspace patches to a
|
|
41
|
+
consumer. Copy the patches shipped in `@hjmds/react-native/docs/patches/` into the
|
|
42
|
+
consumer and register them with its package manager before rebuilding its native
|
|
43
|
+
client. See that directory's README for exact versions and configuration.
|
|
44
|
+
Expo Go cannot verify these linked native modules.
|
|
45
|
+
|
|
46
|
+
## Behavior boundaries
|
|
47
|
+
|
|
48
|
+
- AnimatedStatistic uses the existing Statistic shell and accessible descriptor. `value` must be
|
|
49
|
+
finite, and `locale` is explicit for deterministic hydration. Intl owns the final visible and
|
|
50
|
+
spoken text. RTL, non-Latin digits, exponent notation and reduced motion use static output.
|
|
51
|
+
`Statistic.renderValue` changes only its aria-hidden visual value; it must not change meaning.
|
|
52
|
+
- MorphingMenu is an action-only alternative. Full selection, async loading and nested menu behavior
|
|
53
|
+
stay in canonical Menu. Bloom owns morph geometry; HJM owns actual button items, disabled guards,
|
|
54
|
+
arrow/Home/End/typeahead, Escape/Tab and focus restoration. RTL and reduced motion use Menu.
|
|
55
|
+
Trigger/menu dimensions are bounded defaults inherited from the upstream button-to-menu pattern;
|
|
56
|
+
very long labels, narrow-screen collision and large-text behavior require further visual evidence.
|
|
57
|
+
- ImageViewer is controlled by `open`, requires localized image/control/failure labels, supports
|
|
58
|
+
paging without a swipe, and unmounts on close to reset its session. Failed images offer retry.
|
|
59
|
+
Host-provided safe-area insets are required when placing it edge-to-edge. Remote image permission,
|
|
60
|
+
URL lifetime and caching remain product responsibilities; the adapter does not fetch metadata.
|
|
61
|
+
- KeyboardDock translates with the keyboard. `clearance` is an additional nonnegative gap above it;
|
|
62
|
+
the host retains bottom safe-area ownership. Do not combine this with another keyboard avoidance
|
|
63
|
+
wrapper around the same content. KeyboardFormScrollView handles focused form fields.
|
|
64
|
+
- GestureSheet uses controlled `open`; host must apply onOpenChange. Wrap a screen in
|
|
65
|
+
GestureSheetProvider inside GestureHandlerRootView. Fixed snap points preserve index semantics;
|
|
66
|
+
dynamic sizing would insert points and is deliberately disabled. Busy blocks user dismissal;
|
|
67
|
+
the host can still close programmatically. GestureSheetInput wires sheet keyboard tracking.
|
|
68
|
+
Android back, backdrop and pan dismissal converge on onOpenChange(false). Consumers remain
|
|
69
|
+
responsible for focus restoration to the opener and avoiding simultaneous modal sheets.
|
|
70
|
+
- NativeContextMenu delegates long-press behavior and menu appearance to the OS. Supply an
|
|
71
|
+
accessible native child; item IDs are unique, labels localized, danger maps to OS destructive
|
|
72
|
+
intent and disabled actions are guarded. Arbitrary custom native menu colors are unsupported.
|
|
73
|
+
|
|
74
|
+
## Evidence and promotion
|
|
75
|
+
|
|
76
|
+
Web stories: Patterns/Optional Motion. Native stories: Experimental/Optional Adapters.
|
|
77
|
+
Tests cover adaptation logic and web browser behavior; native mocks cannot prove OS gestures,
|
|
78
|
+
keyboard animation, accessibility focus, native linking or installed-device health. Keep native
|
|
79
|
+
adapters experimental until iOS/Android device evidence exists. No consumer migration or publication
|
|
80
|
+
is implied by adding these entries. The prior Motion Primitives candidate remains reference-only.
|
|
81
|
+
|
|
82
|
+
A removal replaces the optional imports with canonical Statistic/Menu/Sheet/KeyboardAvoiding or
|
|
83
|
+
product image/menu behavior and removes the matching peers. There is no persisted-state migration.
|
|
84
|
+
|
|
85
|
+
## Checkout verification — 2026-09-29
|
|
86
|
+
|
|
87
|
+
- Contracts: 883 tests plus type/build/contract bundle checks passed.
|
|
88
|
+
- Web: 776 Chromium tests passed; the three new browser cases were rerun after focus/direction
|
|
89
|
+
changes. Existing 172 SSR tests and two new adapter SSR tests passed. Export-boundary test
|
|
90
|
+
rerun after final manifest ordering passed. Web typecheck/build and showcase tests/token checks,
|
|
91
|
+
production Storybook build and static verification passed.
|
|
92
|
+
- Native: 735 mock tests passed; the four new adapter cases were rerun after viewport sizing
|
|
93
|
+
changes. Native typecheck/build and showcase typecheck/test passed. Base Metro production
|
|
94
|
+
fixture still has 614 modules and excludes optional peers. Final iOS/Android showcase Hermes
|
|
95
|
+
exports passed; they are JavaScript bundle evidence, not installed native binary evidence.
|
|
96
|
+
- Renderer graph budgets and an additional base-entry optional-peer isolation guard passed.
|
|
97
|
+
Package tarballs contain all six JS/declaration entries with optional peer metadata.
|
|
98
|
+
Workspace/evidence/docs/governance and central library-policy static checks passed.
|
|
99
|
+
- Browser UI: light/dark, number update, morph opening, ArrowDown/Enter action selection and
|
|
100
|
+
restored trigger focus were observed. Device Hub access returned timeoutReached again;
|
|
101
|
+
native visual/gesture/keyboard/assistive-technology and linking verification remain pending.
|
|
102
|
+
- Peer warnings remain: the base RN 0.81 development fixture is below the Reanimated/Worklets
|
|
103
|
+
0.83–0.86 range; the optional showcase uses RN 0.86.2. The native Storybook 10.4.4 fixture also
|
|
104
|
+
reports transitive UI packages expecting Storybook 10.6 and safe-area-context 5.8 versus 5.7.
|
|
105
|
+
Builds passing do not erase these warnings or prove device compatibility.
|
|
106
|
+
- No npm publication, consumer migration, native binary build, commit or push was performed.
|
package/docs/otp-field.md
CHANGED
package/docs/pagination.md
CHANGED
|
@@ -144,4 +144,7 @@ Steps와 같은 이유다: 순서를 나타내는 문장의 어순과 조사는
|
|
|
144
144
|
[MUI Pagination](https://mui.com/material-ui/react-pagination/)의 명시적 페이지 탐색과
|
|
145
145
|
outlined 위치 표시를 비교했습니다. HJM은 기존 content-brand outline과 평평한 목록을 유지합니다.
|
|
146
146
|
브라우저 테스트는 현재 페이지 의미, 마지막 페이지 focus 유지·중복 요청 차단, 빈 결과,
|
|
147
|
-
320px·2배 글자·4자리 페이지·RTL을 다룹니다.
|
|
147
|
+
320px·2배 글자·4자리 페이지·RTL을 다룹니다. Web renderer는 default·접근성·환경 matrix와
|
|
148
|
+
실제 Tab/Space/Enter 페이지 전환·경계 focus proof를 통과해 stable입니다. Pagination에는
|
|
149
|
+
소비자 문장을 그리는 visible text slot이 없어 long-copy proof는 요구하지 않습니다. 제품 URL·목록
|
|
150
|
+
갱신과 실기기/보조기기 QA는 소비 앱 소유입니다.
|
package/docs/password-field.md
CHANGED
package/docs/popover.md
CHANGED
|
@@ -18,7 +18,7 @@ control이 섞인 레이아웃)를 보여줘야 하는 자리가 있다. `docs/d
|
|
|
18
18
|
| 콘텐츠 | 현지화된 plain text 한 문장 | stable id를 가진 action/선택 항목 목록 | 임의의 interactive 콘텐츠(폼, 링크, 혼합 레이아웃) |
|
|
19
19
|
| focus가 surface 안으로 들어가는가 | **아니오** — `docs/tooltip.md`: "tabbable descendant가 없다" | 예 — 항목에 roving/activate focus | **예** — 결정적 차이 |
|
|
20
20
|
| dismiss 계기 | hover/focus 해제, Escape, sibling 전환 | 선택, Escape/back, outside | close action, outside pointer, **outside-focus**(Tab이 surface 밖으로 나감), Escape |
|
|
21
|
-
| trigger 상호작용 | hover(지연) + focus(즉시) | click/Enter/Space로 열림, 방향키로 탐색 | **click/Enter/Space
|
|
21
|
+
| trigger 상호작용 | hover(지연) + focus(즉시) | click/Enter/Space로 열림, 방향키로 탐색 | **click/Enter/Space 기본**; `openOn="hover"`는 지연된 포인터 진입을 추가하지만 click 경로를 유지해 키보드·터치도 같은 콘텐츠에 도달한다 |
|
|
22
22
|
| positioning | 제품 renderer의 비공개 `AnchoredOverlay` | 같은 anatomy(`menuRecipe`)가 이미 소유 | Tooltip과 동일하게 비공개 `AnchoredOverlay`에 위임 — 새 portal/flip/shift API를 만들지 않는다 |
|
|
23
23
|
|
|
24
24
|
`docs/tooltip.md`가 그은 경계("interactive Popover로 확장하지 않는다")를
|
|
@@ -89,8 +89,9 @@ flip/shift, RTL 논리 방향 변환은 제품 Web renderer의 비공개 `Anchor
|
|
|
89
89
|
명시적으로 공급한다 — 기본값을 발명하지 않는다(Tooltip이 `content`를 필수로
|
|
90
90
|
요구하는 것과 반대로, Popover는 콘텐츠 자체를 타입으로 갖지 않으므로 대신
|
|
91
91
|
이 escape hatch만 둔다).
|
|
92
|
-
- trigger는 click/Enter/Space
|
|
93
|
-
|
|
92
|
+
- trigger는 click/Enter/Space로 연다. `openOn="hover"`를 선택하면 pointer hover도
|
|
93
|
+
지연 후 열리지만, click 경로는 계속 사용할 수 있다. hover가 없는 키보드·터치
|
|
94
|
+
환경에서도 동작을 제공해야 하므로 hover만으로 열리는 전용 경로는 만들지 않는다.
|
|
94
95
|
|
|
95
96
|
## 플랫폼 번역
|
|
96
97
|
|
|
@@ -114,7 +115,7 @@ flip/shift, RTL 논리 방향 변환은 제품 Web renderer의 비공개 `Anchor
|
|
|
114
115
|
| dismiss reason(`close-action`/`outside-pointer`/`outside-focus`/`escape`/`programmatic`) | 공개 |
|
|
115
116
|
| `placement`/`align` | 공개(Tooltip과 같은 값 집합) |
|
|
116
117
|
| `busy`(모든 dismiss 차단) | **배제** — 비모달이라 전역 차단 상태가 성립하지 않는다 |
|
|
117
|
-
| hover trigger |
|
|
118
|
+
| hover trigger | 선택형 추가 입력으로 공개(`openOn="hover"`) — 기본 press 동작을 대체하지 않으며 open/close 지연으로 포인터 이동 간 표면을 유지한다 |
|
|
118
119
|
| portal/flip/shift 공개 API | **배제** — Tooltip의 `AnchoredOverlay` 경계를 그대로 상속 |
|
|
119
120
|
| content 데이터 모델 | **배제** — 런타임 의존성 금지 원칙상 React 콘텐츠 타입을 이 패키지가 가질 수 없다. 콘텐츠 자체는 항상 제품/렌더러 소유다 |
|
|
120
121
|
|
|
@@ -139,7 +140,8 @@ flip·shift를 담당하고, 옆 공간이 부족한 넓은 콘텐츠는 block
|
|
|
139
140
|
Dialog 안의 Popover는 첫 Escape를 소유한다. 내부 Menu가 Escape를 처리했다면 부모는
|
|
140
141
|
그 이벤트를 다시 처리하지 않는다. 모달의 초점 목록은 hidden/inert/disabled 자손을 제외한다.
|
|
141
142
|
|
|
142
|
-
2026-09-16 사용자의 확장 요청으로
|
|
143
|
+
2026-09-16 사용자의 확장 요청으로 Web beta를 제공했다. 2026-09-29 focus/keyboard·hover/touch·
|
|
144
|
+
320px long-copy browser proof를 확인해 stable로 승격한다. Native는 `unsupported`; 제품 채택은 별도다.
|
|
143
145
|
`Patterns/Popover/Filters`는 제목·즐겨찾기 조건 적용/취소/초기화와 실제 목록 교체를 제공한다.
|
|
144
146
|
`ReversibleConfirmation`은 보관 후 취소 버튼으로 초점을 옮기며 실제로 복원한다.
|
|
145
147
|
|
|
@@ -149,5 +151,6 @@ Dialog 안의 Popover는 첫 Escape를 소유한다. 내부 Menu가 Escape를
|
|
|
149
151
|
되돌릴 수 있는 제품 행동의 조합에 적용한다. API 호환을 약속하지 않는다.
|
|
150
152
|
|
|
151
153
|
브라우저 검증은 초기 focus, Escape 복귀, 바깥 클릭 유지, Tab 양방향 이탈, controlled 거절 후
|
|
152
|
-
재시도, dismiss 정책, 중첩 modal/menu,
|
|
154
|
+
재시도, dismiss 정책, 중첩 modal/menu, 선택형 hover 지연과 touch/keyboard press 경로,
|
|
155
|
+
320px·2배 글자·RTL·충돌 배치, exit 격리를 다룬다.
|
|
153
156
|
제품 채택·실제 보조기기 검증은 남아 있다.
|
|
@@ -13,7 +13,8 @@ BurnTok(`/Users/jimin/Desktop/BurnTok`) 양쪽에서 **같은 문제를 이미
|
|
|
13
13
|
|
|
14
14
|
> 2026-08-27 후속: 이 문서는 제품 adoption 실측 기록으로 보존한다. 이후 first-party
|
|
15
15
|
> renderer와 canonical evidence만으로 beta가 된 항목이 있어 현재 catalog status와 표의
|
|
16
|
-
> “실제품 승격 판단”은 의도적으로 다를 수 있다. 실제 제품
|
|
16
|
+
> “실제품 승격 판단”은 의도적으로 다를 수 있다. 당시에는 실제 제품 증거도 stable gate로 보았다.
|
|
17
|
+
> 2026-09-29: 현재 승격은 [승격 기준](stable-promotion.md)을 따른다. 이 문서는 과거 채택 조사이며 제품 수·배포는 더 이상 승격 관문이 아니다.
|
|
17
18
|
|
|
18
19
|
## 요약
|
|
19
20
|
|
package/docs/qr-code.md
CHANGED
|
@@ -1,69 +1,15 @@
|
|
|
1
|
-
# QRCode
|
|
1
|
+
# QRCode
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
2026-09-29: 사용자의 미구현 기능 완성 요청으로 문자열을 실제 스캔 가능한 QR로 인코딩하는
|
|
4
|
+
Web/Native 렌더러를 추가했다. `value`, 현지화된 `label`, QR을 쓰지 않아도 같은 목적을
|
|
5
|
+
달성하는 `fallback` 콘텐츠가 필수다. `level`은 L/M/Q/H, 기본 M이다.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
크기**, 대비 요구(밝은 배경 위 어두운 모듈), 그리고 **QR을 읽을 수 없는 사용자를 위한
|
|
9
|
-
대체 경로**(같은 목적지의 링크·텍스트)가 계약할 거리로 보인다는 것이었습니다. 다만
|
|
10
|
-
인코딩 자체(문자열 → 격자 픽셀)는 이 패키지가 하지 않고 제품이 라이브러리로 그린다는
|
|
11
|
-
전제도 함께 있었습니다.
|
|
7
|
+
qrcode-generator 2.0.4(MIT)를 renderer의 선택형 진입점에서만 가져온다. contracts는 인코더를
|
|
8
|
+
주입받아 dependency-free를 유지한다. Native SVG 렌더링은 react-native-svg 15.15.5가 필요하다.
|
|
9
|
+
한글·이모지는 UTF-8로 인코딩하고 jsQR 1.4.0으로 실제 디코딩 왕복 테스트를 수행한다.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
스캔 대비를 유지하려고 테마와 무관하게 검정 모듈·흰 배경·4모듈 여백을 사용한다. 최소
|
|
12
|
+
모듈 크기 2px를 충족하지 못하는 `size`는 거부하고 정수 모듈 크기로 맞춘다. 입력 용량
|
|
13
|
+
초과는 오류로 알린다. 서버가 소유한 만료·인증·목적지 권한은 QR 컴포넌트가 보증하지 않는다.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`Yajalal RN`(`modules/app-rn/src`)과 `BurnTok`(`apps/web/src`, `packages/design-system/src`)
|
|
18
|
-
양쪽을 `qr`/`QRCode`로 전수 검색했지만 실제 화면 코드에서 QR을 그리거나 스캔하는 곳은
|
|
19
|
-
없었습니다. 유일한 매치는 웹팩 빌드 산출물의 우연한 해시 문자열(`0qr3`, `1qr_kgj`)뿐으로
|
|
20
|
-
제품 코드가 아닙니다. 티켓·프로필 공유·앱 다운로드 유도 등 QR이 흔히 쓰이는 흐름 자체가
|
|
21
|
-
두 제품 어디에도 아직 없습니다.
|
|
22
|
-
|
|
23
|
-
### 2. 진짜 계약처럼 보이는 부분은 이미 다른 컴포넌트가 소유한다
|
|
24
|
-
|
|
25
|
-
관찰에서 유일하게 "새 상태 축"처럼 보였던 것 — **QR만으로는 도달할 수 없는 사용자를 위한
|
|
26
|
-
대체 경로가 함께 있어야 한다** — 는 사실 새로운 개념이 아닙니다. `src/image.ts`의
|
|
27
|
-
`ImageDescriptor`가 이미 정확히 같은 모양(`Icon`과 동일한 decorative/informative
|
|
28
|
-
discriminated union)으로 이 문제를 풀어 두었습니다: 사진 자체가 유일한 정보 전달
|
|
29
|
-
수단이면 `decorative: false` + 현지화된 `accessibilityLabel`이 함께 필요합니다
|
|
30
|
-
(`docs/image.md` "대체 텍스트의 의무 — Icon과 같은 모양"). QR 코드를 `decorative: false`
|
|
31
|
-
`Image`로 취급하고 그 옆에 같은 목적지를 가리키는 `Link`를 나란히 두면, "대체 경로 없이
|
|
32
|
-
QR만 보여주지 않는다"는 계약은 새 컴포넌트 없이 이미 성립합니다. antd가 갖는
|
|
33
|
-
`status: active | loading | expired`도 `Image`의 `idle | loading | loaded | error` 콘텐츠
|
|
34
|
-
상태를 그대로 쓰면 되는 문제입니다.
|
|
35
|
-
|
|
36
|
-
남는 것 — 최소 렌더 크기, 모듈 대비 — 은 상태 축이 아니라 **인코딩 라이브러리가 실제
|
|
37
|
-
모듈 크기를 알아야 계산할 수 있는 렌더링 파라미터**입니다. 이 패키지는 인코딩을 하지
|
|
38
|
-
않기로 이미 전제했으므로, 이 값을 검증할 입력 자체가 이 계층에 없습니다. Statistic이
|
|
39
|
-
포맷된 문자열만 받듯, QR 크기·대비도 그 값을 실제로 계산하는 제품/렌더러의 몫입니다.
|
|
40
|
-
|
|
41
|
-
### 3. 결론
|
|
42
|
-
|
|
43
|
-
새 상태 축도, 새 접근성 개념도 남지 않습니다 — 유일하게 유효했던 부분(대체 경로 의무)은
|
|
44
|
-
`Image` + `Link` 조합으로 이미 표현 가능하고, 나머지는 렌더러가 소유하는 인코딩
|
|
45
|
-
파라미터입니다. 측정된 제품 요구도 없습니다. `docs/authoring-brief.md`와
|
|
46
|
-
`docs/expansion-roadmap.md`가 명시한 대로 이 저장소는 측정되지 않은 표면을 미리 만들지
|
|
47
|
-
않습니다.
|
|
48
|
-
|
|
49
|
-
## 만들지 않은 것
|
|
50
|
-
|
|
51
|
-
`src/qrcode.ts`, `test/qrcode.test.ts`는 없습니다. `componentCatalog`의
|
|
52
|
-
`{ name: "QRCode", category: "data-display", platform: "shared", status: "planned" }` 행과
|
|
53
|
-
crosswalk의 `QRCode → QRCode` direct 관계(`src/component-references.ts:103`)는 건드리지
|
|
54
|
-
않습니다 — 이름 자리를 지우자는 것이 아니라, 지금 채울 새 계약이 없다는 것입니다.
|
|
55
|
-
|
|
56
|
-
## 뒤집힐 조건
|
|
57
|
-
|
|
58
|
-
다음 중 하나가 실제로 측정되면 이 판정을 다시 엽니다.
|
|
59
|
-
|
|
60
|
-
1. Yajalal 또는 BurnTok에 QR이 실제로 필요한 vertical slice(예: 오프라인 티켓, 프로필
|
|
61
|
-
공유 QR, 앱 설치 유도)가 나온다.
|
|
62
|
-
2. 그 슬라이스에서 `Image` + `Link` 조합으로는 표현할 수 없는 새 요구(예: 코드 자체의
|
|
63
|
-
유효 기간을 컴포넌트가 알아야 하고, 만료를 `Image`의 `error` 상태와 다르게 발표해야
|
|
64
|
-
하는 경우)가 나온다.
|
|
65
|
-
|
|
66
|
-
## catalog 배선 명세 제안 (리드 적용, 참고용)
|
|
67
|
-
|
|
68
|
-
지금은 변경할 것이 없습니다. 실제로 QR이 필요해지면 새 recipe를 만들기보다
|
|
69
|
-
`imageRecipe` + `linkRecipe` 조합으로 시작할 것을 권합니다.
|
|
15
|
+
진입점: `@hjmds/react/qr-code`, `@hjmds/react-native/qr-code`.
|
|
@@ -311,7 +311,7 @@ formatters, RN 키보드 회피·햅틱 계약.
|
|
|
311
311
|
- **Asset**(Web/RN): 아이콘·이미지·Lottie·비디오를 같은 액자에 넣는다. **재생기는 슬롯으로
|
|
312
312
|
받아** 이 패키지가 의존하지 않는다. [asset.md](./asset.md).
|
|
313
313
|
- **Chart**: 렌더러를 만들지 않는다. 계열 팔레트·축·격자·범례 토큰(`dataviz`)만 고정하고
|
|
314
|
-
그리기는 제품 라이브러리에 위임한다. 실제로 어긋난 것은 색이었다. [
|
|
314
|
+
그리기는 제품 라이브러리에 위임한다. 실제로 어긋난 것은 색이었다. [catalog-cleanup.md](./catalog-cleanup.md).
|
|
315
315
|
- **전역 density**: Provider의 한 축이 목록·메뉴·표의 기본 밀도가 된다. 컴포넌트 prop이
|
|
316
316
|
언제나 이긴다. 어휘는 통일하지 않고 매핑 함수를 한 곳에 뒀다. [density.md](./density.md).
|
|
317
317
|
- **버튼 라벨 wrap**: 자르지 않고 두 줄까지 접는다. 큰 글자에서는 상한을 푼다(WCAG 1.4.4).
|
package/docs/result.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Result contract
|
|
2
2
|
|
|
3
|
+
현재 계약·Web·Native는 [표시 컴포넌트 승격](stable-core.md)에 따라 stable이다.
|
|
4
|
+
아래 실측은 과거 요구 조사 기록이며 제품 채택 수는 [현재 승격 조건](stable-promotion.md)이 아니다.
|
|
5
|
+
|
|
3
6
|
**문제.** 흐름이 끝나는 화면 — 결제 성공, 제출 실패, 존재하지 않는 페이지 — 을 하나의
|
|
4
7
|
상태와 최대 두 개의 다음 행동으로 보여줍니다.
|
|
5
8
|
|
|
@@ -26,7 +29,7 @@ const saved = {
|
|
|
26
29
|
|
|
27
30
|
## EmptyState와의 경계
|
|
28
31
|
|
|
29
|
-
이 시스템에는 이미 `EmptyState
|
|
32
|
+
이 시스템에는 이미 `EmptyState`가 있습니다. 둘 다 "콘텐츠 대신 보여주는 화면"이라는
|
|
30
33
|
점은 같지만 의미가 정반대입니다.
|
|
31
34
|
|
|
32
35
|
- `EmptyState`는 **아직 없음**입니다 — 검색 결과가 없거나 목록이 비었을 뿐, 조건이
|
|
@@ -89,8 +92,8 @@ Web/Native 모두 아이콘 + 제목 + 설명 + action 슬롯을 세로로 쌓
|
|
|
89
92
|
그대로 조합합니다 — Result 자체의 recipe는 아이콘 tone, 타이포그래피 위계, 슬롯 사이
|
|
90
93
|
gap만 제공합니다.
|
|
91
94
|
|
|
92
|
-
##
|
|
95
|
+
## 제품 화면 검증
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
제품에서 채택할 때는 primary-only, primary+secondary, action-없음 중 실제 사용하는
|
|
98
|
+
조합의 다음 행동과 navigation을 확인합니다. 과거 야잘알 결제/제출 후보는 채택 완료
|
|
99
|
+
증거가 아니며, 제품 배포 여부는 HJM renderer 승격 관문에 포함하지 않습니다.
|
package/docs/screen-chrome.md
CHANGED
|
@@ -49,4 +49,5 @@ LTR/RTL, light/dark에서 hit target, 글자 범위, overflow, 제목 분리와
|
|
|
49
49
|
Web List의 indented 구분선은 행 margin이 아닌 별도 선으로 그린다. 320px 조합에서
|
|
50
50
|
두 번째 제목부터 들여쓰기되던 재현을 고쳤고 Native의 기존 선 전용 inset과 맞췄다.
|
|
51
51
|
Storybook의 조작과 브라우저 검사는 Native 기기의 VoiceOver/TalkBack 검증을 대체하지 않는다.
|
|
52
|
-
|
|
52
|
+
2026-09-29 기준 BottomCTA, TopBar, AuthScreenLayout은 계약·Web·Native stable이다. TopBar Native compact title은
|
|
53
|
+
한 줄 clamp를 제거해 이 문서의 제목 줄바꿈 계약을 따르며, 긴 제목 matrix proof가 연결돼 있다.
|
package/docs/sheet.md
CHANGED
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
ReactNode를 `as unknown as string`으로 전달했다. Web도 `.hjm-sheet__header`를 덮어썼다.
|
|
7
7
|
같은 어댑터가 키보드 높이, top inset, 본문 maxHeight를 별도로 보정하고 있었다.
|
|
8
8
|
|
|
9
|
-
1.4는 제목·닫기 컨트롤을 헤더 중앙에 정렬한다.
|
|
9
|
+
1.4는 제목·닫기 컨트롤을 헤더 중앙에 정렬한다. 1.4에서는 제목을 문자열로 유지했다. 임의의 제목 slot을
|
|
10
10
|
추가하면 접근성 이름과 표시가 서로 어긋날 수 있어 기본 renderer 정렬을 고치는 쪽을 택했다.
|
|
11
11
|
|
|
12
|
+
1.7은 Native `Sheet`·`Dialog`의 `title`을 `string | ReactElement`로 넓힌다(`OverlayTitleProps`).
|
|
13
|
+
정렬을 고친 뒤에도 강조·아이콘이 든 제목을 위해 캐스트가 남았기 때문이다(2026-09-27 감사).
|
|
14
|
+
어긋남은 타입으로 막는다: element 제목이면 `accessibilityTitle: string`이 필수이고 modal의
|
|
15
|
+
`accessibilityLabel`은 그 문자열(+description)로만 만든다. 문자열 제목은 그대로 이름이 되고
|
|
16
|
+
`accessibilityTitle`은 선택이다. Web은 `aria-labelledby`가 렌더된 DOM을 읽으므로 ReactNode 그대로다.
|
|
17
|
+
|
|
12
18
|
Native Sheet는 `keyboardAvoidance`와 `scrollable`을 제공한다. 둘 다 기본 false다.
|
|
13
19
|
이미 키보드를 처리하거나 FlatList를 넣는 소비자를 minor에서 이중 처리하지 않기 위한 선택이다.
|
|
14
20
|
입력 폼은 두 옵션을 함께 켜고 제품의 키보드 listener·강제 maxHeight·중첩 ScrollView를 제거한다.
|
|
@@ -40,11 +46,18 @@ Native Sheet는 `keyboardAvoidance`와 `scrollable`을 제공한다. 둘 다 기
|
|
|
40
46
|
## 증거와 남은 확인
|
|
41
47
|
|
|
42
48
|
- `packages/react-native/test/sheet-viewport.test.tsx`: 키보드 사전 표시, frame 변경, resize,
|
|
43
|
-
floating keyboard, listener 해제, footer/body 경계, safe area와 title
|
|
49
|
+
floating keyboard, listener 해제, footer/body 경계, safe area와 title 이름, element 제목의
|
|
50
|
+
`accessibilityTitle` 쌍(타입·accessibilityLabel), close action/busy 차단, 200% 긴 제목·설명.
|
|
44
51
|
- `packages/react-native/test/modal-lifecycle-fallback.test.tsx`: 종료/후속 surface/focus 회귀.
|
|
45
|
-
- `packages/react/test/sheet-layout.browser.test.tsx`: 320px의 제목/닫기 기하와 100/200%
|
|
52
|
+
- `packages/react/test/sheet-layout.browser.test.tsx`: 320px의 제목/닫기 기하와 100/200% 글자,
|
|
53
|
+
긴 제목·설명 줄바꿈, Tab focus containment, Escape 종료와 trigger focus 복원.
|
|
46
54
|
- 위 Native proof는 host mock이다. 소비 앱 Device Hub 및 Android의 실제 키보드 동작은
|
|
47
55
|
별도로 기록하며 mock 통과를 기기 증거로 삼지 않는다.
|
|
48
56
|
|
|
57
|
+
2026-09-29 renderer 증거 보완: 기존 Sheet renderer proof에는 layout·환경 matrix는 있었지만
|
|
58
|
+
behavior contract의 Web key 동작과 Native host action, 긴 제목·설명 회귀가 별도 interaction test로
|
|
59
|
+
등록되어 있지 않았다. 제품별 기기 영수증을 공통 성숙도 조건으로 만들지 않고, renderer가 소유한
|
|
60
|
+
focus/dismiss와 텍스트 배치 회귀를 직접 확인하도록 위 테스트를 추가했다.
|
|
61
|
+
|
|
49
62
|
참조: [React Native Keyboard](https://reactnative.dev/docs/keyboard),
|
|
50
63
|
[ScrollView](https://reactnative.dev/docs/scrollview).
|
package/docs/showcase.md
CHANGED
|
@@ -39,8 +39,16 @@ Web과 Native가 같은 DOM/view tree를 만드는 것이 아니라, 같은 의
|
|
|
39
39
|
문서만 유지합니다. `beta`는 first-party renderer export와 최소 default evidence가 있어야
|
|
40
40
|
하며, 아직 통과하지 못한 dark·긴 문구·큰 글자·RTL·reduced motion·접근성 scenario를
|
|
41
41
|
generated evidence debt로 공개합니다. `stable`은 이 required scenario를 모두 통과해야
|
|
42
|
-
합니다.
|
|
43
|
-
|
|
42
|
+
합니다. 입력 행동이 있는 컴포넌트는 keyboard/host-action 증거를 추가합니다.
|
|
43
|
+
Heading처럼 keyboard와 Native action이 모두 없는 의미 계약에는 이를 요구하지 않습니다.
|
|
44
|
+
`keyboard` scenario는 Web 키보드 동작과 Native host/accessibility action을 가리키는 기존 ID이며,
|
|
45
|
+
모든 Native 컴포넌트의 외장 키보드 지원을 뜻하지 않습니다.
|
|
46
|
+
|
|
47
|
+
2026-09-29부터 `adaptive` 분류만으로 별도 `platform-parity` 시나리오를 강제하지 않습니다.
|
|
48
|
+
각 renderer가 같은 계약을 검증하는 것에 더해 일괄 비교 영수증까지 요구하던 중복을 없앴습니다.
|
|
49
|
+
플랫폼별 완료·취소·선택 의미가 달라질 위험은 해당 동작 회귀 검사에서 확인합니다.
|
|
50
|
+
기존 parity 시나리오와 evidence는 유지되며 필요한 기능에서 추가 실행할 수 있습니다.
|
|
51
|
+
제품 배포·기기·보조기기 QA는 [승격 절차](stable-promotion.md)의 별도 제품 검증 범위입니다.
|
|
44
52
|
|
|
45
53
|
`beta`의 구현 source of truth는 `@hjmds/react/evidence`와
|
|
46
54
|
`@hjmds/react-native/evidence`입니다. 제품 story는 채택 evidence이지 first-party 구현을
|
package/docs/side-panel.md
CHANGED
|
@@ -67,10 +67,11 @@ target은 `control.minTouchTarget`(44) 이상을 유지한다.
|
|
|
67
67
|
버튼 클릭(`close-action`)은 renderer가 직접 `requestClose`를 호출하는 일반
|
|
68
68
|
동작이라 "플랫폼이 감지하는 중단 벡터" 목록에 넣지 않는다.
|
|
69
69
|
|
|
70
|
-
## Web renderer (2026-09-
|
|
70
|
+
## Web renderer (2026-09-29)
|
|
71
71
|
|
|
72
|
-
`@hjmds/react/side-panel`의 `SidePanel`이 위 계약을 실행한다.
|
|
73
|
-
Native `unsupported`다. 제품
|
|
72
|
+
`@hjmds/react/side-panel`의 `SidePanel`이 위 계약을 실행한다. Web은 2026-09-29에 전용 keyboard·
|
|
73
|
+
long-copy proof를 등록하고 stable로 승격한다. Native는 `unsupported`다. 제품 채택과 보조기기
|
|
74
|
+
실측은 별도 소비자 릴리스 QA다.
|
|
74
75
|
|
|
75
76
|
- **modal만 모달이다.** `modal: true`는 Dialog·Sheet와 **같은** 모달 스택에 들어가
|
|
76
77
|
초점을 가두고 body 스크롤을 잠근다. 이를 위해 그 기계장치를 `packages/react/src/modal.tsx`로
|
|
@@ -87,6 +88,11 @@ Native `unsupported`다. 제품 채택·보조기기 실측은 아직 없으므
|
|
|
87
88
|
- **`onDismissComplete`는 한 번만 부른다.** Sheet의 lifecycle counter는 두지 않았다(위 4번).
|
|
88
89
|
Web에서는 닫은 render와 함께 unmount되므로 reduced motion에서도 기다릴 exit transition이
|
|
89
90
|
없다. 사용자 동작 없이 owner가 닫으면 `programmatic`으로 보고한다.
|
|
90
|
-
-
|
|
91
|
-
미러링과 폭,
|
|
92
|
-
controlled owner의 busy 종료와 1회 완료, 320px·2배 글자
|
|
91
|
+
- 렌더러 테스트는 `test/side-panel.browser.test.tsx`의 다섯 흐름에서 모달 도킹·초점 가둠·스크롤 락,
|
|
92
|
+
RTL `start` 미러링과 폭, 비모달 페이지 상호작용과 Escape 범위, 사유별 단일 보고와 busy 차단,
|
|
93
|
+
controlled owner의 busy 종료와 1회 완료, 320px·2배 글자 배치를 확인한다.
|
|
94
|
+
- 승격 검토 기준은 [Stable 승격 기준](stable-promotion.md)이다. `test/side-panel.browser.test.tsx`의
|
|
95
|
+
`keyboard`와 `long-copy` 검증을 중앙 renderer evidence 및 실행 시나리오에 등록했다. 생성된
|
|
96
|
+
evidence가 모든 필수 시나리오를 보고하고 canonical `pnpm ci:check`가 통과한 뒤 catalog를 올린다.
|
|
97
|
+
- SidePanel은 contract상 Web 전용이고 Native는 `unsupported`다. 제품 채택 수나 VoiceOver/TalkBack,
|
|
98
|
+
실제 제품 기기 검증은 소비자 릴리스 QA이며 Web renderer 성숙도의 별도 gate가 아니다.
|
package/docs/sidebar.md
CHANGED
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
**현재 위치는 색이 아니라 `aria-current="page"`가 말한다.**
|
|
26
26
|
|
|
27
27
|
**tab stop.** 각 항목이 링크이고 문서 순서대로 놓인다. 화살표 grid 탐색을 도입하지 않는다.
|
|
28
|
+
접기 버튼이 있으면 링크 앞에 일반 버튼 tab stop으로 놓인다. 긴 항목명과 그룹 제목은 고정 폭 레일을
|
|
29
|
+
넓히거나 내용을 자르지 않고 줄바꿈한다. 특히 공백 없는 로컬라이즈 문자열도 그룹의 의미가 보이도록
|
|
30
|
+
같은 규칙을 적용한다.
|
|
28
31
|
|
|
29
32
|
**Web 전용.** 폰은 BottomNavigation을 쓰고, 네이티브 태블릿의 split view는 navigator의
|
|
30
33
|
문제다.
|
package/docs/splitter.md
CHANGED
|
@@ -53,8 +53,8 @@ PageUp/PageDown(10배 이동)은 넣지 않았다 — 분할 패널 크기 조
|
|
|
53
53
|
|
|
54
54
|
## Web renderer (2026-09-18)
|
|
55
55
|
|
|
56
|
-
`@hjmds/react/splitter`의 `Splitter`가 이 계약을 실행한다. catalog는 Web `
|
|
57
|
-
Native `unsupported`다. 제품
|
|
56
|
+
`@hjmds/react/splitter`의 `Splitter`가 이 계약을 실행한다. catalog는 Web `stable`,
|
|
57
|
+
Native `unsupported`다. 제품 채택과 실제 보조기기 실측은 승격 범위에 포함하지 않는다.
|
|
58
58
|
|
|
59
59
|
- **드래그와 키보드가 같은 값을 만든다.** 둘 다 계약의 `resolveSplitterDragValue`/
|
|
60
60
|
`getNextSplitterValue`를 호출하므로 renderer에 별도 숫자 산술이 없다.
|
|
@@ -67,9 +67,9 @@ Native `unsupported`다. 제품 채택·보조기기 실측은 아직 없다.
|
|
|
67
67
|
크기를 저장하는 owner가 의미 없는 쓰기를 하지 않도록.
|
|
68
68
|
- 구현 중 실제 결함을 하나 잡았다: `onValueChangeEnd?.(commit(next))`는 handler가 없으면
|
|
69
69
|
인자 평가까지 통째로 건너뛰어 키보드 조절이 조용히 죽는다. commit을 먼저 하고 알린다.
|
|
70
|
-
- 로컬 검증: `test/splitter.browser.test.tsx`
|
|
70
|
+
- 로컬 검증: `test/splitter.browser.test.tsx` 6개(separator 의미·수직 방향과 44px hit
|
|
71
71
|
target, 방향키 step과 Home/End 경계, 드래그 스냅과 드래그당 1회 end, RTL 드래그·키보드,
|
|
72
|
-
disabled)와 `Patterns/Splitter`.
|
|
72
|
+
disabled, 실제 Tab focus와 focused keyboard resize)와 `Patterns/Splitter`.
|
|
73
73
|
|
|
74
|
-
**검증
|
|
75
|
-
|
|
74
|
+
**검증 범위.** Web Chromium renderer matrix가 긴 pane 콘텐츠·환경·접근성 증거를 제공한다.
|
|
75
|
+
제품 vertical slice, screen reader 실측, 모든 OS 조합은 보증하지 않으며 소비 앱 릴리스 QA에서 확인한다.
|