@eeennsu/native 0.1.0 → 0.2.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.
@@ -0,0 +1,12 @@
1
+ import type { Contracts } from "@eeennsu/tokens";
2
+ import type { FC } from "react";
3
+ type BadgeProps = Contracts<"native">["Badge"];
4
+ /**
5
+ * 짧은 상태 표시. 웹은 `inline-flex` 라 블록 흐름에서 글자 폭만큼 줄지만 RN 에는 인라인이 없다 —
6
+ * 세로 방향 부모 안에서는 부모 폭으로 늘어난다(웹도 Stack 안에서는 같다). 줄이려면 소비자가
7
+ * `className="self-start"` 를 준다. 기본값으로 넣지 않는 이유는 `align="center"` 인 가로 Stack 에서
8
+ * 세로 가운데 정렬을 깨뜨리기 때문이다.
9
+ */
10
+ export declare const Badge: FC<BadgeProps>;
11
+ export {};
12
+ //# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,KAAK,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;AAyB/C;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CAWhC,CAAC"}
package/dist/badge.js ADDED
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text as RNText, View } from "react-native-css/components";
3
+ import { cn } from "./cn.js";
4
+ /**
5
+ * Button 과 같은 이유로 variant 를 표면(View)과 전경(Text) 둘로 쪼갠다 — RN 은 View → Text 로
6
+ * 색이 상속되지 않는다(구현 노트 N-12). 클래스 이름은 웹 Badge 와 같은 어휘다(AC-25).
7
+ */
8
+ const surfaces = {
9
+ primary: "bg-brand",
10
+ secondary: "bg-surface-muted",
11
+ danger: "bg-danger",
12
+ };
13
+ const foregrounds = {
14
+ primary: "text-fg-on-brand",
15
+ secondary: "text-fg",
16
+ danger: "text-fg-on-danger",
17
+ };
18
+ /** 투명 테두리는 웹과 같이 Input 과 높이를 맞추기 위해서다(plan D-6). */
19
+ const boxes = {
20
+ sm: "px-2 py-0 rounded-full",
21
+ md: "px-3 py-1 rounded-full",
22
+ };
23
+ /**
24
+ * 짧은 상태 표시. 웹은 `inline-flex` 라 블록 흐름에서 글자 폭만큼 줄지만 RN 에는 인라인이 없다 —
25
+ * 세로 방향 부모 안에서는 부모 폭으로 늘어난다(웹도 Stack 안에서는 같다). 줄이려면 소비자가
26
+ * `className="self-start"` 를 준다. 기본값으로 넣지 않는 이유는 `align="center"` 인 가로 Stack 에서
27
+ * 세로 가운데 정렬을 깨뜨리기 때문이다.
28
+ */
29
+ export const Badge = ({ children, variant = "secondary", size = "sm", className }) => (_jsx(View, { className: cn("flex-row items-center border border-transparent", surfaces[variant], boxes[size], className), children: _jsx(RNText, { className: cn(foregrounds[variant], "text-sm"), children: children }) }));
30
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAK7B;;;GAGG;AACH,MAAM,QAAQ,GAAiC;IAC7C,OAAO,EAAE,UAAU;IACnB,SAAS,EAAE,kBAAkB;IAC7B,MAAM,EAAE,WAAW;CACpB,CAAC;AAEF,MAAM,WAAW,GAAiC;IAChD,OAAO,EAAE,kBAAkB;IAC3B,SAAS,EAAE,SAAS;IACpB,MAAM,EAAE,mBAAmB;CAC5B,CAAC;AAEF,oDAAoD;AACpD,MAAM,KAAK,GAA8B;IACvC,EAAE,EAAE,wBAAwB;IAC5B,EAAE,EAAE,wBAAwB;CAC7B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAmB,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,WAAW,EAAE,IAAI,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CACpG,KAAC,IAAI,IACH,SAAS,EAAE,EAAE,CACX,iDAAiD,EACjD,QAAQ,CAAC,OAAO,CAAC,EACjB,KAAK,CAAC,IAAI,CAAC,EACX,SAAS,CACV,YAED,KAAC,MAAM,IAAC,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,YAAG,QAAQ,GAAU,GACtE,CACR,CAAC"}
package/dist/box.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Contracts } from "@eeennsu/tokens";
2
+ import type { FC } from "react";
3
+ /**
4
+ * 스타일 없는 블록 컨테이너. `className` 을 붙일 자리다(웹 Box 와 같은 역할).
5
+ * 배치 prop 은 Stack 만 갖는다(plan D-7). RN `View` 는 원래 세로 flex 라 웹 `div` 와 달리
6
+ * 자식이 가로 폭으로 늘어난다 — 웹 Stack 의 기본값(`column` · `stretch`)과 같은 모양이다.
7
+ */
8
+ export declare const Box: FC<Contracts<"native">["Box"]>;
9
+ //# sourceMappingURL=box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC;;;;GAIG;AACH,eAAO,MAAM,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAE9C,CAAC"}
package/dist/box.js ADDED
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { View } from "react-native-css/components";
3
+ import { cn } from "./cn.js";
4
+ /**
5
+ * 스타일 없는 블록 컨테이너. `className` 을 붙일 자리다(웹 Box 와 같은 역할).
6
+ * 배치 prop 은 Stack 만 갖는다(plan D-7). RN `View` 는 원래 세로 flex 라 웹 `div` 와 달리
7
+ * 자식이 가로 폭으로 늘어난다 — 웹 Stack 의 기본값(`column` · `stretch`)과 같은 모양이다.
8
+ */
9
+ export const Box = ({ children, className }) => (_jsx(View, { className: cn(className), children: children }));
10
+ //# sourceMappingURL=box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.js","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAmC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAC9E,KAAC,IAAI,IAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAAG,QAAQ,GAAQ,CAClD,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
+ import { Badge } from "./badge.js";
2
+ import { Box } from "./box.js";
1
3
  import { Button } from "./button.js";
2
4
  import { Card } from "./card.js";
3
5
  import { Input } from "./input.js";
6
+ import { Label } from "./label.js";
4
7
  import { Stack } from "./stack.js";
5
8
  import { Text } from "./text.js";
6
- export { Button, Card, Input, Stack, Text };
9
+ import { Textarea } from "./textarea.js";
10
+ export { Badge, Box, Button, Card, Input, Label, Stack, Text, Textarea };
7
11
  export { cn } from "./cn.js";
8
12
  /**
9
13
  * 계약 맵 테스트(C-17)가 보는 객체. 키 집합이 `nativeComponents` 와 같고
@@ -36,10 +40,41 @@ export declare const components: {
36
40
  className?: string;
37
41
  ref?: import("react").Ref<import("@eeennsu/tokens").FocusHandle>;
38
42
  }>;
43
+ Textarea: import("react").FC<{
44
+ label: string;
45
+ size?: import("@eeennsu/tokens").ControlSize;
46
+ id?: string;
47
+ placeholder?: string;
48
+ disabled?: boolean;
49
+ invalid?: boolean;
50
+ value?: string;
51
+ defaultValue?: string;
52
+ onValueChange?: (value: string) => void;
53
+ className?: string;
54
+ ref?: import("react").Ref<import("@eeennsu/tokens").FocusHandle>;
55
+ }>;
56
+ Label: import("react").FC<{
57
+ children: string | string[];
58
+ htmlFor?: string;
59
+ className?: string;
60
+ }>;
39
61
  Card: import("react").FC<{
40
62
  children: import("@eeennsu/tokens").ElementChildren;
41
63
  className?: string;
42
64
  }>;
65
+ Badge: import("react").FC<{
66
+ children: string | string[];
67
+ variant?: Extract<import("@eeennsu/tokens").Variant, "primary" | "secondary" | "danger">;
68
+ size?: import("@eeennsu/tokens").BadgeSize;
69
+ className?: string;
70
+ }>;
71
+ Text: import("react").FC<{
72
+ children: string | string[];
73
+ tone?: import("@eeennsu/tokens").Tone;
74
+ size?: import("@eeennsu/tokens").TypographyStep;
75
+ heading?: "1" | "2" | "3";
76
+ className?: string;
77
+ }>;
43
78
  Stack: import("react").FC<{
44
79
  children: import("@eeennsu/tokens").ElementChildren;
45
80
  direction?: "row" | "column";
@@ -48,11 +83,8 @@ export declare const components: {
48
83
  wrap?: boolean;
49
84
  className?: string;
50
85
  }>;
51
- Text: import("react").FC<{
52
- children: string | string[];
53
- tone?: import("@eeennsu/tokens").Tone;
54
- size?: import("@eeennsu/tokens").TypographyStep;
55
- heading?: "1" | "2" | "3";
86
+ Box: import("react").FC<{
87
+ children: import("@eeennsu/tokens").ElementChildren;
56
88
  className?: string;
57
89
  }>;
58
90
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAMtB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACzE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAUtB,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
+ import { Badge } from "./badge.js";
2
+ import { Box } from "./box.js";
1
3
  import { Button } from "./button.js";
2
4
  import { Card } from "./card.js";
3
5
  import { Input } from "./input.js";
6
+ import { Label } from "./label.js";
4
7
  import { Stack } from "./stack.js";
5
8
  import { Text } from "./text.js";
6
- export { Button, Card, Input, Stack, Text };
9
+ import { Textarea } from "./textarea.js";
10
+ export { Badge, Box, Button, Card, Input, Label, Stack, Text, Textarea };
7
11
  export { cn } from "./cn.js";
8
12
  /**
9
13
  * 계약 맵 테스트(C-17)가 보는 객체. 키 집합이 `nativeComponents` 와 같고
@@ -12,8 +16,12 @@ export { cn } from "./cn.js";
12
16
  export const components = {
13
17
  Button,
14
18
  Input,
19
+ Textarea,
20
+ Label,
15
21
  Card,
16
- Stack,
22
+ Badge,
17
23
  Text,
24
+ Stack,
25
+ Box,
18
26
  };
19
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM;IACN,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;CACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACzE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM;IACN,KAAK;IACL,QAAQ;IACR,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,GAAG;CACJ,CAAC"}
package/dist/input.d.ts CHANGED
@@ -1,8 +1,17 @@
1
- import type { Contracts } from "@eeennsu/tokens";
1
+ import type { Contracts, ControlSize } from "@eeennsu/tokens";
2
2
  import type { FC } from "react";
3
3
  type InputProps = Contracts<"native">["Input"];
4
+ /** 웹 Input 과 같은 크기 클래스다(AC-25). 웹의 `text-*` 는 여기서도 같은 스텝을 쓴다. */
5
+ export declare const inputSizes: Record<ControlSize, string>;
4
6
  /**
5
- * 한 줄 입력. `label` 은 `accessibilityLabel` 로만 간다 — 가시 라벨은 v2 의 Label 조합이다(C-13).
7
+ * 테두리 1px 이 Button 과 높이를 맞춘다 — 없으면 Input 이 2px 낮다(plan D-6).
8
+ * 웹에는 있는 `placeholder:text-fg-muted` 가 빠져 있다 — react-native-css 는
9
+ * `placeholder:` 변형을 `placeholderTextColor` 로 옮기지 않는다. v1 은 플랫폼 기본색을 쓴다.
10
+ */
11
+ export declare const controlBase = "w-full bg-surface text-fg border border-border";
12
+ /**
13
+ * 한 줄 입력. `label` 은 `accessibilityLabel` 로만 간다 — 가시 라벨은 Label 조합이다(C-13).
14
+ * `id` 를 주면 같은 `htmlFor` 의 Label 과 `accessibilityLabelledBy` 로 이어진다(Android 전용).
6
15
  * 값 제어는 `value` / `defaultValue` / `onValueChange` 3종뿐이다(C-12).
7
16
  * RN 의 `onChangeText` 가 이미 값을 주므로 어댑터가 이벤트를 벗길 일이 없다.
8
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAA0B,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAKhC,KAAK,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;AA0C/C;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CA0ChC,CAAC"}
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAa,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,KAAK,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;AA4B/C,iEAAiE;AACjE,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAIlD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,mDAAmD,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CA2ChC,CAAC"}
package/dist/input.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { TextInput } from "react-native-css/components";
3
3
  import { cn } from "./cn.js";
4
+ import { labelNativeId } from "./label.js";
4
5
  /**
5
6
  * `kind` → RN `TextInput` 속성 매핑(C-11). 계약은 열거형 4값뿐이고 이 표는 어댑터 구현 세부다.
6
7
  * 자동완성은 `new-password` 를 구분하지 않는다(알려진 동작 8).
@@ -21,7 +22,7 @@ const kinds = {
21
22
  number: { keyboardType: "numeric" },
22
23
  };
23
24
  /** 웹 Input 과 같은 크기 클래스다(AC-25). 웹의 `text-*` 는 여기서도 같은 스텝을 쓴다. */
24
- const sizes = {
25
+ export const inputSizes = {
25
26
  sm: "px-3 py-1 text-sm rounded-md",
26
27
  md: "px-3 py-2 text-md rounded-md",
27
28
  lg: "px-4 py-3 text-lg rounded-md",
@@ -31,9 +32,10 @@ const sizes = {
31
32
  * 웹에는 있는 `placeholder:text-fg-muted` 가 빠져 있다 — react-native-css 는
32
33
  * `placeholder:` 변형을 `placeholderTextColor` 로 옮기지 않는다. v1 은 플랫폼 기본색을 쓴다.
33
34
  */
34
- const base = "w-full bg-surface text-fg border border-border";
35
+ export const controlBase = "w-full bg-surface text-fg border border-border";
35
36
  /**
36
- * 한 줄 입력. `label` 은 `accessibilityLabel` 로만 간다 — 가시 라벨은 v2 의 Label 조합이다(C-13).
37
+ * 한 줄 입력. `label` 은 `accessibilityLabel` 로만 간다 — 가시 라벨은 Label 조합이다(C-13).
38
+ * `id` 를 주면 같은 `htmlFor` 의 Label 과 `accessibilityLabelledBy` 로 이어진다(Android 전용).
37
39
  * 값 제어는 `value` / `defaultValue` / `onValueChange` 3종뿐이다(C-12).
38
40
  * RN 의 `onChangeText` 가 이미 값을 주므로 어댑터가 이벤트를 벗길 일이 없다.
39
41
  *
@@ -44,9 +46,9 @@ const base = "w-full bg-surface text-fg border border-border";
44
46
  */
45
47
  export const Input = ({ label, kind = "text", size = "md", id, placeholder, disabled = false, invalid = false, value, defaultValue, onValueChange, className, ref, }) => {
46
48
  const attributes = kinds[kind];
47
- return (_jsx(TextInput, { ref: ref, id: id, accessibilityLabel: label, placeholder: placeholder, editable: !disabled, value: value, defaultValue: defaultValue, onChangeText: onValueChange,
49
+ return (_jsx(TextInput, { ref: ref, id: id, accessibilityLabel: label, accessibilityLabelledBy: id ? labelNativeId(id) : undefined, placeholder: placeholder, editable: !disabled, value: value, defaultValue: defaultValue, onChangeText: onValueChange,
48
50
  // kind 파생 속성은 하나씩 넘긴다. 스프레드로 넘기면 계약에 없는 prop 이 섞여도
49
51
  // 타입이 잡아주지 못하고, 웹 Input 과 읽는 방식도 갈린다(AC-11a 취지).
50
- secureTextEntry: attributes.secureTextEntry, keyboardType: attributes.keyboardType, autoCapitalize: attributes.autoCapitalize, autoComplete: attributes.autoComplete, textContentType: attributes.textContentType, className: cn(base, sizes[size], invalid && "border-danger", disabled && "opacity-50", className) }));
52
+ secureTextEntry: attributes.secureTextEntry, keyboardType: attributes.keyboardType, autoCapitalize: attributes.autoCapitalize, autoComplete: attributes.autoComplete, textContentType: attributes.textContentType, className: cn(controlBase, inputSizes[size], invalid && "border-danger", disabled && "opacity-50", className) }));
51
53
  };
52
54
  //# sourceMappingURL=input.js.map
package/dist/input.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAI7B;;;GAGG;AACH,MAAM,KAAK,GAMP;IACF,IAAI,EAAE,EAAE;IACR,QAAQ,EAAE;QACR,eAAe,EAAE,IAAI;QACrB,YAAY,EAAE,UAAU;QACxB,eAAe,EAAE,UAAU;KAC5B;IACD,KAAK,EAAE;QACL,YAAY,EAAE,eAAe;QAC7B,cAAc,EAAE,MAAM;QACtB,YAAY,EAAE,OAAO;QACrB,eAAe,EAAE,cAAc;KAChC;IACD,MAAM,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE;CACpC,CAAC;AAEF,iEAAiE;AACjE,MAAM,KAAK,GAAgC;IACzC,EAAE,EAAE,8BAA8B;IAClC,EAAE,EAAE,8BAA8B;IAClC,EAAE,EAAE,8BAA8B;CACnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,IAAI,GAAG,gDAAgD,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAmB,CAAC,EACpC,KAAK,EACL,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,IAAI,EACX,EAAE,EACF,WAAW,EACX,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,KAAK,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,GAAG,GACJ,EAAE,EAAE;IACH,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,CACL,KAAC,SAAS,IACR,GAAG,EAAE,GAAoC,EACzC,EAAE,EAAE,EAAE,EACN,kBAAkB,EAAE,KAAK,EACzB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,QAAQ,EACnB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,aAAa;QAC3B,mDAAmD;QACnD,iDAAiD;QACjD,eAAe,EAAE,UAAU,CAAC,eAAe,EAC3C,YAAY,EAAE,UAAU,CAAC,YAAY,EACrC,cAAc,EAAE,UAAU,CAAC,cAAc,EACzC,YAAY,EAAE,UAAU,CAAC,YAAY,EACrC,eAAe,EAAE,UAAU,CAAC,eAAe,EAC3C,SAAS,EAAE,EAAE,CACX,IAAI,EACJ,KAAK,CAAC,IAAI,CAAC,EACX,OAAO,IAAI,eAAe,EAC1B,QAAQ,IAAI,YAAY,EACxB,SAAS,CACV,GACD,CACH,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI3C;;;GAGG;AACH,MAAM,KAAK,GAMP;IACF,IAAI,EAAE,EAAE;IACR,QAAQ,EAAE;QACR,eAAe,EAAE,IAAI;QACrB,YAAY,EAAE,UAAU;QACxB,eAAe,EAAE,UAAU;KAC5B;IACD,KAAK,EAAE;QACL,YAAY,EAAE,eAAe;QAC7B,cAAc,EAAE,MAAM;QACtB,YAAY,EAAE,OAAO;QACrB,eAAe,EAAE,cAAc;KAChC;IACD,MAAM,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE;CACpC,CAAC;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,UAAU,GAAgC;IACrD,EAAE,EAAE,8BAA8B;IAClC,EAAE,EAAE,8BAA8B;IAClC,EAAE,EAAE,8BAA8B;CACnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,gDAAgD,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,KAAK,GAAmB,CAAC,EACpC,KAAK,EACL,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,IAAI,EACX,EAAE,EACF,WAAW,EACX,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,KAAK,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,GAAG,GACJ,EAAE,EAAE;IACH,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,CACL,KAAC,SAAS,IACR,GAAG,EAAE,GAAoC,EACzC,EAAE,EAAE,EAAE,EACN,kBAAkB,EAAE,KAAK,EACzB,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAC3D,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,QAAQ,EACnB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,aAAa;QAC3B,mDAAmD;QACnD,iDAAiD;QACjD,eAAe,EAAE,UAAU,CAAC,eAAe,EAC3C,YAAY,EAAE,UAAU,CAAC,YAAY,EACrC,cAAc,EAAE,UAAU,CAAC,cAAc,EACzC,YAAY,EAAE,UAAU,CAAC,YAAY,EACrC,eAAe,EAAE,UAAU,CAAC,eAAe,EAC3C,SAAS,EAAE,EAAE,CACX,WAAW,EACX,UAAU,CAAC,IAAI,CAAC,EAChB,OAAO,IAAI,eAAe,EAC1B,QAAQ,IAAI,YAAY,EACxB,SAAS,CACV,GACD,CACH,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Contracts } from "@eeennsu/tokens";
2
+ import type { FC } from "react";
3
+ /**
4
+ * 컨트롤 `id` → 그 컨트롤을 가리키는 Label 의 `nativeID`.
5
+ * 컨트롤이 자기 `id` 를 `nativeID` 로 이미 쓰므로 Label 은 접미어를 붙인 다른 이름을 갖는다 —
6
+ * 같은 `nativeID` 가 둘이면 `accessibilityLabelledBy` 가 어느 쪽을 가리킬지 정해지지 않는다.
7
+ */
8
+ export declare const labelNativeId: (id: string) => string;
9
+ /**
10
+ * Input · Textarea 의 가시 라벨. 웹 Label 과 같은 클래스다(AC-25).
11
+ *
12
+ * 웹의 `<label htmlFor>` 연결을 RN 은 `nativeID` / `accessibilityLabelledBy` 로 옮긴다(C-13) —
13
+ * Label 이 `nativeID` 를 갖고, 같은 `id` 의 컨트롤이 그것을 `accessibilityLabelledBy` 로 가리킨다.
14
+ * Android 전용 속성이고 iOS 는 컨트롤의 `accessibilityLabel`(필수 `label`)만 읽는다.
15
+ * 웹처럼 라벨을 눌러 컨트롤에 포커스하는 동작은 없다(구현 노트 N-16).
16
+ */
17
+ export declare const Label: FC<Contracts<"native">["Label"]>;
18
+ //# sourceMappingURL=label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../src/label.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,IAAI,MAAM,KAAG,MAAuB,CAAC;AAEnE;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAOlD,CAAC"}
package/dist/label.js ADDED
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text as RNText } from "react-native-css/components";
3
+ import { cn } from "./cn.js";
4
+ /**
5
+ * 컨트롤 `id` → 그 컨트롤을 가리키는 Label 의 `nativeID`.
6
+ * 컨트롤이 자기 `id` 를 `nativeID` 로 이미 쓰므로 Label 은 접미어를 붙인 다른 이름을 갖는다 —
7
+ * 같은 `nativeID` 가 둘이면 `accessibilityLabelledBy` 가 어느 쪽을 가리킬지 정해지지 않는다.
8
+ */
9
+ export const labelNativeId = (id) => id + "-label";
10
+ /**
11
+ * Input · Textarea 의 가시 라벨. 웹 Label 과 같은 클래스다(AC-25).
12
+ *
13
+ * 웹의 `<label htmlFor>` 연결을 RN 은 `nativeID` / `accessibilityLabelledBy` 로 옮긴다(C-13) —
14
+ * Label 이 `nativeID` 를 갖고, 같은 `id` 의 컨트롤이 그것을 `accessibilityLabelledBy` 로 가리킨다.
15
+ * Android 전용 속성이고 iOS 는 컨트롤의 `accessibilityLabel`(필수 `label`)만 읽는다.
16
+ * 웹처럼 라벨을 눌러 컨트롤에 포커스하는 동작은 없다(구현 노트 N-16).
17
+ */
18
+ export const Label = ({ children, htmlFor, className }) => (_jsx(RNText, { nativeID: htmlFor ? labelNativeId(htmlFor) : undefined, className: cn("text-sm text-fg", className), children: children }));
19
+ //# sourceMappingURL=label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.js","sourceRoot":"","sources":["../src/label.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC;AAEnE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAqC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAC3F,KAAC,MAAM,IACL,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,EACtD,SAAS,EAAE,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,YAE1C,QAAQ,GACF,CACV,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type Contracts } from "@eeennsu/tokens";
2
+ import type { FC } from "react";
3
+ type TextareaProps = Contracts<"native">["Textarea"];
4
+ /**
5
+ * 여러 줄 입력. `size` 는 글자 크기가 아니라 **행수**로 해석한다 — 3 / 5 / 8 (plan D-14).
6
+ * 패딩과 글자 크기는 Input `md` 로 고정한다. 웹 `rows` 는 RN `numberOfLines` 로 간다.
7
+ *
8
+ * `textAlignVertical="top"` 이 없으면 Android 가 여러 줄 입력의 글자를 세로 가운데에 놓는다.
9
+ * 웹 textarea 는 위에서 시작하므로 맞춘다.
10
+ *
11
+ * `invalid` 는 Input 과 같이 테두리 색까지만 간다 — RN 에 `aria-invalid` 가 없다(구현 노트 F-16).
12
+ */
13
+ export declare const Textarea: FC<TextareaProps>;
14
+ export {};
15
+ //# sourceMappingURL=textarea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../src/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,KAAK,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CAkCtC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { component } from "@eeennsu/tokens";
3
+ import { TextInput } from "react-native-css/components";
4
+ import { cn } from "./cn.js";
5
+ import { controlBase, inputSizes } from "./input.js";
6
+ import { labelNativeId } from "./label.js";
7
+ /**
8
+ * 여러 줄 입력. `size` 는 글자 크기가 아니라 **행수**로 해석한다 — 3 / 5 / 8 (plan D-14).
9
+ * 패딩과 글자 크기는 Input `md` 로 고정한다. 웹 `rows` 는 RN `numberOfLines` 로 간다.
10
+ *
11
+ * `textAlignVertical="top"` 이 없으면 Android 가 여러 줄 입력의 글자를 세로 가운데에 놓는다.
12
+ * 웹 textarea 는 위에서 시작하므로 맞춘다.
13
+ *
14
+ * `invalid` 는 Input 과 같이 테두리 색까지만 간다 — RN 에 `aria-invalid` 가 없다(구현 노트 F-16).
15
+ */
16
+ export const Textarea = ({ label, size = "md", id, placeholder, disabled = false, invalid = false, value, defaultValue, onValueChange, className, ref, }) => (_jsx(TextInput, { ref: ref, id: id, multiline: true, numberOfLines: component.textarea.rows[size], textAlignVertical: "top", accessibilityLabel: label, accessibilityLabelledBy: id ? labelNativeId(id) : undefined, placeholder: placeholder, editable: !disabled, value: value, defaultValue: defaultValue, onChangeText: onValueChange, className: cn(controlBase, inputSizes.md, invalid && "border-danger", disabled && "opacity-50", className) }));
17
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.js","sourceRoot":"","sources":["../src/textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI3C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAsB,CAAC,EAC1C,KAAK,EACL,IAAI,GAAG,IAAI,EACX,EAAE,EACF,WAAW,EACX,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,KAAK,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,GAAG,GACJ,EAAE,EAAE,CAAC,CACJ,KAAC,SAAS,IACR,GAAG,EAAE,GAAuC,EAC5C,EAAE,EAAE,EAAE,EACN,SAAS,QACT,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAC5C,iBAAiB,EAAC,KAAK,EACvB,kBAAkB,EAAE,KAAK,EACzB,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAC3D,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,QAAQ,EACnB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,aAAa,EAC3B,SAAS,EAAE,EAAE,CACX,WAAW,EACX,UAAU,CAAC,EAAE,EACb,OAAO,IAAI,eAAe,EAC1B,QAAQ,IAAI,YAAY,EACxB,SAAS,CACV,GACD,CACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeennsu/native",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "React Native(Expo + NativeWind v5) 디자인 시스템 컴포넌트",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "lucide-react-native": "1.41.0",
23
23
  "tailwind-merge": "^3.6.0",
24
- "@eeennsu/tokens": "0.1.0"
24
+ "@eeennsu/tokens": "0.2.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "nativewind": "5.0.0-preview.4",