@hjmds/design-contracts 0.9.0 → 0.9.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/README.md +15 -10
- package/dist/base-recipes.d.ts +1 -1
- package/dist/base-recipes.js +1 -1
- package/dist/base-recipes.js.map +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/colors.d.ts +5 -1
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +7 -3
- package/dist/colors.js.map +1 -1
- package/dist/icon-button-recipe.d.ts +1 -1
- package/dist/icon-button-recipe.js +1 -1
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/semantic-colors.d.ts +5 -0
- package/dist/semantic-colors.d.ts.map +1 -1
- package/dist/semantic-colors.js +1 -0
- package/dist/semantic-colors.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/architecture.md +3 -2
- package/docs/consumer-policy.md +177 -0
- package/docs/cross-platform-core-normalization.md +24 -7
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +3 -3
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +1 -1
- package/docs/identity.md +5 -2
- package/docs/migration-0.6.md +4 -0
- package/docs/migration-0.9.1.md +15 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -13,6 +13,10 @@ DOM event, focus trap 또는 navigation adapter를 렌더링하지 않고, 두
|
|
|
13
13
|
|
|
14
14
|
상세 원칙은 [`docs/identity.md`](./docs/identity.md), 계층·지원 단계·확장 계획은
|
|
15
15
|
[`docs/architecture.md`](./docs/architecture.md)에 정리되어 있습니다.
|
|
16
|
+
소비 앱의 의무, 성숙도별 채택 조건, 제품 어댑터와 예외 절차는
|
|
17
|
+
[`docs/consumer-policy.md`](./docs/consumer-policy.md)가 규정합니다.
|
|
18
|
+
정책 원문은 package export `@hjmds/design-contracts/consumer-policy.md`에도 포함되어 다음
|
|
19
|
+
patch release부터 독립 소비자 tooling이 설치된 package bytes에서 직접 검증할 수 있습니다.
|
|
16
20
|
외부 라이브러리에서 어떤 문제 분해 원칙만 가져오고 무엇을 복제하지 않는지는
|
|
17
21
|
[`docs/library-reference-decisions.md`](./docs/library-reference-decisions.md)에 기록합니다.
|
|
18
22
|
이번 공백 분석에서 추가한 `Container`, `AspectRatio`, `VisuallyHidden`의 선정 근거는
|
|
@@ -67,14 +71,14 @@ artifact로 제출합니다.
|
|
|
67
71
|
- semantic color reference와 플랫폼 독립 resolver
|
|
68
72
|
- button, surface, field 및 확장 컴포넌트의 typed recipe
|
|
69
73
|
- shared/adaptive/web/native 범위와 stable/beta/planned/deprecated 상태를 담은 component catalog
|
|
70
|
-
-
|
|
74
|
+
- HJM 조직 surface용 기본 그라디언트와 접근성 계약 테스트
|
|
71
75
|
|
|
72
76
|
renderer 및 소비 앱 계층이 소유하는 것:
|
|
73
77
|
|
|
74
78
|
- React DOM 또는 React Native 컴포넌트와 이벤트 타입 (`@hjmds/react`, `@hjmds/react-native`)
|
|
75
79
|
- 제품별 저장 키와 사용자 설정 영속화
|
|
76
80
|
- 아이콘 라이브러리, 폰트 로딩, 애니메이션 구현
|
|
77
|
-
- 제품 전용
|
|
81
|
+
- 제품 전용 컴포넌트, 브랜드 표현과 의미 매핑
|
|
78
82
|
|
|
79
83
|
예를 들어 야구 팀 색상, 경기 상태, 스코어보드, 라인업, 야구장과 같은 야구 도메인
|
|
80
84
|
UI는 Yajalal이 소유합니다. 다른 제품의 기능 상태 역시 각 제품이 범용 `AccentTone`에
|
|
@@ -183,20 +187,21 @@ const successText = resolveColorReference(
|
|
|
183
187
|
나타내는 일반 의미 역할입니다.
|
|
184
188
|
- 저장 키, CSS 변수 이름, KBO 구단/경기 상태 같은 제품 의미는 각 앱에 남습니다.
|
|
185
189
|
|
|
186
|
-
##
|
|
190
|
+
## npm registry에서 설치
|
|
187
191
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
소비 저장소는 세 public package 중 필요한 contracts와 renderer를 npm registry에서
|
|
193
|
+
설치합니다. contracts와 renderer는 fixed release train이므로 같은 정확한 SemVer를
|
|
194
|
+
사용합니다.
|
|
191
195
|
|
|
192
196
|
```bash
|
|
193
|
-
pnpm add
|
|
197
|
+
pnpm add --save-exact @hjmds/design-contracts@<version> @hjmds/react@<version>
|
|
198
|
+
# React Native는 두 번째 package를 @hjmds/react-native로 바꿉니다.
|
|
194
199
|
```
|
|
195
200
|
|
|
196
201
|
`<version>`은 설치할 fixed release의 정확한 SemVer로 바꿉니다.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
Git tag와 release commit은 출처 추적용이며 package-manager dependency로 사용하지 않습니다.
|
|
203
|
+
과거 Git-path 소비자를 옮기는 절차는 역사 문서인
|
|
204
|
+
[`docs/migration-0.6.md`](./docs/migration-0.6.md)에만 남깁니다.
|
|
200
205
|
|
|
201
206
|
## 개발
|
|
202
207
|
|
package/dist/base-recipes.d.ts
CHANGED
package/dist/base-recipes.js
CHANGED
|
@@ -5,7 +5,7 @@ export const buttonRecipe = {
|
|
|
5
5
|
defaults: { tone: "primary", size: "medium" },
|
|
6
6
|
tones: {
|
|
7
7
|
primary: { background: "primary", content: "onPrimary", border: null },
|
|
8
|
-
secondary: { background: "surfaceAlt", content: "text", border: "
|
|
8
|
+
secondary: { background: "surfaceAlt", content: "text", border: "textSub" },
|
|
9
9
|
ghost: { background: null, content: "textMuted", border: null },
|
|
10
10
|
danger: { background: "dangerFill", content: "onDanger", border: null },
|
|
11
11
|
link: { background: null, content: "contentBrand", border: null },
|
package/dist/base-recipes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-recipes.js","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAWpF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU;IACnE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAW;IACtD,KAAK,EAAE;QACL,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE;QACtE,SAAS,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"base-recipes.js","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThemeColors } from \"./colors.js\";\nimport { control, fontWeight, radius, spacing, typography } from \"./foundations.js\";\nimport type { FontWeightValue, TextVariant } from \"./foundations.js\";\n\nexport type ButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\" | \"link\";\nexport type ButtonSize = keyof typeof control.buttonHeight;\nexport type SurfaceTone = \"default\" | \"raised\" | \"accent\" | \"subtle\";\nexport type SurfacePadding = \"none\" | keyof typeof spacing;\nexport type SurfaceRadius = keyof typeof radius;\nexport type FieldVariant = \"surface\" | \"inset\";\nexport type FieldShape = \"medium\" | \"large\" | \"full\";\n\n/** Small renderer entry point for the three foundational visual recipes. */\nexport const buttonRecipe = {\n slots: [\"root\", \"leading\", \"label\", \"trailing\", \"spinner\"] as const,\n defaults: { tone: \"primary\", size: \"medium\" } as const,\n tones: {\n primary: { background: \"primary\", content: \"onPrimary\", border: null },\n secondary: { background: \"surfaceAlt\", content: \"text\", border: \"textSub\" },\n ghost: { background: null, content: \"textMuted\", border: null },\n danger: { background: \"dangerFill\", content: \"onDanger\", border: null },\n link: { background: null, content: \"contentBrand\", border: null },\n },\n sizes: {\n small: {\n height: control.buttonHeight.small,\n hitSlop: control.buttonHitSlop.small,\n paddingHorizontal: spacing.sm,\n textVariant: \"label\",\n },\n medium: {\n height: control.buttonHeight.medium,\n hitSlop: control.buttonHitSlop.medium,\n paddingHorizontal: spacing.md,\n textVariant: \"body\",\n },\n large: {\n height: control.buttonHeight.large,\n hitSlop: control.buttonHitSlop.large,\n paddingHorizontal: spacing.lg,\n textVariant: \"bodyLarge\",\n },\n },\n opacity: { disabled: 0.5, pressed: 0.86 },\n} as const satisfies {\n slots: readonly string[];\n defaults: { tone: ButtonTone; size: ButtonSize };\n tones: Record<\n ButtonTone,\n {\n background: keyof ThemeColors | null;\n content: keyof ThemeColors;\n border: keyof ThemeColors | null;\n }\n >;\n sizes: Record<\n ButtonSize,\n {\n height: number;\n hitSlop: number;\n paddingHorizontal: number;\n textVariant: TextVariant;\n }\n >;\n opacity: { disabled: number; pressed: number };\n};\n\nexport const surfaceRecipe = {\n default: {\n background: \"surface\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: false,\n },\n raised: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: true,\n borderAlways: false,\n },\n accent: {\n background: \"surfaceAccent\",\n border: \"primary\",\n borderAlpha: 0.3,\n elevated: false,\n borderAlways: false,\n },\n subtle: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n },\n} as const satisfies Record<\n SurfaceTone,\n {\n background: keyof ThemeColors;\n border: keyof ThemeColors;\n borderAlpha: number;\n elevated: boolean;\n borderAlways: boolean;\n }\n>;\n\nexport const fieldRecipe = {\n slots: [\n \"root\",\n \"label\",\n \"control\",\n \"leading\",\n \"input\",\n \"trailing\",\n \"hint\",\n \"error\",\n ] as const,\n defaults: { variant: \"surface\", shape: \"medium\" } as const,\n variants: {\n surface: { background: \"surface\" },\n inset: { background: \"bg\" },\n },\n shapes: {\n medium: \"md\",\n large: \"lg\",\n full: \"full\",\n },\n states: {\n idle: { border: \"textMuted\" },\n focused: { border: \"contentBrand\" },\n invalid: { border: \"danger\" },\n },\n minHeight: control.minTouchTarget,\n multilineMinHeight: 80,\n borderWidth: 1,\n focusRingWidth: 2,\n focusRingOffset: 2,\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.sm,\n textVariant: \"body\",\n label: {\n color: \"textBody\",\n textVariant: \"body\",\n fontWeight: fontWeight.semibold,\n gap: spacing.xs,\n },\n support: {\n hintColor: \"textMuted\",\n errorColor: \"danger\",\n textVariant: \"label\",\n gap: 6,\n },\n placeholder: { color: \"textMuted\" },\n disabledOpacity: 0.6,\n} as const satisfies {\n slots: readonly string[];\n defaults: { variant: FieldVariant; shape: FieldShape };\n variants: Record<FieldVariant, { background: keyof ThemeColors }>;\n shapes: Record<FieldShape, keyof typeof radius>;\n states: Record<\n \"idle\" | \"focused\" | \"invalid\",\n { border: keyof ThemeColors }\n >;\n minHeight: number;\n multilineMinHeight: number;\n borderWidth: number;\n focusRingWidth: number;\n focusRingOffset: number;\n paddingHorizontal: number;\n paddingVertical: number;\n textVariant: keyof typeof typography;\n label: {\n color: keyof ThemeColors;\n textVariant: keyof typeof typography;\n fontWeight: FontWeightValue;\n gap: number;\n };\n support: {\n hintColor: keyof ThemeColors;\n errorColor: keyof ThemeColors;\n textVariant: keyof typeof typography;\n gap: number;\n };\n placeholder: { color: keyof ThemeColors };\n disabledOpacity: number;\n};\n\n/**\n * Renderer-neutral Surface geometry. Tone colors stay in `surfaceRecipe` for\n * compatibility; these axes make the previously implicit Web/Native defaults\n * explicit without changing that public recipe shape.\n */\nexport const surfaceDefaults = {\n tone: \"default\",\n padding: \"none\",\n radius: \"lg\",\n bordered: false,\n} as const satisfies {\n tone: SurfaceTone;\n padding: SurfacePadding;\n radius: SurfaceRadius;\n bordered: boolean;\n};\n\nexport const surfaceGeometry = {\n paddings: { none: 0, ...spacing },\n radii: radius,\n} as const satisfies {\n paddings: Record<SurfacePadding, number>;\n radii: Record<SurfaceRadius, number>;\n};\n"]}
|
package/dist/catalog.d.ts
CHANGED
|
@@ -2140,7 +2140,7 @@ export declare const recipeRegistry: {
|
|
|
2140
2140
|
readonly secondary: {
|
|
2141
2141
|
readonly background: "surfaceAlt";
|
|
2142
2142
|
readonly content: "text";
|
|
2143
|
-
readonly border: "
|
|
2143
|
+
readonly border: "textSub";
|
|
2144
2144
|
};
|
|
2145
2145
|
readonly ghost: {
|
|
2146
2146
|
readonly background: null;
|
|
@@ -3343,7 +3343,7 @@ export declare const recipeRegistry: {
|
|
|
3343
3343
|
}>;
|
|
3344
3344
|
readonly border: Readonly<{
|
|
3345
3345
|
source: "theme";
|
|
3346
|
-
key: "
|
|
3346
|
+
key: "textSub";
|
|
3347
3347
|
alpha?: number;
|
|
3348
3348
|
}>;
|
|
3349
3349
|
};
|
package/dist/colors.d.ts
CHANGED
|
@@ -37,7 +37,11 @@ export declare const accentTint: {
|
|
|
37
37
|
readonly strong: 0.2;
|
|
38
38
|
readonly border: 0.3;
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* HJM organization surfaces' default signature. Renderers translate the
|
|
42
|
+
* normalized coordinates. Product identity is owned by each product adapter;
|
|
43
|
+
* consumers must not treat this value as every product's automatic brand.
|
|
44
|
+
*/
|
|
41
45
|
export declare const brandGradient: {
|
|
42
46
|
readonly from: "#0369a1";
|
|
43
47
|
readonly to: "#155dfc";
|
package/dist/colors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE/D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAwCF,eAAO,MAAM,MAAM,EAAE,QAAQ,CAC3B,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAC3B,CAAC;AAEpB,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,eAAO,MAAM,OAAO,EAAE,QAAQ,CAC5B,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAc5D,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAK3D,CAAC;AAEF,eAAO,MAAM,YAAY,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE/D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAwCF,eAAO,MAAM,MAAM,EAAE,QAAQ,CAC3B,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAC3B,CAAC;AAEpB,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,eAAO,MAAM,OAAO,EAAE,QAAQ,CAC5B,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAc5D,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAK3D,CAAC;AAEF,eAAO,MAAM,YAAY,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;CAKhB,CAAC;AAEX,eAAO,MAAM,eAAe,YAAY,CAAC;AAEzC,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAc5D"}
|
package/dist/colors.js
CHANGED
|
@@ -24,12 +24,12 @@ const dark = {
|
|
|
24
24
|
surface: "#131a36",
|
|
25
25
|
surfaceAlt: "#1e293b",
|
|
26
26
|
surfaceAccent: "#1e3a5f",
|
|
27
|
-
border: "#
|
|
27
|
+
border: "#64748b",
|
|
28
28
|
text: "#f1f5f9",
|
|
29
29
|
textBody: "#e2e8f0",
|
|
30
30
|
textMuted: "#cbd5e1",
|
|
31
31
|
textSub: "#94a3b8",
|
|
32
|
-
textWeak: "#
|
|
32
|
+
textWeak: "#8292a9",
|
|
33
33
|
primary: "#075985",
|
|
34
34
|
contentBrand: "#38bdf8",
|
|
35
35
|
danger: "#f87171",
|
|
@@ -66,7 +66,11 @@ export const accentTint = {
|
|
|
66
66
|
strong: 0.2,
|
|
67
67
|
border: 0.3,
|
|
68
68
|
};
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* HJM organization surfaces' default signature. Renderers translate the
|
|
71
|
+
* normalized coordinates. Product identity is owned by each product adapter;
|
|
72
|
+
* consumers must not treat this value as every product's automatic brand.
|
|
73
|
+
*/
|
|
70
74
|
export const brandGradient = {
|
|
71
75
|
from: "#0369a1",
|
|
72
76
|
to: "#155dfc",
|
package/dist/colors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,CAAC;AACrE,CAAC;AAyBD,MAAM,KAAK,GAAG;IACZ,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,SAAS;IACrB,aAAa,EAAE,SAAS;IACxB,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IACvB,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,SAAS;IACpB,UAAU,EAAE,SAAS;IACrB,QAAQ,EAAE,SAAS;CACW,CAAC;AAEjC,MAAM,IAAI,GAAG;IACX,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,SAAS;IACrB,aAAa,EAAE,SAAS;IACxB,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IACvB,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,SAAS;IACpB,UAAU,EAAE,SAAS;IACrB,QAAQ,EAAE,SAAS;CACW,CAAC;AAEjC,MAAM,CAAC,MAAM,MAAM,GAEf,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAKpB,MAAM,CAAC,MAAM,OAAO,GAEhB;IACF,KAAK,EAAE;QACL,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,SAAS;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,SAAS;KACrB;CACF,CAAC;AAEF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAyC;IAC9D,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,SAAS;CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;CACH,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"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","sourcesContent":["/** A persisted preference is an application concern; this package only defines valid values. */\nexport type ThemePreference = \"system\" | \"light\" | \"dark\";\nexport type ResolvedTheme = Exclude<ThemePreference, \"system\">;\n\nexport function isThemePreference(value: unknown): value is ThemePreference {\n return value === \"system\" || value === \"light\" || value === \"dark\";\n}\n\n/**\n * Product code chooses colors by meaning, never by a raw palette name.\n * Both themes deliberately expose exactly the same keys.\n */\nexport type ThemeColors = {\n bg: string;\n surface: string;\n surfaceAlt: string;\n surfaceAccent: string;\n border: string;\n text: string;\n textBody: string;\n textMuted: string;\n textSub: string;\n textWeak: string;\n primary: string;\n contentBrand: string;\n danger: string;\n onPrimary: string;\n dangerFill: string;\n onDanger: string;\n};\n\nconst light = {\n bg: \"#ffffff\",\n surface: \"#f2f4f6\",\n surfaceAlt: \"#e5e8eb\",\n surfaceAccent: \"#c9e2ff\",\n border: \"#e5e8eb\",\n text: \"#191f28\",\n textBody: \"#333d4b\",\n textMuted: \"#4e5968\",\n textSub: \"#6b7684\",\n textWeak: \"#8b95a1\",\n primary: \"#0369a1\",\n contentBrand: \"#075985\",\n danger: \"#b71919\",\n onPrimary: \"#ffffff\",\n dangerFill: \"#b91c1c\",\n onDanger: \"#ffffff\",\n} as const satisfies ThemeColors;\n\nconst dark = {\n bg: \"#0b1026\",\n surface: \"#131a36\",\n surfaceAlt: \"#1e293b\",\n surfaceAccent: \"#1e3a5f\",\n border: \"#64748b\",\n text: \"#f1f5f9\",\n textBody: \"#e2e8f0\",\n textMuted: \"#cbd5e1\",\n textSub: \"#94a3b8\",\n textWeak: \"#8292a9\",\n primary: \"#075985\",\n contentBrand: \"#38bdf8\",\n danger: \"#f87171\",\n onPrimary: \"#ffffff\",\n dangerFill: \"#b91c1c\",\n onDanger: \"#ffffff\",\n} as const satisfies ThemeColors;\n\nexport const THEMES: Readonly<\n Record<ResolvedTheme, Readonly<ThemeColors>>\n> = { light, dark };\n\n/** Generic emphasis roles. Product-specific meanings are mapped by each consumer. */\nexport type AccentTone = \"info\" | \"success\" | \"warning\" | \"attention\";\n\nexport const ACCENTS: Readonly<\n Record<ResolvedTheme, Readonly<Record<AccentTone, string>>>\n> = {\n light: {\n info: \"#6d28d9\",\n success: \"#065f46\",\n warning: \"#92400e\",\n attention: \"#9a3412\",\n },\n dark: {\n info: \"#a78bfa\",\n success: \"#34d399\",\n warning: \"#fbbf24\",\n attention: \"#fb923c\",\n },\n};\n\n/** Solid emphasis fills always pair with `onAccentFill`. */\nexport const accentFill: Readonly<Record<AccentTone, string>> = {\n info: \"#6d28d9\",\n success: \"#065f46\",\n warning: \"#92400e\",\n attention: \"#9a3412\",\n};\n\nexport const onAccentFill = \"#ffffff\";\n\nexport const accentTint = {\n weak: 0.1,\n base: 0.15,\n strong: 0.2,\n border: 0.3,\n} as const;\n\n/**\n * HJM organization surfaces' default signature. Renderers translate the\n * normalized coordinates. Product identity is owned by each product adapter;\n * consumers must not treat this value as every product's automatic brand.\n */\nexport const brandGradient = {\n from: \"#0369a1\",\n to: \"#155dfc\",\n start: { x: 0, y: 0 },\n end: { x: 1, y: 1 },\n} as const;\n\nexport const onBrandGradient = \"#ffffff\";\n\n/** Add an alpha channel without coupling callers to a CSS or React Native helper. */\nexport function withAlpha(hex: string, alpha: number): string {\n const match = /^#([0-9a-fA-F]{6})$/.exec(hex);\n if (!match) {\n throw new TypeError(\"A six-digit hex color is required\");\n }\n if (!Number.isFinite(alpha) || alpha < 0 || alpha > 1) {\n throw new RangeError(\"Alpha must be a finite number between 0 and 1\");\n }\n\n const source = match[1]!;\n const channels = [0, 2, 4].map((offset) =>\n Number.parseInt(source.slice(offset, offset + 2), 16),\n );\n return `rgba(${channels[0]}, ${channels[1]}, ${channels[2]}, ${alpha})`;\n}\n"]}
|
|
@@ -13,7 +13,7 @@ export const iconButtonRecipe = {
|
|
|
13
13
|
secondary: {
|
|
14
14
|
background: semanticColors.action.neutral.background,
|
|
15
15
|
content: semanticColors.action.neutral.content,
|
|
16
|
-
border: semanticColors.border
|
|
16
|
+
border: semanticColors.action.neutral.border,
|
|
17
17
|
},
|
|
18
18
|
ghost: {
|
|
19
19
|
background: null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAGtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,OAAO,EACP,MAAM,GAEP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMtD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU;IAC3C,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;IAC7D,KAAK,EAAE;QACL,OAAO,EAAE;YACP,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU;YAClD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO;YAC5C,MAAM,EAAE,IAAI;SACb;QACD,SAAS,EAAE;YACT,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;YACpD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO;YAC9C,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO;
|
|
1
|
+
{"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAGtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,OAAO,EACP,MAAM,GAEP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMtD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU;IAC3C,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;IAC7D,KAAK,EAAE;QACL,OAAO,EAAE;YACP,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU;YAClD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO;YAC5C,MAAM,EAAE,IAAI;SACb;QACD,SAAS,EAAE;YACT,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;YACpD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO;YAC9C,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;SAC7C;QACD,KAAK,EAAE;YACL,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,SAAS;YACzC,MAAM,EAAE,IAAI;SACb;QACD,MAAM,EAAE;YACN,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;YACnD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO;YAC7C,MAAM,EAAE,IAAI;SACb;KACF;IACD,KAAK,EAAE;QACL,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE;QAChD,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE;QACjD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE;KACjD;IACD,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;IACzC,MAAM,EAAE;QACN,cAAc,EAAE,OAAO,CAAC,OAAO;QAC/B,eAAe,EAAE,OAAO,CAAC,QAAQ;KAClC;CAeF,CAAC;AAQF,iFAAiF;AACjF,MAAM,UAAU,6BAA6B,CAC3C,IAAoB,EACpB,OAA8B;IAE9B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO;QACL,UAAU,EACR,QAAQ,CAAC,UAAU,KAAK,IAAI;YAC1B,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;QACzD,OAAO,EAAE,qBAAqB,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QACzD,MAAM,EACJ,QAAQ,CAAC,MAAM,KAAK,IAAI;YACtB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;KACtD,CAAC;AACJ,CAAC","sourcesContent":["import {\n resolveColorReference,\n type ColorReference,\n type ColorReferencePalette,\n} from \"./color-references.js\";\nimport {\n opacity,\n radius,\n type GlyphSize,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\nexport type IconButtonSize = \"small\" | \"medium\" | \"large\";\nexport type IconButtonShape = \"rounded\" | \"circle\";\nexport type IconButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n\nexport const iconButtonRecipe = {\n slots: [\"root\", \"icon\", \"spinner\"] as const,\n defaults: { tone: \"ghost\", size: \"medium\", shape: \"rounded\" },\n tones: {\n primary: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n border: null,\n },\n secondary: {\n background: semanticColors.action.neutral.background,\n content: semanticColors.action.neutral.content,\n border: semanticColors.action.neutral.border,\n },\n ghost: {\n background: null,\n content: semanticColors.content.secondary,\n border: null,\n },\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n border: null,\n },\n },\n sizes: {\n small: { diameter: 36, hitSlop: 4, glyph: \"sm\" },\n medium: { diameter: 44, hitSlop: 0, glyph: \"md\" },\n large: { diameter: 52, hitSlop: 0, glyph: \"lg\" },\n },\n shapes: { rounded: \"md\", circle: \"full\" },\n states: {\n pressedOpacity: opacity.pressed,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: {\n tone: IconButtonTone;\n size: IconButtonSize;\n shape: IconButtonShape;\n };\n tones: Record<\n IconButtonTone,\n { background: ColorReference | null; content: ColorReference; border: ColorReference | null }\n >;\n sizes: Record<IconButtonSize, { diameter: number; hitSlop: number; glyph: GlyphSize }>;\n shapes: Record<IconButtonShape, keyof typeof radius>;\n states: { pressedOpacity: number; disabledOpacity: number };\n};\n\nexport type ResolvedIconButtonPresentation = Readonly<{\n background: string | null;\n content: string;\n border: string | null;\n}>;\n\n/** Resolve one recipe tone for non-CSS renderers without a second tone table. */\nexport function resolveIconButtonPresentation(\n tone: IconButtonTone,\n palette: ColorReferencePalette,\n): ResolvedIconButtonPresentation {\n const contract = iconButtonRecipe.tones[tone];\n return {\n background:\n contract.background === null\n ? null\n : resolveColorReference(contract.background, palette),\n content: resolveColorReference(contract.content, palette),\n border:\n contract.border === null\n ? null\n : resolveColorReference(contract.border, palette),\n };\n}\n"]}
|
|
@@ -123,6 +123,11 @@ export declare const semanticColors: {
|
|
|
123
123
|
key: "text";
|
|
124
124
|
alpha?: number;
|
|
125
125
|
}>;
|
|
126
|
+
readonly border: Readonly<{
|
|
127
|
+
source: "theme";
|
|
128
|
+
key: "textSub";
|
|
129
|
+
alpha?: number;
|
|
130
|
+
}>;
|
|
126
131
|
};
|
|
127
132
|
readonly danger: {
|
|
128
133
|
readonly background: Readonly<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-colors.d.ts","sourceRoot":"","sources":["../src/semantic-colors.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"semantic-colors.d.ts","sourceRoot":"","sources":["../src/semantic-colors.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8EjB,CAAC"}
|
package/dist/semantic-colors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-colors.js","sourceRoot":"","sources":["../src/semantic-colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC;IACxB,OAAO,EAAE;QACP,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;QAC9B,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC;QACxB,KAAK,EAAE,UAAU,CAAC,eAAe,CAAC;KACnC;IACD,OAAO,EAAE;QACP,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;QAC3B,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC;QAC5B,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC;QAClC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC;QAC/B,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;QAClC,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC;QACjC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;QAC5B,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC;KACjC;IACD,MAAM,EAAE;QACN,MAAM,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC;QACjC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC;QAC7B,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC;QAC9B,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC;QACjC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;KAC7B;IACD,MAAM,EAAE;QACN,KAAK,EAAE;YACL,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC;YACjC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC;SACjC;QACD,OAAO,EAAE;YACP,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC;YACpC,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"semantic-colors.js","sourceRoot":"","sources":["../src/semantic-colors.ts"],"names":[],"mappings":"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","sourcesContent":["import { accentColor, themeColor } from \"./color-references.js\";\n\n/**\n * Stable role aliases above the legacy ThemeColors key set. New recipes should\n * prefer these roles so the underlying theme shape can evolve independently.\n */\nexport const semanticColors = {\n canvas: themeColor(\"bg\"),\n surface: {\n default: themeColor(\"surface\"),\n sunken: themeColor(\"surfaceAlt\"),\n raised: themeColor(\"bg\"),\n brand: themeColor(\"surfaceAccent\"),\n },\n content: {\n primary: themeColor(\"text\"),\n body: themeColor(\"textBody\"),\n secondary: themeColor(\"textMuted\"),\n tertiary: themeColor(\"textSub\"),\n decorative: themeColor(\"textWeak\"),\n brand: themeColor(\"contentBrand\"),\n danger: themeColor(\"danger\"),\n inverse: themeColor(\"onPrimary\"),\n },\n border: {\n subtle: themeColor(\"border\", 0.7),\n default: themeColor(\"border\"),\n strong: themeColor(\"textWeak\"),\n focus: themeColor(\"contentBrand\"),\n danger: themeColor(\"danger\"),\n },\n action: {\n brand: {\n background: themeColor(\"primary\"),\n content: themeColor(\"onPrimary\"),\n },\n neutral: {\n background: themeColor(\"surfaceAlt\"),\n content: themeColor(\"text\"),\n border: themeColor(\"textSub\"),\n },\n danger: {\n background: themeColor(\"dangerFill\"),\n content: themeColor(\"onDanger\"),\n },\n },\n feedback: {\n info: {\n foreground: accentColor(\"info\"),\n background: accentColor(\"info\", 0.1),\n badgeBackground: accentColor(\"info\", 0.1),\n border: accentColor(\"info\", 0.3),\n },\n success: {\n foreground: accentColor(\"success\"),\n background: accentColor(\"success\", 0.1),\n badgeBackground: accentColor(\"success\", 0.1),\n border: accentColor(\"success\", 0.3),\n },\n warning: {\n foreground: accentColor(\"warning\"),\n background: accentColor(\"warning\", 0.1),\n badgeBackground: accentColor(\"warning\", 0.1),\n border: accentColor(\"warning\", 0.3),\n },\n attention: {\n foreground: accentColor(\"attention\"),\n background: accentColor(\"attention\", 0.1),\n badgeBackground: accentColor(\"attention\", 0.1),\n border: accentColor(\"attention\", 0.3),\n },\n danger: {\n foreground: themeColor(\"danger\"),\n background: themeColor(\"danger\", 0.1),\n badgeBackground: themeColor(\"danger\", 0.1),\n border: themeColor(\"danger\", 0.3),\n },\n },\n interaction: {\n hover: themeColor(\"text\", 0.06),\n focus: themeColor(\"contentBrand\", 0.08),\n pressed: themeColor(\"text\", 0.1),\n selected: themeColor(\"primary\", 0.1),\n },\n} as const;\n"]}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAgB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"0.9.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAgB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"0.9.1\" as const;\n"]}
|
package/docs/architecture.md
CHANGED
|
@@ -292,8 +292,9 @@ scenario 전체와 consumer adoption evidence까지 통과한 surface에만 허
|
|
|
292
292
|
- public token/recipe 변경에는 타입 검사, 계약 테스트, light/dark 대비 검증을 포함합니다.
|
|
293
293
|
- beta → stable 승격에는 Web/RN fixture, 키보드 또는 screen reader 검증, Reduce Motion 확인이
|
|
294
294
|
필요합니다.
|
|
295
|
-
- 소비 앱은 정확한 SemVer
|
|
296
|
-
|
|
295
|
+
- 소비 앱은 npm registry의 정확한 SemVer를 고정하며 Git ref, package path, tarball 또는
|
|
296
|
+
로컬 경로를 커밋하지 않습니다.
|
|
297
|
+
- contracts와 선택한 renderer의 package version을 항상 동일하게 유지합니다.
|
|
297
298
|
- 제거는 deprecation 기간과 migration note를 거칩니다.
|
|
298
299
|
- 원시 팔레트나 제3자 라이브러리 이름을 public component prop으로 노출하지 않습니다.
|
|
299
300
|
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# HJM 소비 앱 정책
|
|
2
|
+
|
|
3
|
+
상태: **Normative**
|
|
4
|
+
정책 버전: **1.2.0**
|
|
5
|
+
적용 대상: 신규 HJM Web·React Native 앱과 기존 앱의 새 화면
|
|
6
|
+
|
|
7
|
+
이 정책 원문은 다음 package patch release부터
|
|
8
|
+
`@hjmds/design-contracts/consumer-policy.md` export에 포함됩니다. 아직 그 export를 포함하지
|
|
9
|
+
않는 `0.9.0` 소비자는 HJM-APP-STANDARD의 versioned profile과 catalog snapshot을 정책
|
|
10
|
+
근거로 사용하고, 존재하지 않는 `v0.9.0` 정책 URL을 만들어 내면 안 됩니다.
|
|
11
|
+
|
|
12
|
+
이 문서는 "HJM답게 보인다"를 특정 화면 복제로 정의하지 않습니다. 모든 제품이 공유해야
|
|
13
|
+
하는 것은 정보 위계, semantic role, 상태 피드백, 접근성 품질과 플랫폼별 행동입니다.
|
|
14
|
+
제품의 이름, 도메인 언어, 핵심 콘텐츠와 대표 브랜드 표현은 각 제품이 소유합니다.
|
|
15
|
+
|
|
16
|
+
`MUST`, `MUST NOT`, `SHOULD`, `MAY`는 각각 필수, 금지, 강한 권고, 선택을 뜻합니다.
|
|
17
|
+
|
|
18
|
+
## 1. 의존성과 버전
|
|
19
|
+
|
|
20
|
+
- 앱은 `@hjmds/design-contracts`와 한 renderer(`@hjmds/react` 또는
|
|
21
|
+
`@hjmds/react-native`)를 npm registry에서 설치해야 합니다(MUST).
|
|
22
|
+
- contracts와 renderer는 같은 정확한 SemVer여야 합니다(MUST). `^`, `~`, workspace·file,
|
|
23
|
+
Git ref와 tarball dependency는 허용하지 않습니다(MUST NOT).
|
|
24
|
+
- 앱 runtime은 granular subpath를 우선하고 catalog·showcase·evidence entry는 CI나
|
|
25
|
+
tooling에서만 사용해야 합니다(SHOULD).
|
|
26
|
+
|
|
27
|
+
## 2. 성숙도별 채택
|
|
28
|
+
|
|
29
|
+
| Catalog 상태 | 신규 앱 기본 정책 | 추가 조건 |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `stable` | 사용 가능 | 제품 흐름·copy 검증 |
|
|
32
|
+
| `beta` | 기본 비활성 | ADR, 앱 테스트, 실제 기기/브라우저 evidence |
|
|
33
|
+
| `planned` | 사용 금지 | HJM package에서 구현·승격한 뒤 채택 |
|
|
34
|
+
| `deprecated` | 신규 사용 금지 | 공지된 migration 기한 안에 제거 |
|
|
35
|
+
|
|
36
|
+
신규 앱 scaffold는 Stable Core만 기본 surface로 채택해야 합니다(MUST). Beta를 사용하려면
|
|
37
|
+
앱의 `docs/decisions/` 아래 ADR에 채택 이유, 대체안, 소유자, 검증 환경과 재검토 날짜를
|
|
38
|
+
기록해야 합니다(MUST).
|
|
39
|
+
|
|
40
|
+
### 2.1 Stable Core와 필수 foundation bridge
|
|
41
|
+
|
|
42
|
+
현재 Stable Core는 `Surface`, `Button`, `Field`, `TextArea` 네 surface입니다. `Text`,
|
|
43
|
+
`Icon`, `Stack`, `Container`, `DesignSystemProvider`처럼 첫 제품 화면에 필요한 foundation
|
|
44
|
+
일부는 catalog에서 여전히 `beta`입니다. 따라서 “첫 화면부터 HJM”을 요구하면서 이
|
|
45
|
+
foundation을 몰래 `stable`로 간주하거나 `betaAdoptions: []`로 기록하는 것은 허용하지
|
|
46
|
+
않습니다(MUST NOT).
|
|
47
|
+
|
|
48
|
+
HJM-APP-STANDARD가 versioned `requiredFoundations` 목록을 선언한 경우 다음 bridge를
|
|
49
|
+
적용합니다.
|
|
50
|
+
|
|
51
|
+
- 필수 foundation의 채택 이유와 최소 목록은 중앙 profile이 소유합니다. 앱마다 같은
|
|
52
|
+
선택 이유를 새로 발명하지 않습니다(MUST).
|
|
53
|
+
- 각 앱은 실제 adapter와 사용 환경에 대한 evidence를 소유합니다(MUST). `draft` /
|
|
54
|
+
`incubating` contract에서는 evidence가 `planned`일 수 있지만, `active` 또는 release gate는
|
|
55
|
+
timestamp가 있는 `verified` evidence 없이는 통과하면 안 됩니다(MUST NOT).
|
|
56
|
+
- 중앙 필수 목록 밖의 `beta`는 계속 제품별 optional adoption입니다. 제품 ADR, 대안,
|
|
57
|
+
제거·승격 조건과 verified app evidence가 모두 필요합니다(MUST).
|
|
58
|
+
- foundation이 catalog에서 `stable`로 승격되면 기존 표준의 의미를 조용히 바꾸지 않고
|
|
59
|
+
다음 versioned app profile에서 bridge 목록을 줄입니다(MUST).
|
|
60
|
+
|
|
61
|
+
이 bridge는 성숙도 예외가 아니라 공개된 임시 채택 계약입니다. catalog와 generated
|
|
62
|
+
maturity manifest에는 해당 surface가 계속 `beta`로 보여야 합니다.
|
|
63
|
+
|
|
64
|
+
## 3. 코드 경계
|
|
65
|
+
|
|
66
|
+
- 앱 root는 HJM Provider를 한 번 구성하고 theme, direction, text scale, reduce-motion 입력을
|
|
67
|
+
제품 설정과 연결해야 합니다(MUST).
|
|
68
|
+
- 화면은 원시 hex, 임의 spacing/radius/type scale을 새로 선언하지 않고 HJM semantic token
|
|
69
|
+
또는 제품 어댑터를 사용해야 합니다(MUST).
|
|
70
|
+
- 도메인 상태는 화면마다 색을 정하지 않고 제품 어댑터에서 HJM `AccentTone`과 component
|
|
71
|
+
variant에 매핑해야 합니다(MUST).
|
|
72
|
+
- HJM component의 `style` escape hatch는 배치용 margin, width, flex와 화면 composition에만
|
|
73
|
+
사용해야 합니다(SHOULD). color, typography, radius, control height와 interaction state를
|
|
74
|
+
덮어쓰는 용도로 사용하면 안 됩니다(MUST NOT).
|
|
75
|
+
- 플랫폼 primitive가 필요한 경우 접근성 또는 플랫폼 관습 때문에 필요한 adapter에
|
|
76
|
+
한정하고, 그 이유를 해당 adapter test로 고정해야 합니다(MUST).
|
|
77
|
+
|
|
78
|
+
### 3.1 React Native legacy style compatibility boundary
|
|
79
|
+
|
|
80
|
+
`@hjmds/react-native` 0.9.x의 공개 타입에는 `style`, `labelStyle`, `inputStyle`,
|
|
81
|
+
`containerStyle`과 여러 slot `*Style`처럼 전체 React Native style을 받는 호환 API가 남아
|
|
82
|
+
있습니다. 이 타입 범위와 caller-last 렌더 순서는 기존 소비자를 위한 집행 공백이지, 앞 절의
|
|
83
|
+
금지 속성을 제품이 덮어써도 된다는 허가가 아닙니다.
|
|
84
|
+
|
|
85
|
+
- 신규 앱과 기존 앱의 새 화면은 legacy raw style prop을 새로 사용하면 안 됩니다(MUST NOT).
|
|
86
|
+
컴포넌트가 `layoutStyle`을 제공하면 배치에는 그것만 사용하고, 제공하지 않으면 바깥
|
|
87
|
+
composition wrapper를 사용하거나 HJM에 semantic axis를 먼저 추가해야 합니다(MUST).
|
|
88
|
+
- `HjmCompositionStyle` / `layoutStyle`은 margin, width, flex 계열과 `alignSelf`만 노출하며
|
|
89
|
+
color, typography, padding, gap, border, radius, height, opacity, transform과 interaction
|
|
90
|
+
state key를 타입에서 제외합니다. 허용된 margin 값도 HJM spacing token 또는 검토된 제품
|
|
91
|
+
adapter에서 와야 합니다(MUST).
|
|
92
|
+
- 기존 화면의 legacy prop은 migration 기간에만 유지할 수 있습니다(MAY). controlled visual
|
|
93
|
+
key가 남아 있으면 정책 항목, 소유자, 대체 semantic API와 제거 train을 ADR에 기록해야
|
|
94
|
+
하며, 신규 사용으로 복사해서는 안 됩니다(MUST NOT).
|
|
95
|
+
- 0.9 호환 train에서는 등록 style ID와 배열을 런타임에서 필터링하거나 조용히 삭제하지
|
|
96
|
+
않습니다. 그러한 즉시 변경은 기존 앱의 레이아웃을 예측 불가능하게 깨뜨리기 때문입니다.
|
|
97
|
+
|
|
98
|
+
legacy raw style surface는 다음 조건이 모두 충족된 뒤 공지된 breaking train에서 제거합니다.
|
|
99
|
+
|
|
100
|
+
1. Stable Core가 canonical `layoutStyle` 또는 동등한 좁은 composition API를 제공한다.
|
|
101
|
+
2. HJM showcase와 관리 중인 앱이 새 API로 이동하고 light/dark, large text, RTL과 touch-target
|
|
102
|
+
evidence를 다시 검증한다.
|
|
103
|
+
3. 최소 한 fixed release train 동안 deprecation과 migration 문서를 제공한다.
|
|
104
|
+
4. 제거 Changeset이 영향을 받는 prop과 semantic 대안을 열거한다.
|
|
105
|
+
|
|
106
|
+
이 제거는 늦어도 첫 `1.0.0` train의 release gate 전에 완료해야 합니다(MUST). 그 전까지
|
|
107
|
+
legacy prop의 런타임 호환성은 유지하지만 신규 앱 적합성 검사에서는 실패로 취급합니다.
|
|
108
|
+
|
|
109
|
+
권장 구조는 다음과 같습니다. 실제 폴더명은 stack 관습에 맞춰도 역할은 유지합니다.
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
src/ui/hjm-provider.* 공통 환경 연결
|
|
113
|
+
src/ui/product-theme.* 제품 브랜드·도메인 semantic mapping
|
|
114
|
+
src/ui/components/* 제품 전용 composition과 플랫폼 adapter
|
|
115
|
+
src/features/* UI 계약을 소비하는 기능
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 4. 제품 정체성 경계
|
|
119
|
+
|
|
120
|
+
HJM이 소유하는 것:
|
|
121
|
+
|
|
122
|
+
- semantic color role과 light/dark 대비
|
|
123
|
+
- spacing, type scale, radius, motion, touch target
|
|
124
|
+
- component anatomy, 상태, 키보드·screen-reader 행동
|
|
125
|
+
- loading, empty, error, disabled, focus의 일관된 문법
|
|
126
|
+
|
|
127
|
+
제품이 소유하는 것:
|
|
128
|
+
|
|
129
|
+
- 이름, 로고, 대표 이미지와 illustration
|
|
130
|
+
- 제품 대표 accent·gradient와 도메인 상태 매핑
|
|
131
|
+
- 핵심 콘텐츠 밀도, 정보 우선순위와 feature composition
|
|
132
|
+
- 사용자에게 보이는 copy, i18n, navigation 정보 구조
|
|
133
|
+
|
|
134
|
+
`brandGradient`는 HJM 조직 surface와 fallback용입니다. 신규 제품이 이를 hero나 CTA의
|
|
135
|
+
기본값으로 그대로 채택할 의무는 없습니다. 제품 고유 gradient를 쓰는 경우 light/dark와
|
|
136
|
+
on-color 대비, 색에 의존하지 않는 상태 표지, reduce-motion을 제품 테스트로 검증해야
|
|
137
|
+
합니다(MUST).
|
|
138
|
+
|
|
139
|
+
## 5. 필수 검증과 evidence
|
|
140
|
+
|
|
141
|
+
앱 CI는 최소한 다음을 실패 조건으로 두어야 합니다(MUST).
|
|
142
|
+
|
|
143
|
+
1. contracts/renderer exact version 일치와 금지 dependency 형식 검사
|
|
144
|
+
2. versioned `requiredFoundations` 전체의 선언과 lifecycle에 맞는 app evidence 검사
|
|
145
|
+
3. HJM Provider 존재와 제품 theme adapter 존재 검사
|
|
146
|
+
4. 원시 색·간격·radius의 화면 레이어 유입 방지 검사
|
|
147
|
+
5. typecheck, unit/component test, production build
|
|
148
|
+
6. light/dark, 100–200% 글자 크기, LTR/RTL, reduce motion 중 앱이 지원한다고 선언한 환경
|
|
149
|
+
7. optional Beta component를 쓴다면 ADR과 해당 component·환경의 versioned consumer evidence
|
|
150
|
+
|
|
151
|
+
앱이 지원하지 않는 플랫폼이나 환경은 가짜 통과 script로 만들지 않고 app contract에서
|
|
152
|
+
`not-applicable`과 이유를 선언해야 합니다(MUST).
|
|
153
|
+
|
|
154
|
+
## 6. 예외와 변경 절차
|
|
155
|
+
|
|
156
|
+
필수 규칙의 예외는 암묵적으로 두지 않습니다. ADR에는 다음을 모두 기록해야 합니다.
|
|
157
|
+
|
|
158
|
+
- 위반하는 정책 항목과 사용자 가치
|
|
159
|
+
- 검토한 대안과 선택 이유
|
|
160
|
+
- 위험, 보완 테스트와 담당자
|
|
161
|
+
- 만료 또는 재검토 날짜
|
|
162
|
+
|
|
163
|
+
공통 API를 바꾸는 것이 한 제품의 local override보다 적절하면 제품 코드를 복제하지 않고
|
|
164
|
+
HJM에 Changeset과 Web/RN evidence를 먼저 제출합니다. 반대로 제품 의미가 들어가면 공통
|
|
165
|
+
package로 승격하지 않습니다.
|
|
166
|
+
|
|
167
|
+
## 7. 신규 앱 완료 조건
|
|
168
|
+
|
|
169
|
+
다음 질문에 모두 "예"라고 답할 수 있어야 HJM 채택이 완료된 것입니다.
|
|
170
|
+
|
|
171
|
+
- exact fixed-train dependency와 Provider가 CI에서 검증되는가?
|
|
172
|
+
- Stable은 기본 사용하고 필수 beta foundation은 중앙 목록+앱 evidence로, optional Beta는
|
|
173
|
+
제품 ADR+evidence로 구분되어 있는가?
|
|
174
|
+
- screen 코드가 semantic token·component를 우회하지 않는가?
|
|
175
|
+
- 같은 상태가 Web/RN에서 같은 의미와 자연스러운 플랫폼 행동을 갖는가?
|
|
176
|
+
- 로고를 제거해도 제품의 핵심 콘텐츠와 정보 구조가 다른 제품과 구분되는가?
|
|
177
|
+
- 제품 고유 표현을 제거해도 정보 위계·피드백·접근성에서는 HJM의 결이 남는가?
|
|
@@ -82,6 +82,22 @@ edge를 항상 그린다.
|
|
|
82
82
|
|
|
83
83
|
호환 alias는 새 문서와 예제에서 사용하지 않는다. 제거는 major release에서만 한다.
|
|
84
84
|
|
|
85
|
+
## Collection and state vocabulary
|
|
86
|
+
|
|
87
|
+
공통 제품 코드에서 같은 역할은 같은 이름을 사용한다. Web을 기준으로 Native의 비파괴 호환
|
|
88
|
+
bridge를 추가했으며, 새 코드는 canonical 열만 사용한다.
|
|
89
|
+
|
|
90
|
+
| Component | Canonical Web/Native API | Deprecated Native alias |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| Switch | `checked`, `defaultChecked`, `onCheckedChange` | `value`, `defaultValue`, `onValueChange` |
|
|
93
|
+
| RadioGroup | `items: RadioGroupItem[]` | `options: RadioOption[]` |
|
|
94
|
+
| SegmentedControl | `items: SegmentedControlItem[]` | `options: SegmentedControlOption[]` |
|
|
95
|
+
| Tabs | `items: TabItem[]`, item key `id` | `options: TabOption[]`, item key `value` |
|
|
96
|
+
| Select | `source`/`items`/`sections`, `selectedKey`, `defaultSelectedKey`, `onSelectionChange` | `options`, `value`, `defaultValue`, `onValueChange` |
|
|
97
|
+
|
|
98
|
+
한 인스턴스에서 canonical과 deprecated channel을 함께 전달하면 타입과 runtime 모두 실패한다.
|
|
99
|
+
이 규칙은 TypeScript를 우회하는 JavaScript 소비자에게도 결정적인 상태 모델을 보장한다.
|
|
100
|
+
|
|
85
101
|
## Reference application notes
|
|
86
102
|
|
|
87
103
|
상위 판단 원칙은 [library-reference-decisions.md](./library-reference-decisions.md)에만 둔다.
|
|
@@ -97,14 +113,15 @@ edge를 항상 그린다.
|
|
|
97
113
|
|
|
98
114
|
## Audited next migrations
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
합치지 않았다.
|
|
116
|
+
Accordion은 이름만 맞추면 의미가 오히려 불명확해져 이번 release에서 억지로 합치지 않았다.
|
|
102
117
|
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
- Web은 single/multiple mode에 따라 `value: string | string[]`, `allowsMultipleExpanded`,
|
|
119
|
+
`items[{id,title,panel}]`을 사용한다.
|
|
120
|
+
- Native는 항상 집합 형태인 `expandedValues: string[]`, `multiple`,
|
|
121
|
+
`items[{value,title,content}]`를 사용한다.
|
|
122
|
+
- 공통 descriptor의 key/content 이름과 single/multiple selection type을 먼저 결정한 뒤,
|
|
123
|
+
기존 두 모델을 deprecated alias로 격리해야 한다. host event/style 차이와 달리 이 상태 모델
|
|
124
|
+
차이는 다음 minor의 명시적 migration 대상이다.
|
|
108
125
|
|
|
109
126
|
## Intentional remaining differences
|
|
110
127
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component maturity and evidence manifest
|
|
2
2
|
|
|
3
|
-
> Generated from `@hjmds/design-contracts` 0.9.
|
|
3
|
+
> Generated from `@hjmds/design-contracts` 0.9.1. Do not edit this file directly; run `pnpm contracts:sync`.
|
|
4
4
|
|
|
5
5
|
This document is the human-readable projection of the same catalog and Showcase manifest consumed by product CI.
|
|
6
6
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"designSystemVersion": "0.9.
|
|
3
|
+
"designSystemVersion": "0.9.1",
|
|
4
4
|
"source": "packages/design-contracts/docs/generated/showcase-manifest.json",
|
|
5
5
|
"surfaces": {
|
|
6
6
|
"web": {
|
|
7
7
|
"packageName": "@hjmds/react",
|
|
8
|
-
"packageVersion": "0.9.
|
|
8
|
+
"packageVersion": "0.9.1",
|
|
9
9
|
"activeComponents": 63,
|
|
10
10
|
"claimedComponents": 63,
|
|
11
11
|
"completeScenarioComponents": 33,
|
|
@@ -2918,7 +2918,7 @@
|
|
|
2918
2918
|
},
|
|
2919
2919
|
"native": {
|
|
2920
2920
|
"packageName": "@hjmds/react-native",
|
|
2921
|
-
"packageVersion": "0.9.
|
|
2921
|
+
"packageVersion": "0.9.1",
|
|
2922
2922
|
"activeComponents": 63,
|
|
2923
2923
|
"claimedComponents": 63,
|
|
2924
2924
|
"completeScenarioComponents": 34,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Renderer evidence coverage
|
|
2
2
|
|
|
3
|
-
> Generated for HJM 0.9.
|
|
3
|
+
> Generated for HJM 0.9.1. Do not edit directly; run `pnpm evidence:sync`.
|
|
4
4
|
|
|
5
5
|
This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
|
|
6
6
|
|
package/docs/identity.md
CHANGED
|
@@ -50,7 +50,9 @@ HJM은 장식으로 브랜드를 증명하지 않습니다. 정보와 행동의
|
|
|
50
50
|
|
|
51
51
|
- 깨끗한 white canvas와 깊은 navy dark canvas가 기본입니다.
|
|
52
52
|
- HJM blue는 행동과 현재 상태를 드러내는 서명입니다.
|
|
53
|
-
-
|
|
53
|
+
- 공통 `brandGradient`는 HJM 조직 surface와 fallback에만 사용합니다. 제품 hero와 특별한
|
|
54
|
+
CTA의 브랜드 표현은 제품 어댑터가 소유하며, 모든 앱이 같은 그라디언트를 자동으로
|
|
55
|
+
복제하지 않습니다.
|
|
54
56
|
- `text`, `textBody`, `textMuted`는 필수 정보에 사용할 수 있습니다.
|
|
55
57
|
- `textSub`, `textWeak`는 장식적·중복적인 정보에만 사용하며 필수 문장에는 쓰지 않습니다.
|
|
56
58
|
- 제품 상태는 먼저 `info / success / warning / attention`에 매핑하고, 제품 이름은 공용
|
|
@@ -103,7 +105,8 @@ HJM은 장식으로 브랜드를 증명하지 않습니다. 정보와 행동의
|
|
|
103
105
|
| product palette | KBO 구단 색상, 코드 미리보기 색상 |
|
|
104
106
|
|
|
105
107
|
제품 매핑은 앱 또는 제품 어댑터에 남깁니다. HJM 코어에 제품명, 저장 키, 도메인 상태를
|
|
106
|
-
추가하지 않습니다.
|
|
108
|
+
추가하지 않습니다. 공통 HJM 결을 유지하면서 제품을 구별하는 구체적인 경계와 검증 항목은
|
|
109
|
+
[`consumer-policy.md`](./consumer-policy.md)의 "제품 정체성 경계"를 따릅니다.
|
|
107
110
|
|
|
108
111
|
## 참고 원칙
|
|
109
112
|
|
package/docs/migration-0.6.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# v0.6 migration
|
|
2
2
|
|
|
3
|
+
> **역사 문서:** 아래 Git-path 명령은 v0.6 당시의 일회성 전환 기록이며 신규 설치 예제가
|
|
4
|
+
> 아닙니다. 현재 소비 앱은 [`../README.md`](../README.md)의 npm registry 설치 규칙에 따라
|
|
5
|
+
> contracts와 renderer를 같은 정확한 SemVer로 설치합니다.
|
|
6
|
+
|
|
3
7
|
v0.6은 renderer가 없는 계약 패키지의 역할을 이름에서 분명히 하고, Web/RN 앱이 필요한
|
|
4
8
|
graph만 가져가도록 package boundary를 나누는 breaking release입니다. package name은
|
|
5
9
|
`@hjm/design-system`에서 `@hjmds/design-contracts`로 변경됩니다. 이전 이름 alias나 호환
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 0.9.1 contrast correction
|
|
2
|
+
|
|
3
|
+
The patch improves boundaries visible in dark product screens and the secondary action outlines in both themes. Upgrade contracts and the Web or Native renderer to the same exact version. No required theme keys or component props are added.
|
|
4
|
+
|
|
5
|
+
| Role | Previous | Updated | Contrast on neutral surfaces |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| Dark `border` | `#1e293b` | `#64748b` | 3.07–3.95:1 on `surfaceAlt`, `surface`, `bg` |
|
|
8
|
+
| Dark `textWeak` | `#64748b` | `#8292a9` | 4.62–5.94:1 on the same surfaces; weaker than `textSub` |
|
|
9
|
+
| Secondary Button / IconButton border | `border` | `textSub` | 3.75:1 light / 5.71:1 dark against its `surfaceAlt` fill |
|
|
10
|
+
|
|
11
|
+
`semanticColors.action.neutral.border` exposes the existing `textSub` theme key for neutral action recipes. Native renderers already resolve these recipes; Web CSS uses the same role. Field idle, focus, invalid, placeholder and hint colors are unchanged.
|
|
12
|
+
|
|
13
|
+
After upgrading, remove product overrides whose only purpose was restoring these defaults. Keep product-owned treatment for special backgrounds and emphasis. In particular, choose `tone="secondary"` when an icon action needs a visible circular or rounded boundary: the default `ghost` tone remains transparent and has no visible outline.
|
|
14
|
+
|
|
15
|
+
The reported ratios describe opaque enabled colors on the three named neutral surfaces. They do not establish contrast for tinted surfaces, photos, opacity overlays, disabled states or custom palettes. Light `textWeak` remains decorative; light `textSub` is not sufficient for small text on every neutral surface, so meaningful small light-mode copy should use `textMuted` or stronger. Recheck both themes, focus/invalid states and consumer style overrides in the actual product after updating.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hjmds/design-contracts",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -112,6 +112,9 @@
|
|
|
112
112
|
"./renderer-evidence.json": {
|
|
113
113
|
"default": "./docs/generated/renderer-evidence.json"
|
|
114
114
|
},
|
|
115
|
+
"./consumer-policy.md": {
|
|
116
|
+
"default": "./docs/consumer-policy.md"
|
|
117
|
+
},
|
|
115
118
|
"./components/alert-dialog": {
|
|
116
119
|
"types": "./dist/alert-dialog.d.ts",
|
|
117
120
|
"react-native": "./dist/alert-dialog.js",
|