@hjmds/design-contracts 1.7.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 +8 -2
- 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/virtual-list.md
CHANGED
|
@@ -1,70 +1,13 @@
|
|
|
1
|
-
# VirtualList
|
|
1
|
+
# VirtualList
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
2026-09-29: 사용자의 미구현 기능 완성 요청으로 고정 높이 행의 가상화 렌더러를 추가했다.
|
|
4
|
+
Web은 보이는 범위와 overscan만 마운트하고, Native는 FlatList에 위임한다. `rowHeight`와
|
|
5
|
+
`height`는 필수이며 가변 높이·페이지 가져오기를 이 API에 섞지 않는다. 콘텐츠와 글자
|
|
6
|
+
배율에 맞는 행 높이는 호스트가 지정하고, 높이를 확정할 수 없으면 기존 List를 사용한다.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
뒤집지 않는다. 두 catalog row(`List` beta, `VirtualList` planned + `aliases: ["Listy"]`)를
|
|
9
|
-
합치자는 이야기가 아니라, **`VirtualList`가 소유할 계약이 실제로 있는지**를 판정한다.
|
|
8
|
+
Web은 ArrowUp/Down/Home/End로 행을 탐색하고 실제 포커스를 옮긴다. 포커스된 항목은
|
|
9
|
+
스크롤로 가시 범위를 벗어나도 마운트를 유지한다. 필터 결과가 줄면 스크롤 위치를
|
|
10
|
+
새 범위로 제한한다. 전체 개수와 위치는 현재 전달된 배열 기준으로 표시한다.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
가상화가 계약이 되려면 "Web과 Native가 각자 다른 구현 기법으로 같은 결과를 낸다"는
|
|
14
|
-
공통 semantic이 있어야 한다(`docs/architecture.md`의 `adaptive` 정의 그대로). 후보를
|
|
15
|
-
셋으로 나눠 각각 판정했다.
|
|
16
|
-
|
|
17
|
-
### 1. 항목 높이 추정(고정/가변) — 렌더러 기법이다
|
|
18
|
-
|
|
19
|
-
Web windowing 라이브러리(react-window/virtua류)와 RN `FlatList`는 각자의 windowing
|
|
20
|
-
파라미터(`itemSize`/`overscan` vs `getItemLayout`/`windowSize`/`initialNumToRender`)를
|
|
21
|
-
갖지만 이름도, 단위도, 의미도 서로 대응하지 않는다. Slider의 `min`/`max`/`step`처럼
|
|
22
|
-
두 플랫폼이 같은 사용자 의미를 공유하는 것이 아니라, 각 플랫폼의 렌더링 성능 엔진이
|
|
23
|
-
내부적으로 요구하는 힌트일 뿐이다 — 공유할 semantic이 없다.
|
|
24
|
-
|
|
25
|
-
### 2. 스크롤 위치 복원 — 가상화 전용 문제가 아니다
|
|
26
|
-
|
|
27
|
-
가상화하지 않은 평범한 긴 목록도 스크롤 위치 복원이 필요하다(뒤로가기 후 원래 보던
|
|
28
|
-
위치로). 이 문제는 "가상화됐는가"와 독립이고, 스크롤을 소유한 컨테이너/렌더러의 몫이다
|
|
29
|
-
— `VirtualList`라는 이름 아래 있어야 할 이유가 없다.
|
|
30
|
-
|
|
31
|
-
### 3. 총 개수의 낭독 — 실제로는 이미 있거나, 아직 없다
|
|
32
|
-
|
|
33
|
-
가상화된 목록은 DOM/네이티브 뷰 트리에 일부만 마운트되므로 스크린 리더가 전체 개수를
|
|
34
|
-
잘못 알 수 있다는 우려는 진짜다. 그런데 이 문제를 나눠보면:
|
|
35
|
-
|
|
36
|
-
- 전체 데이터가 이미 메모리에 있는 경우(`items.length`를 제품이 이미 안다) — 총
|
|
37
|
-
개수는 이미 알려진 값이고, `aria-setsize`/`aria-posinset`류를 실제 배열 길이로
|
|
38
|
-
채우는 것은 렌더러가 창을 마운트할 때 하는 일이다. 이걸 계산하거나 유도할 판단이
|
|
39
|
-
없다 — Steps/Timeline/Carousel의 `position`/`total`처럼 커서 위치나 유효하지 않은
|
|
40
|
-
조합을 막는 로직이 있는 게 아니라, 그냥 `.length`를 읽는 일이다.
|
|
41
|
-
- 전체 데이터가 아직 로딩 중인 경우(페이지네이션) — 이건 `src/load-more.ts`가 이미
|
|
42
|
-
소유한 문제다. `LoadMoreState`는 의도적으로 `totalCount`를 갖지 않는다 — 모르는
|
|
43
|
-
총합을 지어내는 것이 아무것도 말하지 않는 것보다 나쁘기 때문이다(`idle|loading|
|
|
44
|
-
loadingMore|error|complete` 중 어느 것도 총 개수를 전제하지 않는다). `VirtualList`가
|
|
45
|
-
이 자리에 총 개수 축을 새로 만들면 LoadMore가 이미 내린 판단과 충돌한다.
|
|
46
|
-
|
|
47
|
-
즉 이 문제는 이미 있는 계약(`LoadMore`) 또는 렌더러가 이미 아는 값(`items.length`) 중
|
|
48
|
-
하나로 항상 환원된다 — `VirtualList`가 따로 소유할 몫이 남지 않는다.
|
|
49
|
-
|
|
50
|
-
## 결론
|
|
51
|
-
|
|
52
|
-
측정된 제품 요구도 없다 — 로드맵·메모리 어디에도 "List+LoadMore로는 렌더링 성능이
|
|
53
|
-
부족했다"는 vertical slice 기록이 없다. 야잘알의 긴 목록(팀 순위, 선수 검색 결과)은
|
|
54
|
-
이미 List/ListRow + LoadMore 조합으로 충분히 설계돼 있다.
|
|
55
|
-
|
|
56
|
-
`src/virtual-list.ts`, `test/virtual-list.test.ts`는 만들지 않는다. catalog row(`{ name:
|
|
57
|
-
"VirtualList", category: "data-display", platform: "adaptive", status: "planned",
|
|
58
|
-
aliases: ["Listy"] }`)는 건드리지 않는다 — 이름 자리를 지우자는 것이 아니라, 지금
|
|
59
|
-
채울 계약이 없다는 것이다.
|
|
60
|
-
|
|
61
|
-
## 뒤집힐 조건
|
|
62
|
-
|
|
63
|
-
다음 중 하나가 실제로 측정되면 이 판정을 다시 연다.
|
|
64
|
-
|
|
65
|
-
1. 실제 제품에서 List+LoadMore로 렌더링 성능(프레임 드랍, 초기 마운트 시간)이 측정
|
|
66
|
-
가능하게 부족한 vertical slice가 나온다.
|
|
67
|
-
2. Web과 Native 렌더러가 **같은 이름의 파라미터**로 반응하는 windowing 설정이 두
|
|
68
|
-
플랫폼 모두에서 검증돼, 진짜 공유 semantic이 있다고 판단된다.
|
|
69
|
-
3. 총 개수를 알 수 없는 채로 가상화해야 하는 화면이 나와, `LoadMore`의 "총합을 지어내지
|
|
70
|
-
않는다"는 원칙과 다른 새 발화 규칙이 필요해진다.
|
|
12
|
+
진입점: `@hjmds/react/virtual-list`, `@hjmds/react-native/virtual-list`.
|
|
13
|
+
네트워크 로딩은 기존 LoadMore를 조합한다. Native 재활용·보조기술 스크롤은 FlatList가 소유한다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hjmds/design-contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -133,6 +133,12 @@
|
|
|
133
133
|
"./consumer-policy.md": {
|
|
134
134
|
"default": "./docs/consumer-policy.md"
|
|
135
135
|
},
|
|
136
|
+
"./components/thinking-orb": {
|
|
137
|
+
"types": "./dist/thinking-orb.d.ts",
|
|
138
|
+
"react-native": "./dist/thinking-orb.js",
|
|
139
|
+
"import": "./dist/thinking-orb.js",
|
|
140
|
+
"default": "./dist/thinking-orb.js"
|
|
141
|
+
},
|
|
136
142
|
"./components/agreement": {
|
|
137
143
|
"types": "./dist/agreement.d.ts",
|
|
138
144
|
"react-native": "./dist/agreement.js",
|
|
@@ -522,21 +528,42 @@
|
|
|
522
528
|
"react-native": "./dist/showcase.js",
|
|
523
529
|
"import": "./dist/showcase.js",
|
|
524
530
|
"default": "./dist/showcase.js"
|
|
531
|
+
},
|
|
532
|
+
"./components/masonry": {
|
|
533
|
+
"types": "./dist/masonry.d.ts",
|
|
534
|
+
"react-native": "./dist/masonry.js",
|
|
535
|
+
"import": "./dist/masonry.js",
|
|
536
|
+
"default": "./dist/masonry.js"
|
|
537
|
+
},
|
|
538
|
+
"./components/virtual-list": {
|
|
539
|
+
"types": "./dist/virtual-list.d.ts",
|
|
540
|
+
"react-native": "./dist/virtual-list.js",
|
|
541
|
+
"import": "./dist/virtual-list.js",
|
|
542
|
+
"default": "./dist/virtual-list.js"
|
|
543
|
+
},
|
|
544
|
+
"./components/qr-code": {
|
|
545
|
+
"types": "./dist/qr-code.d.ts",
|
|
546
|
+
"react-native": "./dist/qr-code.js",
|
|
547
|
+
"import": "./dist/qr-code.js",
|
|
548
|
+
"default": "./dist/qr-code.js"
|
|
525
549
|
}
|
|
526
550
|
},
|
|
527
551
|
"files": [
|
|
528
552
|
"dist",
|
|
529
553
|
"docs",
|
|
530
554
|
"README.md",
|
|
531
|
-
"LICENSE"
|
|
555
|
+
"LICENSE",
|
|
556
|
+
"THIRD_PARTY_NOTICES.md"
|
|
532
557
|
],
|
|
533
558
|
"engines": {
|
|
534
559
|
"node": ">=20"
|
|
535
560
|
},
|
|
536
561
|
"devDependencies": {
|
|
537
562
|
"@types/node": "^24.13.3",
|
|
563
|
+
"jsqr": "1.4.0",
|
|
538
564
|
"typescript": "^5.9.3",
|
|
539
|
-
"vitest": "^4.1.11"
|
|
565
|
+
"vitest": "^4.1.11",
|
|
566
|
+
"qrcode-generator": "2.0.4"
|
|
540
567
|
},
|
|
541
568
|
"scripts": {
|
|
542
569
|
"build": "tsc -p tsconfig.build.json",
|
package/docs/app-provider.md
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# AppProvider — 새 컴포넌트를 만들지 않는다
|
|
2
|
-
|
|
3
|
-
## 문제로 제기된 것
|
|
4
|
-
|
|
5
|
-
antd `App`은 `message`/`notification`/`Modal`을 **명령형 훅**(`App.useApp()`)으로
|
|
6
|
-
어디서든 부를 수 있게 context를 심어 주는 컴포넌트다 — 정적 `Modal.confirm()` 같은
|
|
7
|
-
호출이 실제로는 테마·locale context에 접근할 수 있도록 antd가 마련한 배선이다.
|
|
8
|
-
|
|
9
|
-
## 판정: 런타임을 걷어내면 아무것도 남지 않는다
|
|
10
|
-
|
|
11
|
-
`App`이 명령형으로 여는 세 가지는 이미 전부 다른 HJM 계약에 배정돼 있다.
|
|
12
|
-
|
|
13
|
-
| antd `App`이 여는 것 | HJM 대응 | 상태 |
|
|
14
|
-
| --- | --- | --- |
|
|
15
|
-
| `message` | `Toast` | 이미 계약, `beta` |
|
|
16
|
-
| `notification` | `Toast`(`docs/notification.md`가 이미 alias로 흡수) | 이미 계약 |
|
|
17
|
-
| `Modal.confirm`/`Modal.info` 등 | `Dialog`/`AlertDialog`(`decomposed`, crosswalk 확정) | 이미 계약 |
|
|
18
|
-
|
|
19
|
-
즉 `message`/`notification`/`modal`이 **무엇을 보여주는지**는 이미 다 계약돼 있다.
|
|
20
|
-
`App`이 실제로 더하는 것은 오직 하나 — "이미 계약된 그 표면을, 컴포넌트 트리 아무 곳에서나
|
|
21
|
-
`useApp()`으로 명령형 호출할 수 있게 context에 인스턴스를 심어 둔다"는 **배선**이다. 그건
|
|
22
|
-
정의상 React Context + 특정 프레임워크의 훅 API이고, 이 패키지는 React도 RN도 import하지
|
|
23
|
-
않는다(`docs/architecture.md`). 새로운 상태 축도, 새로운 접근성 개념도, 새로운 시각
|
|
24
|
-
recipe도 없다 — Toast/Dialog/AlertDialog가 이미 가진 것 이상으로 계약할 것이 없다.
|
|
25
|
-
|
|
26
|
-
`DesignSystemProvider`(`docs/design-system-provider.md`)와 비교하면 차이가 분명하다:
|
|
27
|
-
그쪽은 런타임을 걷어내도 "테마·방향·배율·모션 선호"라는 **값 타입**이 남았다. `App`은
|
|
28
|
-
걷어내면 **값 타입조차 남지 않는다** — 남는 셋(Toast/Dialog/AlertDialog)이 이미 각자의
|
|
29
|
-
파일에서 완결된 계약이기 때문이다.
|
|
30
|
-
|
|
31
|
-
## 결론
|
|
32
|
-
|
|
33
|
-
`src/app-provider.ts`, `test/app-provider.test.ts`는 만들지 않는다. 제품이 "어디서든
|
|
34
|
-
Toast/AlertDialog를 부르고 싶다"는 요구를 실제로 갖게 되면, 그건 새 HJM 계약이 아니라
|
|
35
|
-
**각 제품 renderer가 자기 프레임워크(React Context, RN 동등물)로 만드는 명령형 wrapper**
|
|
36
|
-
다 — Toast의 `createToastStore`/`createToastSession`이 이미 큐·타이머·중복 처리를
|
|
37
|
-
소유하고 있으므로 renderer는 그 세션에 접근하는 hook만 얹으면 된다.
|
|
38
|
-
|
|
39
|
-
## 판정이 뒤집힐 조건
|
|
40
|
-
|
|
41
|
-
Toast/Dialog/AlertDialog 중 무엇으로도 표현할 수 없는 넷째 표면이 `App`에 새로 필요하다는
|
|
42
|
-
것이 확인되면(예: 화면 밖 push나 시스템 알림함처럼 `docs/notification.md`가 이미 배제
|
|
43
|
-
조건으로 남긴 것), 그때는 그 표면부터 별도로 계약하고 `App`의 배선 문제는 그 이후에
|
|
44
|
-
다시 본다.
|
|
45
|
-
|
|
46
|
-
## 배선 명세 (리드 참고)
|
|
47
|
-
|
|
48
|
-
catalog의 `{ name: "AppProvider", category: "provider", platform: "adaptive", status:
|
|
49
|
-
"planned", aliases: ["App"] }`(`src/catalog.ts:124`)는 그대로 둔다 — recipe/behavior가
|
|
50
|
-
없었고 지금도 없다. crosswalk의 `App → AppProvider`(`adapted`)도 바꿀 필요 없다.
|
package/docs/border-beam.md
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# BorderBeam — 새 컴포넌트를 만들지 않는다
|
|
2
|
-
|
|
3
|
-
## 정정
|
|
4
|
-
|
|
5
|
-
이 문서의 이전 판은 `BorderBeam`이 Ant Design 컴포넌트가 아니라 Magic UI/Aceternity
|
|
6
|
-
계열의 장식 컴포넌트가 crosswalk에 잘못 섞여 들어온 것이라고 주장했다. **그 주장은
|
|
7
|
-
사실이 아니었다** — antd의 실제 Components Overview를 직접 확인하지 않고 일반
|
|
8
|
-
웹검색만으로 판단한 결과였고, 검색 결과가 더 대중적인 Magic UI/Aceternity 쪽으로
|
|
9
|
-
쏠려 있어 antd가 별도로 같은 이름의 컴포넌트를 추가했을 가능성을 놓쳤다.
|
|
10
|
-
|
|
11
|
-
리드가 공식 Overview를 직접 확인해 정정했다: `BorderBeam`은 antd "Other" 섹션에
|
|
12
|
-
실재하는 컴포넌트다. `Watermark`도 crosswalk에서 빠지지 않았다 —
|
|
13
|
-
`src/component-references.ts:123`에 `category: "feedback"`으로 이미 정확히 잡혀
|
|
14
|
-
있다(antd에서 Watermark는 Other가 아니라 Feedback 섹션이다). 섹션별 수(general 4 /
|
|
15
|
-
layout 7 / navigation 7 / data-entry 18 / data-display 21 / feedback 11 / other 5 =
|
|
16
|
-
73)도 저장소 테스트의 단정과 전부 일치한다. `component-references.ts:127`의
|
|
17
|
-
`BorderBeam` 행은 **정확하다** — 제거하지 않는다.
|
|
18
|
-
|
|
19
|
-
## 판정: 그럼에도 만들지 않는다
|
|
20
|
-
|
|
21
|
-
crosswalk이 맞다는 것과 이 컴포넌트를 지금 만들 것인가는 별개 질문이다. `BorderBeam`이
|
|
22
|
-
실제로 antd에 있다 해도, 그 실체 — 사용자 행동에 반응하지 않는 **상시 반복 이동
|
|
23
|
-
애니메이션**(컨테이너 테두리를 따라 빛줄기가 도는 효과) — 은 `docs/identity.md`와
|
|
24
|
-
정면으로 충돌한다.
|
|
25
|
-
|
|
26
|
-
- 첫 문장부터 "HJM은 장식으로 브랜드를 증명하지 않습니다."
|
|
27
|
-
- Motion 원칙: "Reduce Motion에서는 이동과 반복을 제거하고 즉시 전환 또는 짧은 opacity로
|
|
28
|
-
대체합니다", "bounce와 spring은 공간 관계를 설명할 때만 사용합니다."
|
|
29
|
-
- HJM답지 않은 패턴: "브랜드색을 장식 배경처럼 넓게 사용."
|
|
30
|
-
|
|
31
|
-
두 질문으로 검증했다:
|
|
32
|
-
|
|
33
|
-
1. **Reduce Motion에서 무엇이 남는가?** 이동 자체가 이 컴포넌트의 전부이므로, 이동을
|
|
34
|
-
제거하면 정적인 테두리 선(또는 아무것도) 만 남는다 — "즉시 전환"으로 대체할 상태
|
|
35
|
-
변화가 애초에 없다(열림/닫힘/포커스 같은 원인이 없다).
|
|
36
|
-
2. **장식이 없어도 화면이 같은 뜻을 전하는가?** 그렇다 — 이 컴포넌트는 어떤 상태·값·
|
|
37
|
-
선택도 표현하지 않는다. 있으나 없으나 화면이 말하는 내용은 똑같고, 차이는 순전히
|
|
38
|
-
"화려함"뿐이다.
|
|
39
|
-
|
|
40
|
-
두 질문 모두 "이 장식은 정보를 나르지 않는다"로 귀결됐다 — identity가 정확히 배제하는
|
|
41
|
-
자리(장식으로 증명하는 브랜드, 원인 없는 반복 모션)다. 이 세 근거는 crosswalk 출처
|
|
42
|
-
문제와 무관하게 그대로 성립한다.
|
|
43
|
-
|
|
44
|
-
## 결론
|
|
45
|
-
|
|
46
|
-
`src/border-beam.ts`, `test/border-beam.test.ts`는 만들지 않는다.
|
|
47
|
-
|
|
48
|
-
## 판정이 뒤집힐 조건
|
|
49
|
-
|
|
50
|
-
BurnTok/Yajalal 중 하나가 실제로 "강조해야 하는 순간"(예: 실시간 방송 중임을 알리는
|
|
51
|
-
라이브 표시, 당첨/축하 모멘트)에 은은한 강조 테두리가 필요하다고 판단하면, 그건
|
|
52
|
-
`BorderBeam`(상시 반복 장식)이 아니라 그 순간에 한정된 **의미 있는 강조 recipe**(예:
|
|
53
|
-
`feedback.attention` 톤의 짧은 1회성 pulse, Toast의 `priority: high`처럼 특정 상태에만
|
|
54
|
-
묶인 것)로 다시 계약해야 한다.
|
|
55
|
-
|
|
56
|
-
## 배선 명세 (리드 적용)
|
|
57
|
-
|
|
58
|
-
`src/component-references.ts:127`의 `BorderBeam` crosswalk 행은 **정확하므로 바꾸지
|
|
59
|
-
않는다.** `src/catalog.ts`의 `{ name: "BorderBeam", category: "utility", platform:
|
|
60
|
-
"web", status: "planned" }` 행만 대상이다 — 이 행은 "만들 계획"을 뜻하는 `planned`인데
|
|
61
|
-
실제로는 "만들지 않기로 확정"이라 상태가 거짓말을 하고 있다. 이 불일치를 어떻게
|
|
62
|
-
표현할지는 `docs/catalog-decision-status.md`에서 별도로 다룬다.
|
|
63
|
-
|
|
64
|
-
## 출처
|
|
65
|
-
|
|
66
|
-
- [Ant Design — Components Overview](https://ant.design/components/overview/)
|
package/docs/chart.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Chart — 렌더러를 만들지 않는다
|
|
2
|
-
|
|
3
|
-
**결정.** 막대·선·원 차트 렌더러를 HJM에 두지 않는다. 대신 **색·축·격자·범례 토큰**만
|
|
4
|
-
`dataviz` 계약으로 고정하고, 그리는 일은 제품이 고른 라이브러리(Recharts·victory-native·
|
|
5
|
-
d3 등)에 맡긴다.
|
|
6
|
-
|
|
7
|
-
**왜.** 차트를 하나 그리기 시작하면 축 눈금, 툴팁, 애니메이션, 반응형 재계산, 키보드
|
|
8
|
-
탐색, 데이터 테이블 대체 표현까지 전부 따라온다. 그 전부를 이 패키지가 두 표면에서
|
|
9
|
-
유지하는 비용이 제품이 라이브러리 하나를 붙이는 비용보다 크다. 게다가 반쯤 만든 차트는
|
|
10
|
-
제품이 **우리 차트와 자기 차트 두 벌**을 갖게 만든다.
|
|
11
|
-
|
|
12
|
-
**실제로 어긋난 것은 색이었다.** Spint 열지도와 Yajalal 통계가 각자 색을 골랐고, 같은
|
|
13
|
-
포트폴리오의 두 화면이 다른 파랑을 썼다. 그건 렌더러가 없어서가 아니라 **팔레트가 없어서**
|
|
14
|
-
생긴 문제다. 그래서 그 자리만 계약으로 막는다.
|
|
15
|
-
|
|
16
|
-
## 계약이 정하는 것
|
|
17
|
-
|
|
18
|
-
- `datavizSeriesPalette` — light/dark 각 8색의 계열 팔레트. 상태색(info/success/warning/
|
|
19
|
-
attention)은 **쓰지 않는다**: 뜻을 가진 색이라 "3번 계열"에 쓰면 사용자가 경고로 읽는다.
|
|
20
|
-
- `resolveDatavizSeriesColor(theme, index)` — 8을 넘으면 **순환**한다. 색을 자동 생성하지
|
|
21
|
-
않는다. 생성색은 대비를 보장할 수 없고, 9번째 계열이 필요한 화면은 대개 표가 맞다.
|
|
22
|
-
- `datavizChromeTokens` — 축선·축라벨·격자·범례·툴팁은 본문 토큰(`border`·`textMuted`·
|
|
23
|
-
`textBody`·`surface`)을 그대로 쓴다. 차트 전용 회색을 따로 두면 같은 화면의 표·캡션과
|
|
24
|
-
어긋난다.
|
|
25
|
-
- `datavizRedundantEncodings` / `validateDatavizEncoding` — 색만으로 계열을 구분하지
|
|
26
|
-
않는다(WCAG 1.4.1). 직접 라벨·패턴·마커 모양 중 **하나 이상**을 색과 함께 쓴다. 색각
|
|
27
|
-
이상과 흑백 인쇄에서 차트가 남는 조건이다.
|
|
28
|
-
|
|
29
|
-
## 계약이 정하지 않는 것
|
|
30
|
-
|
|
31
|
-
축 스케일, 보간, 툴팁 동작, 데이터 정렬, 빈 상태 문구. 전부 제품과 라이브러리의 몫이다.
|
|
32
|
-
이 결정을 뒤집으려면 "제품 두 곳 이상이 같은 차트 종류를 필요로 하고, 라이브러리 위임으로
|
|
33
|
-
해결되지 않는 접근성 문제가 실측으로 확인됐다"가 먼저 있어야 한다.
|
package/docs/utility.md
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# Utility — 새 컴포넌트를 만들지 않는다
|
|
2
|
-
|
|
3
|
-
## 이름이 이미 경고였다
|
|
4
|
-
|
|
5
|
-
"유틸"은 컴포넌트가 아니다. 먼저 antd의 실제 `Util` 페이지가 무엇인지 확인했다(공식
|
|
6
|
-
문서 확인, 아래 출처). antd `Util`은 UI 컴포넌트가 아니라 **`theme.useToken()` 훅으로
|
|
7
|
-
현재 테마의 design token 값을 자신의 커스텀 컴포넌트에서 읽는 방법**을 설명하는 문서
|
|
8
|
-
페이지다.
|
|
9
|
-
|
|
10
|
-
## 판정: 이 패키지 자체가 이미 그 역할이다
|
|
11
|
-
|
|
12
|
-
`useToken()`이 제공하는 것 — 현재 테마의 색·간격·타이포 값을 코드에서 직접 읽는 것 —
|
|
13
|
-
은 이 저장소에서는 **훅이 아니라 이미 export된 상수**로 존재한다: `spacing`, `radius`,
|
|
14
|
-
`typography`, `glyph`, `stroke`, `semanticColors`, `THEMES`(`foundations.ts`,
|
|
15
|
-
`semantic-colors.ts`, `colors.ts`). antd는 이 값들을 Context에 넣고 훅으로 꺼내야 하지만
|
|
16
|
-
(런타임 테마 스위칭이 Context 기반이므로), 이 패키지는 애초에 런타임 의존성이 없어 그
|
|
17
|
-
값들을 정적 module import로 바로 쓴다 — **"컴포넌트에서 토큰 값을 읽는 방법"이라는 antd
|
|
18
|
-
`Util` 페이지의 문제 자체가 이 패키지 구조에서는 발생하지 않는다.**
|
|
19
|
-
|
|
20
|
-
즉 `Utility`라는 이름 아래 모일 실체가 없다:
|
|
21
|
-
|
|
22
|
-
- 새 값 타입 없음 — 토큰은 이미 `foundations.ts`/`semantic-colors.ts`/`colors.ts`에 있다.
|
|
23
|
-
- 새 접근 패턴 없음 — `import { spacing } from "@hjmds/design-contracts"`가 이미 `useToken()`이
|
|
24
|
-
하는 일과 같은 결과를 낸다(테마별 실제 색 resolve는 `resolveColorReference`가 이미
|
|
25
|
-
한다).
|
|
26
|
-
- 새 접근성·상태 축 없음 — 컴포넌트가 아니므로 애초에 대상이 아니다.
|
|
27
|
-
|
|
28
|
-
`ContextPanel`(`docs/context-panel.md`)과 같은 자리다 — crosswalk에 실체가 없는 이름이
|
|
29
|
-
목록에 먼저 올라간 경우.
|
|
30
|
-
|
|
31
|
-
## 결론
|
|
32
|
-
|
|
33
|
-
`src/utility.ts`, `test/utility.test.ts`는 만들지 않는다.
|
|
34
|
-
|
|
35
|
-
## 판정이 뒤집힐 조건
|
|
36
|
-
|
|
37
|
-
antd `Util` 페이지가 이후 실제 유틸리티 함수(단순 토큰 읽기를 넘어서는, 예를 들어 이
|
|
38
|
-
패키지가 아직 갖지 않은 계산 헬퍼)를 추가하고 그중 플랫폼 중립적으로 유용한 것이
|
|
39
|
-
확인되면, 그건 `Utility`라는 이름의 새 컴포넌트가 아니라 **그 헬퍼가 속한 기존 모듈**
|
|
40
|
-
(예: 숫자 관련이면 `number-field.ts`의 `clampToRange`류)에 함수로 추가하는 쪽을 권한다.
|
|
41
|
-
|
|
42
|
-
## 배선 명세 제안 (리드 적용)
|
|
43
|
-
|
|
44
|
-
`ContextPanel`과 같은 방식을 권한다.
|
|
45
|
-
|
|
46
|
-
**(a) 권고: catalog에서 제거.** `src/catalog.ts`의 `{ name: "Utility", category:
|
|
47
|
-
"utility", platform: "web", status: "planned", aliases: ["Util"] }`(`src/catalog.ts:127`)
|
|
48
|
-
행을 지운다. `component-definitions.ts`의 예약 ID는 무해하니 남겨도 된다.
|
|
49
|
-
|
|
50
|
-
**(b) 대안: catalog row 유지 + 이 문서만 링크.**
|
|
51
|
-
|
|
52
|
-
이 저작자 판단은 (a)다 — 대응할 실체가 없는 `planned` 행이 "곧 만들 컴포넌트"로
|
|
53
|
-
오인되는 비용이 검색 편의보다 크다고 봤다(`ContextPanel`과 같은 이유).
|