@ecohouse/ui 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/index.cjs +1266 -109
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +188 -12
  4. package/dist/index.d.ts +188 -12
  5. package/dist/index.js +1260 -112
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/components/Button/Button.tsx +106 -88
  9. package/src/components/Checkbox/Checkbox.stories.tsx +112 -0
  10. package/src/components/Checkbox/Checkbox.tsx +150 -0
  11. package/src/components/Checkbox/index.ts +2 -0
  12. package/src/components/Input/Input.stories.tsx +11 -40
  13. package/src/components/Input/Input.tsx +58 -54
  14. package/src/components/Input/index.ts +1 -1
  15. package/src/components/Select/Select.stories.tsx +196 -0
  16. package/src/components/Select/Select.tsx +851 -0
  17. package/src/components/Select/index.ts +2 -0
  18. package/src/components/Textarea/Textarea.stories.tsx +71 -0
  19. package/src/components/Textarea/Textarea.tsx +241 -0
  20. package/src/components/Textarea/index.ts +2 -0
  21. package/src/components/Toggle/Toggle.stories.tsx +100 -0
  22. package/src/components/Toggle/Toggle.tsx +176 -0
  23. package/src/components/Toggle/index.ts +2 -0
  24. package/src/components/index.ts +13 -1
  25. package/src/icons/Check/CheckIcon.tsx +26 -0
  26. package/src/icons/Check/CheckIcon.web.tsx +32 -0
  27. package/src/icons/Check/checkPath.ts +2 -0
  28. package/src/icons/Check/index.ts +1 -0
  29. package/src/icons/ChevronDown/ChevronDownIcon.tsx +30 -0
  30. package/src/icons/ChevronDown/ChevronDownIcon.web.tsx +36 -0
  31. package/src/icons/ChevronDown/chevronDownPath.ts +2 -0
  32. package/src/icons/ChevronDown/index.ts +1 -0
  33. package/src/icons/Search/SearchIcon.tsx +37 -0
  34. package/src/icons/Search/SearchIcon.web.tsx +43 -0
  35. package/src/icons/Search/index.ts +1 -0
  36. package/src/icons/Search/searchPath.ts +5 -0
  37. package/src/icons/index.ts +3 -0
  38. package/src/icons/registry.ts +8 -2
  39. package/src/index.ts +21 -3
  40. package/src/theme/index.ts +7 -1
  41. package/src/theme/typography.ts +52 -2
  42. package/src/utils/mergeRefs.ts +20 -0
@@ -0,0 +1,30 @@
1
+ import Svg, { Path } from "react-native-svg";
2
+ import { CHEVRON_DOWN_PATH } from "./chevronDownPath";
3
+ import { colors } from "../../theme";
4
+
5
+ export { CHEVRON_DOWN_PATH } from "./chevronDownPath";
6
+
7
+ interface ChevronDownIconProps {
8
+ size?: number;
9
+ color?: string;
10
+ strokeWidth?: number;
11
+ }
12
+
13
+ /** Native — react-native-svg (peer dependency). */
14
+ export function ChevronDownIcon({
15
+ size = 20,
16
+ color = colors.primary,
17
+ strokeWidth = 2,
18
+ }: ChevronDownIconProps) {
19
+ return (
20
+ <Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
21
+ <Path
22
+ d={CHEVRON_DOWN_PATH}
23
+ stroke={color}
24
+ strokeWidth={strokeWidth}
25
+ strokeLinecap="round"
26
+ strokeLinejoin="round"
27
+ />
28
+ </Svg>
29
+ );
30
+ }
@@ -0,0 +1,36 @@
1
+ import { CHEVRON_DOWN_PATH } from "./chevronDownPath";
2
+ import { colors } from "../../theme";
3
+
4
+ interface ChevronDownIconProps {
5
+ size?: number;
6
+ color?: string;
7
+ strokeWidth?: number;
8
+ }
9
+
10
+ /** Web / Storybook — plain SVG (no react-native-svg). */
11
+ export function ChevronDownIcon({
12
+ size = 20,
13
+ color = colors.primary,
14
+ strokeWidth = 2,
15
+ }: ChevronDownIconProps) {
16
+ return (
17
+ <svg
18
+ width={size}
19
+ height={size}
20
+ viewBox="0 0 20 20"
21
+ fill="none"
22
+ xmlns="http://www.w3.org/2000/svg"
23
+ aria-hidden
24
+ >
25
+ <path
26
+ d={CHEVRON_DOWN_PATH}
27
+ stroke={color}
28
+ strokeWidth={strokeWidth}
29
+ strokeLinecap="round"
30
+ strokeLinejoin="round"
31
+ />
32
+ </svg>
33
+ );
34
+ }
35
+
36
+ export { CHEVRON_DOWN_PATH } from "./chevronDownPath";
@@ -0,0 +1,2 @@
1
+ /** Chevron down path — 20×20 viewBox. */
2
+ export const CHEVRON_DOWN_PATH = "M5 7.5L10 12.5L15 7.5";
@@ -0,0 +1 @@
1
+ export { ChevronDownIcon, CHEVRON_DOWN_PATH } from "./ChevronDownIcon";
@@ -0,0 +1,37 @@
1
+ import Svg, { Path } from "react-native-svg";
2
+ import { SEARCH_CIRCLE_PATH, SEARCH_HANDLE_PATH } from "./searchPath";
3
+ import { colors } from "../../theme";
4
+
5
+ export { SEARCH_CIRCLE_PATH, SEARCH_HANDLE_PATH } from "./searchPath";
6
+
7
+ interface SearchIconProps {
8
+ size?: number;
9
+ color?: string;
10
+ strokeWidth?: number;
11
+ }
12
+
13
+ /** Native — react-native-svg (peer dependency). */
14
+ export function SearchIcon({
15
+ size = 20,
16
+ color = colors.primary,
17
+ strokeWidth = 2,
18
+ }: SearchIconProps) {
19
+ return (
20
+ <Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
21
+ <Path
22
+ d={SEARCH_CIRCLE_PATH}
23
+ stroke={color}
24
+ strokeWidth={strokeWidth}
25
+ strokeLinecap="round"
26
+ strokeLinejoin="round"
27
+ />
28
+ <Path
29
+ d={SEARCH_HANDLE_PATH}
30
+ stroke={color}
31
+ strokeWidth={strokeWidth}
32
+ strokeLinecap="round"
33
+ strokeLinejoin="round"
34
+ />
35
+ </Svg>
36
+ );
37
+ }
@@ -0,0 +1,43 @@
1
+ import { SEARCH_CIRCLE_PATH, SEARCH_HANDLE_PATH } from "./searchPath";
2
+ import { colors } from "../../theme";
3
+
4
+ interface SearchIconProps {
5
+ size?: number;
6
+ color?: string;
7
+ strokeWidth?: number;
8
+ }
9
+
10
+ /** Web / Storybook — plain SVG (no react-native-svg). */
11
+ export function SearchIcon({
12
+ size = 20,
13
+ color = colors.primary,
14
+ strokeWidth = 2,
15
+ }: SearchIconProps) {
16
+ return (
17
+ <svg
18
+ width={size}
19
+ height={size}
20
+ viewBox="0 0 20 20"
21
+ fill="none"
22
+ xmlns="http://www.w3.org/2000/svg"
23
+ aria-hidden
24
+ >
25
+ <path
26
+ d={SEARCH_CIRCLE_PATH}
27
+ stroke={color}
28
+ strokeWidth={strokeWidth}
29
+ strokeLinecap="round"
30
+ strokeLinejoin="round"
31
+ />
32
+ <path
33
+ d={SEARCH_HANDLE_PATH}
34
+ stroke={color}
35
+ strokeWidth={strokeWidth}
36
+ strokeLinecap="round"
37
+ strokeLinejoin="round"
38
+ />
39
+ </svg>
40
+ );
41
+ }
42
+
43
+ export { SEARCH_CIRCLE_PATH, SEARCH_HANDLE_PATH } from "./searchPath";
@@ -0,0 +1 @@
1
+ export { SearchIcon, SEARCH_CIRCLE_PATH, SEARCH_HANDLE_PATH } from "./SearchIcon";
@@ -0,0 +1,5 @@
1
+ /** Search (magnifying glass) paths — 20×20 viewBox. */
2
+ export const SEARCH_CIRCLE_PATH =
3
+ "M9.16667 15.8333C12.8486 15.8333 15.8333 12.8486 15.8333 9.16667C15.8333 5.48477 12.8486 2.5 9.16667 2.5C5.48477 2.5 2.5 5.48477 2.5 9.16667C2.5 12.8486 5.48477 15.8333 9.16667 15.8333Z";
4
+
5
+ export const SEARCH_HANDLE_PATH = "M17.5 17.5L13.875 13.875";
@@ -10,7 +10,9 @@ export { BagIcon } from "./Bag";
10
10
  export { BellIcon } from "./Bell";
11
11
  export { BuildingIcon } from "./Building";
12
12
  export { CameraIcon } from "./Camera";
13
+ export { CheckIcon } from "./Check";
13
14
  export { CheckBadgeIcon } from "./CheckBadge";
15
+ export { ChevronDownIcon } from "./ChevronDown";
14
16
  export { ClockIcon } from "./Clock";
15
17
  export { FacebookIcon } from "./Facebook";
16
18
  export { HomeIcon } from "./Home";
@@ -20,5 +22,6 @@ export { LinkedInIcon } from "./LinkedIn";
20
22
  export { MailIcon } from "./Mail";
21
23
  export { NavigateIcon } from "./Navigate";
22
24
  export { PhoneIcon } from "./Phone";
25
+ export { SearchIcon } from "./Search";
23
26
  export { ShowIcon } from "./Show";
24
27
  export { UserIcon } from "./User";
@@ -3,7 +3,9 @@ import { BagIcon } from "./Bag";
3
3
  import { BellIcon } from "./Bell";
4
4
  import { BuildingIcon } from "./Building";
5
5
  import { CameraIcon } from "./Camera";
6
+ import { CheckIcon } from "./Check";
6
7
  import { CheckBadgeIcon } from "./CheckBadge";
8
+ import { ChevronDownIcon } from "./ChevronDown";
7
9
  import { ClockIcon } from "./Clock";
8
10
  import { FacebookIcon } from "./Facebook";
9
11
  import { HomeIcon } from "./Home";
@@ -13,6 +15,7 @@ import { LinkedInIcon } from "./LinkedIn";
13
15
  import { MailIcon } from "./Mail";
14
16
  import { NavigateIcon } from "./Navigate";
15
17
  import { PhoneIcon } from "./Phone";
18
+ import { SearchIcon } from "./Search";
16
19
  import { ShowIcon } from "./Show";
17
20
  import { UserIcon } from "./User";
18
21
  import type { IconComponent } from "./types";
@@ -23,7 +26,9 @@ export const icons = {
23
26
  bell: BellIcon,
24
27
  building: BuildingIcon,
25
28
  camera: CameraIcon,
29
+ check: CheckIcon,
26
30
  checkBadge: CheckBadgeIcon,
31
+ chevronDown: ChevronDownIcon,
27
32
  clock: ClockIcon,
28
33
  facebook: FacebookIcon,
29
34
  home: HomeIcon,
@@ -33,6 +38,7 @@ export const icons = {
33
38
  mail: MailIcon,
34
39
  navigate: NavigateIcon,
35
40
  phone: PhoneIcon,
41
+ search: SearchIcon,
36
42
  show: ShowIcon,
37
43
  user: UserIcon,
38
44
  } as const satisfies Record<string, IconComponent>;
@@ -42,8 +48,8 @@ export type IconName = keyof typeof icons;
42
48
  export const iconNames = Object.keys(icons) as IconName[];
43
49
 
44
50
  export const iconGroups = {
45
- navigation: ["arrowRight", "home", "navigate"],
46
- actions: ["show", "bell", "camera", "key", "checkBadge"],
51
+ navigation: ["arrowRight", "chevronDown", "home", "navigate"],
52
+ actions: ["show", "bell", "camera", "key", "check", "checkBadge", "search"],
47
53
  objects: ["bag", "building", "clock", "user"],
48
54
  communication: ["mail", "phone"],
49
55
  social: ["facebook", "instagram", "linkedin"],
package/src/index.ts CHANGED
@@ -1,11 +1,18 @@
1
- export { Button, Input } from "./components";
1
+ export { Button, Checkbox, Input, Select, Textarea, Toggle } from "./components";
2
2
  export type {
3
3
  ButtonProps,
4
4
  ButtonSize,
5
5
  ButtonVariant,
6
+ CheckboxProps,
7
+ CheckboxVariant,
6
8
  InputProps,
7
9
  InputSize,
8
- InputState,
10
+ SelectOption,
11
+ SelectProps,
12
+ SelectSingleProps,
13
+ SelectMultipleProps,
14
+ TextareaProps,
15
+ ToggleProps,
9
16
  } from "./components";
10
17
 
11
18
  export {
@@ -20,7 +27,9 @@ export {
20
27
  BellIcon,
21
28
  BuildingIcon,
22
29
  CameraIcon,
30
+ CheckIcon,
23
31
  CheckBadgeIcon,
32
+ ChevronDownIcon,
24
33
  ClockIcon,
25
34
  FacebookIcon,
26
35
  HomeIcon,
@@ -30,10 +39,19 @@ export {
30
39
  MailIcon,
31
40
  NavigateIcon,
32
41
  PhoneIcon,
42
+ SearchIcon,
33
43
  ShowIcon,
34
44
  UserIcon,
35
45
  } from "./icons";
36
46
  export type { IconProps, IconName, IconGroup, IconComponent, IconByNameProps } from "./icons";
37
47
 
38
- export { colors, grey, buttonTypography, inputTypography, fonts } from "./theme";
48
+ export {
49
+ colors,
50
+ grey,
51
+ buttonTypography,
52
+ inputTypography,
53
+ selectTypography,
54
+ textareaTypography,
55
+ fonts,
56
+ } from "./theme";
39
57
  export type { GreyStep } from "./theme";
@@ -1,4 +1,10 @@
1
1
  export { colors, grey } from "./colors";
2
2
  export type { GreyStep } from "./colors";
3
3
 
4
- export { fonts, buttonTypography, inputTypography } from "./typography";
4
+ export {
5
+ fonts,
6
+ buttonTypography,
7
+ inputTypography,
8
+ selectTypography,
9
+ textareaTypography,
10
+ } from "./typography";
@@ -26,9 +26,34 @@ export const inputTypography = {
26
26
  fontFamily: fonts.sans,
27
27
  fontSize: 12,
28
28
  fontWeight: "500" as const,
29
- lineHeight: 16,
29
+ lineHeight: 12,
30
+ letterSpacing: 0.36,
31
+ },
32
+ field: {
33
+ fontFamily: fonts.sans,
34
+ fontSize: 14,
35
+ fontWeight: "400" as const,
36
+ lineHeight: 19,
30
37
  letterSpacing: 0,
31
38
  },
39
+ hint: {
40
+ fontFamily: fonts.sans,
41
+ fontSize: 12,
42
+ fontWeight: "400" as const,
43
+ lineHeight: 12,
44
+ letterSpacing: 0.36,
45
+ },
46
+ } as const;
47
+
48
+ /** Select label / field / hint typography — Medium/Regular 12–14, letter-spacing 3%. */
49
+ export const selectTypography = {
50
+ label: {
51
+ fontFamily: fonts.sans,
52
+ fontSize: 12,
53
+ fontWeight: "500" as const,
54
+ lineHeight: 12,
55
+ letterSpacing: 0.36,
56
+ },
32
57
  field: {
33
58
  fontFamily: fonts.sans,
34
59
  fontSize: 14,
@@ -40,7 +65,32 @@ export const inputTypography = {
40
65
  fontFamily: fonts.sans,
41
66
  fontSize: 12,
42
67
  fontWeight: "400" as const,
43
- lineHeight: 16,
68
+ lineHeight: 12,
69
+ letterSpacing: 0.36,
70
+ },
71
+ } as const;
72
+
73
+ /** Textarea label / field / hint typography — Medium/Regular 12–14, letter-spacing 3%. */
74
+ export const textareaTypography = {
75
+ label: {
76
+ fontFamily: fonts.sans,
77
+ fontSize: 12,
78
+ fontWeight: "500" as const,
79
+ lineHeight: 12,
80
+ letterSpacing: 0.36,
81
+ },
82
+ field: {
83
+ fontFamily: fonts.sans,
84
+ fontSize: 14,
85
+ fontWeight: "400" as const,
86
+ lineHeight: 19,
44
87
  letterSpacing: 0,
45
88
  },
89
+ hint: {
90
+ fontFamily: fonts.sans,
91
+ fontSize: 12,
92
+ fontWeight: "400" as const,
93
+ lineHeight: 12,
94
+ letterSpacing: 0.36,
95
+ },
46
96
  } as const;
@@ -0,0 +1,20 @@
1
+ import type { ForwardedRef, MutableRefObject, RefCallback } from "react";
2
+
3
+ /**
4
+ * Combines a component's internal ref (used e.g. by `useApplyWebClassName`)
5
+ * with an optional externally-forwarded ref, so consumers can still call
6
+ * `.focus()`/`.measure()` on the underlying native node via `ref`.
7
+ */
8
+ export function mergeRefs<T>(
9
+ internalRef: MutableRefObject<T | null>,
10
+ forwardedRef: ForwardedRef<T>,
11
+ ): RefCallback<T> {
12
+ return (node) => {
13
+ internalRef.current = node;
14
+ if (typeof forwardedRef === "function") {
15
+ forwardedRef(node);
16
+ } else if (forwardedRef) {
17
+ forwardedRef.current = node;
18
+ }
19
+ };
20
+ }