@tonyarbor/components 0.1.0 → 0.2.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.
Files changed (126) hide show
  1. package/dist/Banner.d.mts +59 -0
  2. package/dist/Banner.d.ts +59 -0
  3. package/dist/Banner.js +222 -0
  4. package/dist/Banner.js.map +1 -0
  5. package/dist/Banner.mjs +7 -0
  6. package/dist/Banner.mjs.map +1 -0
  7. package/dist/Checkbox.d.mts +52 -0
  8. package/dist/Checkbox.d.ts +52 -0
  9. package/dist/Checkbox.js +194 -0
  10. package/dist/Checkbox.js.map +1 -0
  11. package/dist/Checkbox.mjs +7 -0
  12. package/dist/Checkbox.mjs.map +1 -0
  13. package/dist/Combobox.d.mts +67 -0
  14. package/dist/Combobox.d.ts +67 -0
  15. package/dist/Combobox.js +329 -0
  16. package/dist/Combobox.js.map +1 -0
  17. package/dist/Combobox.mjs +7 -0
  18. package/dist/Combobox.mjs.map +1 -0
  19. package/dist/DatePicker.d.mts +68 -0
  20. package/dist/DatePicker.d.ts +68 -0
  21. package/dist/DatePicker.js +490 -0
  22. package/dist/DatePicker.js.map +1 -0
  23. package/dist/DatePicker.mjs +7 -0
  24. package/dist/DatePicker.mjs.map +1 -0
  25. package/dist/NumericInput.d.mts +68 -0
  26. package/dist/NumericInput.d.ts +68 -0
  27. package/dist/NumericInput.js +319 -0
  28. package/dist/NumericInput.js.map +1 -0
  29. package/dist/NumericInput.mjs +7 -0
  30. package/dist/NumericInput.mjs.map +1 -0
  31. package/dist/Pagination.d.mts +36 -0
  32. package/dist/Pagination.d.ts +36 -0
  33. package/dist/Pagination.js +301 -0
  34. package/dist/Pagination.js.map +1 -0
  35. package/dist/Pagination.mjs +7 -0
  36. package/dist/Pagination.mjs.map +1 -0
  37. package/dist/Radio.d.mts +48 -0
  38. package/dist/Radio.d.ts +48 -0
  39. package/dist/Radio.js +194 -0
  40. package/dist/Radio.js.map +1 -0
  41. package/dist/Radio.mjs +7 -0
  42. package/dist/Radio.mjs.map +1 -0
  43. package/dist/Table.d.mts +80 -0
  44. package/dist/Table.d.ts +80 -0
  45. package/dist/Table.js +347 -0
  46. package/dist/Table.js.map +1 -0
  47. package/dist/Table.mjs +8 -0
  48. package/dist/Table.mjs.map +1 -0
  49. package/dist/TableControls.d.mts +76 -0
  50. package/dist/TableControls.d.ts +76 -0
  51. package/dist/TableControls.js +461 -0
  52. package/dist/TableControls.js.map +1 -0
  53. package/dist/TableControls.mjs +7 -0
  54. package/dist/TableControls.mjs.map +1 -0
  55. package/dist/TableFooterPagination.d.mts +56 -0
  56. package/dist/TableFooterPagination.d.ts +56 -0
  57. package/dist/TableFooterPagination.js +499 -0
  58. package/dist/TableFooterPagination.js.map +1 -0
  59. package/dist/TableFooterPagination.mjs +7 -0
  60. package/dist/TableFooterPagination.mjs.map +1 -0
  61. package/dist/Tabs.d.mts +50 -0
  62. package/dist/Tabs.d.ts +50 -0
  63. package/dist/Tabs.js +187 -0
  64. package/dist/Tabs.js.map +1 -0
  65. package/dist/Tabs.mjs +7 -0
  66. package/dist/Tabs.mjs.map +1 -0
  67. package/dist/TextArea.d.mts +64 -0
  68. package/dist/TextArea.d.ts +64 -0
  69. package/dist/TextArea.js +171 -0
  70. package/dist/TextArea.js.map +1 -0
  71. package/dist/TextArea.mjs +7 -0
  72. package/dist/TextArea.mjs.map +1 -0
  73. package/dist/Toast.d.mts +48 -0
  74. package/dist/Toast.d.ts +48 -0
  75. package/dist/Toast.js +169 -0
  76. package/dist/Toast.js.map +1 -0
  77. package/dist/Toast.mjs +7 -0
  78. package/dist/Toast.mjs.map +1 -0
  79. package/dist/Toggle.d.mts +48 -0
  80. package/dist/Toggle.d.ts +48 -0
  81. package/dist/Toggle.js +291 -0
  82. package/dist/Toggle.js.map +1 -0
  83. package/dist/Toggle.mjs +7 -0
  84. package/dist/Toggle.mjs.map +1 -0
  85. package/dist/Tooltip.d.mts +32 -0
  86. package/dist/Tooltip.d.ts +32 -0
  87. package/dist/Tooltip.js +109 -0
  88. package/dist/Tooltip.js.map +1 -0
  89. package/dist/Tooltip.mjs +7 -0
  90. package/dist/Tooltip.mjs.map +1 -0
  91. package/dist/chunk-52TG3BFX.mjs +463 -0
  92. package/dist/chunk-52TG3BFX.mjs.map +1 -0
  93. package/dist/chunk-5BUXFTPW.mjs +283 -0
  94. package/dist/chunk-5BUXFTPW.mjs.map +1 -0
  95. package/dist/chunk-7OWLBYNM.mjs +293 -0
  96. package/dist/chunk-7OWLBYNM.mjs.map +1 -0
  97. package/dist/chunk-AI2U34CF.mjs +159 -0
  98. package/dist/chunk-AI2U34CF.mjs.map +1 -0
  99. package/dist/chunk-C25FFMRQ.mjs +255 -0
  100. package/dist/chunk-C25FFMRQ.mjs.map +1 -0
  101. package/dist/chunk-CUTYEIFE.mjs +158 -0
  102. package/dist/chunk-CUTYEIFE.mjs.map +1 -0
  103. package/dist/chunk-DULH2KRW.mjs +133 -0
  104. package/dist/chunk-DULH2KRW.mjs.map +1 -0
  105. package/dist/chunk-G5NVKF2G.mjs +434 -0
  106. package/dist/chunk-G5NVKF2G.mjs.map +1 -0
  107. package/dist/chunk-M6DVBEEL.mjs +158 -0
  108. package/dist/chunk-M6DVBEEL.mjs.map +1 -0
  109. package/dist/chunk-MBUMR2XJ.mjs +135 -0
  110. package/dist/chunk-MBUMR2XJ.mjs.map +1 -0
  111. package/dist/chunk-MNH2TGUX.mjs +73 -0
  112. package/dist/chunk-MNH2TGUX.mjs.map +1 -0
  113. package/dist/chunk-RRMG2SSZ.mjs +265 -0
  114. package/dist/chunk-RRMG2SSZ.mjs.map +1 -0
  115. package/dist/chunk-U4JXKZZG.mjs +186 -0
  116. package/dist/chunk-U4JXKZZG.mjs.map +1 -0
  117. package/dist/chunk-W55QJIAN.mjs +467 -0
  118. package/dist/chunk-W55QJIAN.mjs.map +1 -0
  119. package/dist/chunk-YV4OXFIM.mjs +151 -0
  120. package/dist/chunk-YV4OXFIM.mjs.map +1 -0
  121. package/dist/index.d.mts +22 -1
  122. package/dist/index.d.ts +22 -1
  123. package/dist/index.js +3559 -2
  124. package/dist/index.js.map +1 -1
  125. package/dist/index.mjs +61 -1
  126. package/package.json +81 -3
@@ -0,0 +1,158 @@
1
+ // src/Radio/Radio.tsx
2
+ import * as React from "react";
3
+ import { clsx } from "clsx";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var radioStyles = {
6
+ width: "16px",
7
+ height: "16px",
8
+ border: "1px solid #7e7e7e",
9
+ // grey-500
10
+ borderRadius: "50%",
11
+ display: "flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ cursor: "pointer",
15
+ transition: "all 0.2s ease-in-out",
16
+ flexShrink: 0,
17
+ backgroundColor: "#ffffff"
18
+ };
19
+ var checkedStyles = {
20
+ border: "1px solid #0e8a0e"
21
+ // brand-600
22
+ };
23
+ var checkedHoverStyles = {
24
+ border: "1px solid #005700"
25
+ // brand-800
26
+ };
27
+ var uncheckedHoverStyles = {
28
+ border: "1px solid #2f2f2f"
29
+ // grey-900
30
+ };
31
+ var innerDotStyles = {
32
+ width: "10px",
33
+ height: "10px",
34
+ borderRadius: "50%",
35
+ backgroundColor: "#0e8a0e",
36
+ // brand-600
37
+ transition: "all 0.2s ease-in-out"
38
+ };
39
+ var innerDotHoverStyles = {
40
+ backgroundColor: "#005700"
41
+ // brand-800
42
+ };
43
+ var labelStyles = {
44
+ fontSize: "13px",
45
+ color: "#2f2f2f",
46
+ cursor: "pointer",
47
+ userSelect: "none",
48
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
49
+ };
50
+ var wrapperStyles = {
51
+ display: "flex",
52
+ alignItems: "center",
53
+ gap: "8px"
54
+ };
55
+ var Radio = React.forwardRef(
56
+ ({
57
+ label,
58
+ checked = false,
59
+ onChange,
60
+ disabled = false,
61
+ className,
62
+ style,
63
+ "data-testid": dataTestId,
64
+ name,
65
+ value
66
+ }, ref) => {
67
+ const [isFocused, setIsFocused] = React.useState(false);
68
+ const [isHovered, setIsHovered] = React.useState(false);
69
+ const radioId = React.useId();
70
+ const handleChange = (e) => {
71
+ if (!disabled) {
72
+ onChange?.(e.target.checked);
73
+ }
74
+ };
75
+ const circleStyle = {
76
+ ...radioStyles,
77
+ ...checked && !disabled && checkedStyles,
78
+ ...isHovered && !disabled && !checked && uncheckedHoverStyles,
79
+ ...isHovered && !disabled && checked && checkedHoverStyles,
80
+ ...disabled && !checked && { backgroundColor: "#efefef", border: "1px solid #7e7e7e" },
81
+ ...disabled && checked && { backgroundColor: "#efefef", border: "1px solid #7e7e7e" },
82
+ ...isFocused && !disabled && {
83
+ boxShadow: "0px 0px 0px 3px #3cad51"
84
+ }
85
+ };
86
+ const dotStyle = {
87
+ ...innerDotStyles,
88
+ ...isHovered && !disabled && innerDotHoverStyles,
89
+ ...disabled && { backgroundColor: "#7e7e7e" }
90
+ };
91
+ return /* @__PURE__ */ jsxs(
92
+ "div",
93
+ {
94
+ className: clsx("arbor-radio-wrapper", className),
95
+ style: { ...wrapperStyles, ...style },
96
+ "data-testid": dataTestId,
97
+ children: [
98
+ /* @__PURE__ */ jsx(
99
+ "input",
100
+ {
101
+ ref,
102
+ id: radioId,
103
+ type: "radio",
104
+ checked,
105
+ onChange: handleChange,
106
+ onFocus: () => setIsFocused(true),
107
+ onBlur: () => setIsFocused(false),
108
+ disabled,
109
+ name,
110
+ value,
111
+ style: {
112
+ position: "absolute",
113
+ opacity: 0,
114
+ width: 0,
115
+ height: 0
116
+ },
117
+ "aria-checked": checked
118
+ }
119
+ ),
120
+ /* @__PURE__ */ jsxs(
121
+ "label",
122
+ {
123
+ htmlFor: radioId,
124
+ onMouseEnter: () => !disabled && setIsHovered(true),
125
+ onMouseLeave: () => !disabled && setIsHovered(false),
126
+ style: {
127
+ display: "flex",
128
+ alignItems: "center",
129
+ gap: "8px",
130
+ cursor: disabled ? "not-allowed" : "pointer"
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ jsx("div", { style: circleStyle, children: checked && /* @__PURE__ */ jsx("div", { style: dotStyle }) }),
134
+ label && /* @__PURE__ */ jsx(
135
+ "span",
136
+ {
137
+ style: {
138
+ ...labelStyles,
139
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
140
+ cursor: disabled ? "not-allowed" : "pointer"
141
+ },
142
+ children: label
143
+ }
144
+ )
145
+ ]
146
+ }
147
+ )
148
+ ]
149
+ }
150
+ );
151
+ }
152
+ );
153
+ Radio.displayName = "Radio";
154
+
155
+ export {
156
+ Radio
157
+ };
158
+ //# sourceMappingURL=chunk-M6DVBEEL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Radio/Radio.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface RadioProps {\n /**\n * The label for the radio button\n */\n label?: string;\n /**\n * Whether the radio is selected\n */\n checked?: boolean;\n /**\n * Callback when selection changes\n */\n onChange?: (checked: boolean) => void;\n /**\n * Whether the radio is disabled\n */\n disabled?: boolean;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n /**\n * Name attribute for form submission (groups radios together)\n */\n name?: string;\n /**\n * Value attribute for form submission\n */\n value?: string;\n}\n\nconst radioStyles: React.CSSProperties = {\n width: '16px',\n height: '16px',\n border: '1px solid #7e7e7e', // grey-500\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n transition: 'all 0.2s ease-in-out',\n flexShrink: 0,\n backgroundColor: '#ffffff',\n};\n\nconst checkedStyles: React.CSSProperties = {\n border: '1px solid #0e8a0e', // brand-600\n};\n\nconst checkedHoverStyles: React.CSSProperties = {\n border: '1px solid #005700', // brand-800\n};\n\nconst uncheckedHoverStyles: React.CSSProperties = {\n border: '1px solid #2f2f2f', // grey-900\n};\n\nconst innerDotStyles: React.CSSProperties = {\n width: '10px',\n height: '10px',\n borderRadius: '50%',\n backgroundColor: '#0e8a0e', // brand-600\n transition: 'all 0.2s ease-in-out',\n};\n\nconst innerDotHoverStyles: React.CSSProperties = {\n backgroundColor: '#005700', // brand-800\n};\n\nconst labelStyles: React.CSSProperties = {\n fontSize: '13px',\n color: '#2f2f2f',\n cursor: 'pointer',\n userSelect: 'none' as const,\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n};\n\nconst wrapperStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n};\n\n/**\n * Radio component - Arbor Design System\n *\n * A radio button input with label support.\n */\nexport const Radio = React.forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n label,\n checked = false,\n onChange,\n disabled = false,\n className,\n style,\n 'data-testid': dataTestId,\n name,\n value,\n },\n ref\n ) => {\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const radioId = React.useId();\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!disabled) {\n onChange?.(e.target.checked);\n }\n };\n\n const circleStyle: React.CSSProperties = {\n ...radioStyles,\n ...(checked && !disabled && checkedStyles),\n ...(isHovered && !disabled && !checked && uncheckedHoverStyles),\n ...(isHovered && !disabled && checked && checkedHoverStyles),\n ...(disabled && !checked && { backgroundColor: '#efefef', border: '1px solid #7e7e7e' }),\n ...(disabled && checked && { backgroundColor: '#efefef', border: '1px solid #7e7e7e' }),\n ...(isFocused && !disabled && {\n boxShadow: '0px 0px 0px 3px #3cad51',\n }),\n };\n\n const dotStyle: React.CSSProperties = {\n ...innerDotStyles,\n ...(isHovered && !disabled && innerDotHoverStyles),\n ...(disabled && { backgroundColor: '#7e7e7e' }),\n };\n\n return (\n <div\n className={clsx('arbor-radio-wrapper', className)}\n style={{ ...wrapperStyles, ...style }}\n data-testid={dataTestId}\n >\n <input\n ref={ref}\n id={radioId}\n type=\"radio\"\n checked={checked}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n disabled={disabled}\n name={name}\n value={value}\n style={{\n position: 'absolute',\n opacity: 0,\n width: 0,\n height: 0,\n }}\n aria-checked={checked}\n />\n <label\n htmlFor={radioId}\n onMouseEnter={() => !disabled && setIsHovered(true)}\n onMouseLeave={() => !disabled && setIsHovered(false)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n cursor: disabled ? 'not-allowed' : 'pointer',\n }}\n >\n <div style={circleStyle}>\n {checked && <div style={dotStyle} />}\n </div>\n {label && (\n <span\n style={{\n ...labelStyles,\n color: disabled ? '#7e7e7e' : '#2f2f2f',\n cursor: disabled ? 'not-allowed' : 'pointer',\n }}\n >\n {label}\n </span>\n )}\n </label>\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n"],"mappings":"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","names":[]}
@@ -0,0 +1,135 @@
1
+ // src/TextArea/TextArea.tsx
2
+ import * as React from "react";
3
+ import { clsx } from "clsx";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var labelStyles = {
6
+ fontSize: "13px",
7
+ fontWeight: 600,
8
+ color: "#2f2f2f",
9
+ marginBottom: "0px",
10
+ display: "block",
11
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
12
+ };
13
+ var textareaWrapperStyles = {
14
+ position: "relative",
15
+ width: "100%"
16
+ };
17
+ var textareaStyles = {
18
+ width: "100%",
19
+ minHeight: "72px",
20
+ padding: "8px",
21
+ fontSize: "13px",
22
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
23
+ border: "1px solid",
24
+ borderRadius: "8px",
25
+ outline: "none",
26
+ resize: "vertical",
27
+ transition: "all 0.2s ease-in-out",
28
+ lineHeight: "1.5"
29
+ };
30
+ var helperTextStyles = {
31
+ fontSize: "13px",
32
+ marginTop: "4px",
33
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
34
+ };
35
+ var TextArea = React.forwardRef(
36
+ ({
37
+ label,
38
+ placeholder,
39
+ value,
40
+ onChange,
41
+ state = "default",
42
+ error,
43
+ helperText,
44
+ disabled = false,
45
+ rows = 3,
46
+ className,
47
+ style,
48
+ "data-testid": dataTestId,
49
+ name
50
+ }, ref) => {
51
+ const [isFocused, setIsFocused] = React.useState(false);
52
+ const [isHovered, setIsHovered] = React.useState(false);
53
+ const textareaId = React.useId();
54
+ const actualState = error ? "error" : state;
55
+ const getBorderColor = () => {
56
+ if (disabled) {
57
+ return "#dfdfdf";
58
+ }
59
+ if (actualState === "error") {
60
+ return "#c93232";
61
+ }
62
+ if (actualState === "success") {
63
+ return "#0e8a0e";
64
+ }
65
+ if (isFocused) {
66
+ return "#0e8a0e";
67
+ }
68
+ if (isHovered) {
69
+ return "#7e7e7e";
70
+ }
71
+ return "#dfdfdf";
72
+ };
73
+ const getBackgroundColor = () => {
74
+ if (disabled) {
75
+ return "#efefef";
76
+ }
77
+ return "#ffffff";
78
+ };
79
+ const getBoxShadow = () => {
80
+ if (isFocused && !disabled) {
81
+ if (actualState === "error") {
82
+ return "0px 0px 0px 3px rgba(201, 50, 50, 0.2)";
83
+ }
84
+ return "0px 0px 0px 3px #3cad51";
85
+ }
86
+ return void 0;
87
+ };
88
+ const textareaStylesCombined = {
89
+ ...textareaStyles,
90
+ borderColor: getBorderColor(),
91
+ backgroundColor: getBackgroundColor(),
92
+ boxShadow: getBoxShadow(),
93
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
94
+ cursor: disabled ? "not-allowed" : "text"
95
+ };
96
+ const helperColor = error ? "#c93232" : actualState === "success" ? "#0e8a0e" : "#595959";
97
+ return /* @__PURE__ */ jsxs(
98
+ "div",
99
+ {
100
+ className: clsx("arbor-textarea-wrapper", className),
101
+ style,
102
+ "data-testid": dataTestId,
103
+ children: [
104
+ label && /* @__PURE__ */ jsx("label", { htmlFor: textareaId, style: labelStyles, children: label }),
105
+ label && /* @__PURE__ */ jsx("div", { style: { height: "8px" } }),
106
+ /* @__PURE__ */ jsx("div", { style: textareaWrapperStyles, children: /* @__PURE__ */ jsx(
107
+ "textarea",
108
+ {
109
+ ref,
110
+ id: textareaId,
111
+ name,
112
+ placeholder,
113
+ value,
114
+ onChange,
115
+ disabled,
116
+ rows,
117
+ onFocus: () => setIsFocused(true),
118
+ onBlur: () => setIsFocused(false),
119
+ onMouseEnter: () => setIsHovered(true),
120
+ onMouseLeave: () => setIsHovered(false),
121
+ style: textareaStylesCombined
122
+ }
123
+ ) }),
124
+ (error || helperText) && /* @__PURE__ */ jsx("div", { style: { ...helperTextStyles, color: helperColor }, role: error ? "alert" : void 0, children: error || helperText })
125
+ ]
126
+ }
127
+ );
128
+ }
129
+ );
130
+ TextArea.displayName = "TextArea";
131
+
132
+ export {
133
+ TextArea
134
+ };
135
+ //# sourceMappingURL=chunk-MBUMR2XJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/TextArea/TextArea.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface TextAreaProps {\n /**\n * The label for the textarea\n */\n label?: string;\n /**\n * Placeholder text\n */\n placeholder?: string;\n /**\n * Current value\n */\n value?: string;\n /**\n * Change handler\n */\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n /**\n * Validation state - affects border color\n */\n state?: 'default' | 'success' | 'error';\n /**\n * Error message (implies error state)\n */\n error?: string;\n /**\n * Helper text shown below input\n */\n helperText?: string;\n /**\n * Whether the textarea is disabled\n */\n disabled?: boolean;\n /**\n * Number of rows (affects height)\n */\n rows?: number;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n /**\n * Name attribute for form submission\n */\n name?: string;\n}\n\nconst labelStyles: React.CSSProperties = {\n fontSize: '13px',\n fontWeight: 600,\n color: '#2f2f2f',\n marginBottom: '0px',\n display: 'block',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n};\n\nconst textareaWrapperStyles: React.CSSProperties = {\n position: 'relative',\n width: '100%',\n};\n\nconst textareaStyles: React.CSSProperties = {\n width: '100%',\n minHeight: '72px',\n padding: '8px',\n fontSize: '13px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n border: '1px solid',\n borderRadius: '8px',\n outline: 'none',\n resize: 'vertical',\n transition: 'all 0.2s ease-in-out',\n lineHeight: '1.5',\n};\n\nconst helperTextStyles: React.CSSProperties = {\n fontSize: '13px',\n marginTop: '4px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n};\n\n/**\n * TextArea component - Arbor Design System\n *\n * A multi-line text input with label, helper text, and validation states.\n */\nexport const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(\n (\n {\n label,\n placeholder,\n value,\n onChange,\n state = 'default',\n error,\n helperText,\n disabled = false,\n rows = 3,\n className,\n style,\n 'data-testid': dataTestId,\n name,\n },\n ref\n ) => {\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const textareaId = React.useId();\n\n // Determine the actual state (error overrides state prop)\n const actualState = error ? 'error' : state;\n\n // Get border color based on state and interactions\n const getBorderColor = (): string => {\n if (disabled) {\n return '#dfdfdf';\n }\n\n if (actualState === 'error') {\n return '#c93232';\n }\n\n if (actualState === 'success') {\n return '#0e8a0e';\n }\n\n if (isFocused) {\n return '#0e8a0e';\n }\n\n if (isHovered) {\n return '#7e7e7e';\n }\n\n return '#dfdfdf';\n };\n\n // Get background color\n const getBackgroundColor = (): string => {\n if (disabled) {\n return '#efefef';\n }\n return '#ffffff';\n };\n\n // Get box shadow (focus ring)\n const getBoxShadow = (): string | undefined => {\n if (isFocused && !disabled) {\n if (actualState === 'error') {\n return '0px 0px 0px 3px rgba(201, 50, 50, 0.2)';\n }\n return '0px 0px 0px 3px #3cad51';\n }\n return undefined;\n };\n\n const textareaStylesCombined: React.CSSProperties = {\n ...textareaStyles,\n borderColor: getBorderColor(),\n backgroundColor: getBackgroundColor(),\n boxShadow: getBoxShadow(),\n color: disabled ? '#7e7e7e' : '#2f2f2f',\n cursor: disabled ? 'not-allowed' : 'text',\n };\n\n const helperColor = error ? '#c93232' : actualState === 'success' ? '#0e8a0e' : '#595959';\n\n return (\n <div\n className={clsx('arbor-textarea-wrapper', className)}\n style={style}\n data-testid={dataTestId}\n >\n {label && (\n <label htmlFor={textareaId} style={labelStyles}>\n {label}\n </label>\n )}\n {label && <div style={{ height: '8px' }} />}\n <div style={textareaWrapperStyles}>\n <textarea\n ref={ref}\n id={textareaId}\n name={name}\n placeholder={placeholder}\n value={value}\n onChange={onChange}\n disabled={disabled}\n rows={rows}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={textareaStylesCombined}\n />\n </div>\n {(error || helperText) && (\n <div style={{ ...helperTextStyles, color: helperColor }} role={error ? 'alert' : undefined}>\n {error || helperText}\n </div>\n )}\n </div>\n );\n }\n);\n\nTextArea.displayName = 'TextArea';\n"],"mappings":"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","names":[]}
@@ -0,0 +1,73 @@
1
+ // src/Tooltip/Tooltip.tsx
2
+ import * as React from "react";
3
+ import { clsx } from "clsx";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var tooltipStyles = {
6
+ position: "absolute",
7
+ bottom: "calc(100% + 8px)",
8
+ left: "50%",
9
+ transform: "translateX(-50%)",
10
+ backgroundColor: "#2f2f2f",
11
+ color: "#ffffff",
12
+ padding: "12px",
13
+ borderRadius: "8px",
14
+ boxShadow: "0px 4px 12px 0px rgba(32, 32, 32, 0.08)",
15
+ fontSize: "13px",
16
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
17
+ fontWeight: 400,
18
+ lineHeight: 1.5,
19
+ whiteSpace: "nowrap",
20
+ pointerEvents: "none",
21
+ zIndex: 1e3,
22
+ opacity: 0,
23
+ transition: "opacity 0.2s ease-in-out"
24
+ };
25
+ var wrapperStyles = {
26
+ position: "relative",
27
+ display: "inline-block"
28
+ };
29
+ var Tooltip = React.forwardRef(
30
+ ({
31
+ content,
32
+ children,
33
+ className,
34
+ style,
35
+ "data-testid": dataTestId
36
+ }, ref) => {
37
+ const [isVisible, setIsVisible] = React.useState(false);
38
+ const visibleTooltipStyles = {
39
+ ...tooltipStyles,
40
+ opacity: isVisible ? 1 : 0,
41
+ ...style
42
+ };
43
+ return /* @__PURE__ */ jsxs(
44
+ "div",
45
+ {
46
+ ref,
47
+ style: wrapperStyles,
48
+ onMouseEnter: () => setIsVisible(true),
49
+ onMouseLeave: () => setIsVisible(false),
50
+ "data-testid": dataTestId,
51
+ children: [
52
+ children,
53
+ /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ className: clsx("arbor-tooltip", className),
57
+ style: visibleTooltipStyles,
58
+ role: "tooltip",
59
+ "aria-hidden": !isVisible,
60
+ children: content
61
+ }
62
+ )
63
+ ]
64
+ }
65
+ );
66
+ }
67
+ );
68
+ Tooltip.displayName = "Tooltip";
69
+
70
+ export {
71
+ Tooltip
72
+ };
73
+ //# sourceMappingURL=chunk-MNH2TGUX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface TooltipProps {\n /**\n * The content to display in the tooltip\n */\n content: string;\n /**\n * The trigger element that shows the tooltip on hover\n */\n children: React.ReactNode;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n}\n\nconst tooltipStyles: React.CSSProperties = {\n position: 'absolute',\n bottom: 'calc(100% + 8px)',\n left: '50%',\n transform: 'translateX(-50%)',\n backgroundColor: '#2f2f2f',\n color: '#ffffff',\n padding: '12px',\n borderRadius: '8px',\n boxShadow: '0px 4px 12px 0px rgba(32, 32, 32, 0.08)',\n fontSize: '13px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontWeight: 400,\n lineHeight: 1.5,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n zIndex: 1000,\n opacity: 0,\n transition: 'opacity 0.2s ease-in-out',\n};\n\nconst wrapperStyles: React.CSSProperties = {\n position: 'relative',\n display: 'inline-block',\n};\n\n/**\n * Tooltip component - Arbor Design System\n *\n * A tooltip that appears on hover over a trigger element.\n */\nexport const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(\n (\n {\n content,\n children,\n className,\n style,\n 'data-testid': dataTestId,\n },\n ref\n ) => {\n const [isVisible, setIsVisible] = React.useState(false);\n\n const visibleTooltipStyles: React.CSSProperties = {\n ...tooltipStyles,\n opacity: isVisible ? 1 : 0,\n ...style,\n };\n\n return (\n <div\n ref={ref}\n style={wrapperStyles}\n onMouseEnter={() => setIsVisible(true)}\n onMouseLeave={() => setIsVisible(false)}\n data-testid={dataTestId}\n >\n {children}\n <div\n className={clsx('arbor-tooltip', className)}\n style={visibleTooltipStyles}\n role=\"tooltip\"\n aria-hidden={!isVisible}\n >\n {content}\n </div>\n </div>\n );\n }\n);\n\nTooltip.displayName = 'Tooltip';\n"],"mappings":";AAAA,YAAY,WAAW;AACvB,SAAS,YAAY;AA4Ef,SAQE,KARF;AAnDN,IAAM,gBAAqC;AAAA,EACzC,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,YAAY;AACd;AAEA,IAAM,gBAAqC;AAAA,EACzC,UAAU;AAAA,EACV,SAAS;AACX;AAOO,IAAM,UAAgB;AAAA,EAC3B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,EACjB,GACA,QACG;AACH,UAAM,CAAC,WAAW,YAAY,IAAU,eAAS,KAAK;AAEtD,UAAM,uBAA4C;AAAA,MAChD,GAAG;AAAA,MACH,SAAS,YAAY,IAAI;AAAA,MACzB,GAAG;AAAA,IACL;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,QACP,cAAc,MAAM,aAAa,IAAI;AAAA,QACrC,cAAc,MAAM,aAAa,KAAK;AAAA,QACtC,eAAa;AAAA,QAEZ;AAAA;AAAA,UACD;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,KAAK,iBAAiB,SAAS;AAAA,cAC1C,OAAO;AAAA,cACP,MAAK;AAAA,cACL,eAAa,CAAC;AAAA,cAEb;AAAA;AAAA,UACH;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,QAAQ,cAAc;","names":[]}
@@ -0,0 +1,265 @@
1
+ // src/Pagination/Pagination.tsx
2
+ import * as React from "react";
3
+ import { clsx } from "clsx";
4
+ import { ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight } from "lucide-react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var containerStyles = {
7
+ display: "flex",
8
+ alignItems: "center",
9
+ gap: "8px",
10
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
11
+ };
12
+ var buttonStyles = {
13
+ width: "24px",
14
+ height: "24px",
15
+ borderRadius: "50%",
16
+ border: "none",
17
+ background: "transparent",
18
+ cursor: "pointer",
19
+ display: "flex",
20
+ alignItems: "center",
21
+ justifyContent: "center",
22
+ padding: 0,
23
+ transition: "background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out",
24
+ flexShrink: 0,
25
+ WebkitTapHighlightColor: "transparent",
26
+ outline: "none"
27
+ };
28
+ var buttonDisabledStyles = {
29
+ cursor: "not-allowed",
30
+ opacity: 0.5
31
+ };
32
+ var labelStyles = {
33
+ fontSize: "13px",
34
+ fontWeight: 600,
35
+ lineHeight: "1.5",
36
+ color: "#2f2f2f"
37
+ };
38
+ var inputWrapperStyles = {
39
+ display: "flex",
40
+ alignItems: "center",
41
+ gap: "8px"
42
+ };
43
+ var inputStyles = {
44
+ width: "60px",
45
+ paddingTop: "12px",
46
+ paddingBottom: "12px",
47
+ paddingLeft: "16px",
48
+ paddingRight: "16px",
49
+ fontSize: "13px",
50
+ fontWeight: 400,
51
+ lineHeight: "1.5",
52
+ color: "#2f2f2f",
53
+ backgroundColor: "white",
54
+ border: "1px solid #dfdfdf",
55
+ borderRadius: "8px",
56
+ fontFamily: "inherit",
57
+ textAlign: "center",
58
+ outline: "none"
59
+ };
60
+ var inputFocusStyles = {
61
+ boxShadow: "0px 0px 0px 3px #3cad51"
62
+ };
63
+ var textStyles = {
64
+ fontSize: "13px",
65
+ fontWeight: 400,
66
+ lineHeight: "1.5",
67
+ color: "#2f2f2f"
68
+ };
69
+ var Pagination = React.forwardRef(
70
+ ({
71
+ currentPage,
72
+ totalPages,
73
+ onPageChange,
74
+ className,
75
+ style,
76
+ "data-testid": dataTestId
77
+ }, ref) => {
78
+ const [inputValue, setInputValue] = React.useState(currentPage.toString());
79
+ const [focusedButton, setFocusedButton] = React.useState(null);
80
+ const [hoveredButton, setHoveredButton] = React.useState(null);
81
+ const [activeButton, setActiveButton] = React.useState(null);
82
+ const [inputFocused, setInputFocused] = React.useState(false);
83
+ React.useEffect(() => {
84
+ setInputValue(currentPage.toString());
85
+ }, [currentPage]);
86
+ const handleFirstPage = () => {
87
+ if (currentPage !== 1) {
88
+ onPageChange(1);
89
+ }
90
+ };
91
+ const handlePreviousPage = () => {
92
+ if (currentPage > 1) {
93
+ onPageChange(currentPage - 1);
94
+ }
95
+ };
96
+ const handleNextPage = () => {
97
+ if (currentPage < totalPages) {
98
+ onPageChange(currentPage + 1);
99
+ }
100
+ };
101
+ const handleLastPage = () => {
102
+ if (currentPage !== totalPages) {
103
+ onPageChange(totalPages);
104
+ }
105
+ };
106
+ const handleInputChange = (e) => {
107
+ const value = e.target.value;
108
+ if (value === "" || /^\d+$/.test(value)) {
109
+ setInputValue(value);
110
+ }
111
+ };
112
+ const handleInputBlur = () => {
113
+ setInputFocused(false);
114
+ const pageNumber = parseInt(inputValue, 10);
115
+ if (isNaN(pageNumber) || pageNumber < 1) {
116
+ setInputValue(currentPage.toString());
117
+ } else if (pageNumber > totalPages) {
118
+ setInputValue(totalPages.toString());
119
+ onPageChange(totalPages);
120
+ } else if (pageNumber !== currentPage) {
121
+ onPageChange(pageNumber);
122
+ }
123
+ };
124
+ const handleInputKeyDown = (e) => {
125
+ if (e.key === "Enter") {
126
+ handleInputBlur();
127
+ e.target.blur();
128
+ }
129
+ };
130
+ const getButtonStyle = (buttonName, disabled) => {
131
+ if (disabled) {
132
+ return { ...buttonStyles, ...buttonDisabledStyles };
133
+ }
134
+ const isHovered = hoveredButton === buttonName;
135
+ const isFocused = focusedButton === buttonName;
136
+ const isActive = activeButton === buttonName;
137
+ const style2 = {
138
+ ...buttonStyles
139
+ };
140
+ if (isHovered && !isFocused && !isActive) {
141
+ style2.backgroundColor = "#efefef";
142
+ }
143
+ if (isActive && !isFocused) {
144
+ style2.backgroundColor = "transparent";
145
+ }
146
+ if (isFocused) {
147
+ style2.boxShadow = "0px 0px 0px 3px #3cad51";
148
+ style2.backgroundColor = "rgba(255, 255, 255, 0.01)";
149
+ }
150
+ return style2;
151
+ };
152
+ const isFirstDisabled = currentPage === 1;
153
+ const isPreviousDisabled = currentPage === 1;
154
+ const isNextDisabled = currentPage === totalPages;
155
+ const isLastDisabled = currentPage === totalPages;
156
+ return /* @__PURE__ */ jsxs(
157
+ "div",
158
+ {
159
+ ref,
160
+ className: clsx("arbor-pagination", className),
161
+ style: { ...containerStyles, ...style },
162
+ "data-testid": dataTestId,
163
+ children: [
164
+ /* @__PURE__ */ jsx(
165
+ "button",
166
+ {
167
+ type: "button",
168
+ onClick: handleFirstPage,
169
+ disabled: isFirstDisabled,
170
+ onMouseEnter: () => setHoveredButton("first"),
171
+ onMouseLeave: () => setHoveredButton(null),
172
+ onMouseDown: () => setActiveButton("first"),
173
+ onMouseUp: () => setActiveButton(null),
174
+ onFocus: () => setFocusedButton("first"),
175
+ onBlur: () => setFocusedButton(null),
176
+ style: getButtonStyle("first", isFirstDisabled),
177
+ "aria-label": "Go to first page",
178
+ children: /* @__PURE__ */ jsx(ChevronsLeft, { size: 16, color: "#2f2f2f" })
179
+ }
180
+ ),
181
+ /* @__PURE__ */ jsx(
182
+ "button",
183
+ {
184
+ type: "button",
185
+ onClick: handlePreviousPage,
186
+ disabled: isPreviousDisabled,
187
+ onMouseEnter: () => setHoveredButton("previous"),
188
+ onMouseLeave: () => setHoveredButton(null),
189
+ onMouseDown: () => setActiveButton("previous"),
190
+ onMouseUp: () => setActiveButton(null),
191
+ onFocus: () => setFocusedButton("previous"),
192
+ onBlur: () => setFocusedButton(null),
193
+ style: getButtonStyle("previous", isPreviousDisabled),
194
+ "aria-label": "Go to previous page",
195
+ children: /* @__PURE__ */ jsx(ChevronLeft, { size: 16, color: "#2f2f2f" })
196
+ }
197
+ ),
198
+ /* @__PURE__ */ jsxs("div", { style: inputWrapperStyles, children: [
199
+ /* @__PURE__ */ jsx("span", { style: labelStyles, children: "Page" }),
200
+ /* @__PURE__ */ jsx(
201
+ "input",
202
+ {
203
+ type: "text",
204
+ value: inputValue,
205
+ onChange: handleInputChange,
206
+ onBlur: handleInputBlur,
207
+ onFocus: () => setInputFocused(true),
208
+ onKeyDown: handleInputKeyDown,
209
+ style: {
210
+ ...inputStyles,
211
+ ...inputFocused && inputFocusStyles
212
+ },
213
+ "aria-label": `Page ${currentPage} of ${totalPages}`
214
+ }
215
+ ),
216
+ /* @__PURE__ */ jsxs("span", { style: textStyles, children: [
217
+ "of ",
218
+ totalPages
219
+ ] })
220
+ ] }),
221
+ /* @__PURE__ */ jsx(
222
+ "button",
223
+ {
224
+ type: "button",
225
+ onClick: handleNextPage,
226
+ disabled: isNextDisabled,
227
+ onMouseEnter: () => setHoveredButton("next"),
228
+ onMouseLeave: () => setHoveredButton(null),
229
+ onMouseDown: () => setActiveButton("next"),
230
+ onMouseUp: () => setActiveButton(null),
231
+ onFocus: () => setFocusedButton("next"),
232
+ onBlur: () => setFocusedButton(null),
233
+ style: getButtonStyle("next", isNextDisabled),
234
+ "aria-label": "Go to next page",
235
+ children: /* @__PURE__ */ jsx(ChevronRight, { size: 16, color: "#2f2f2f" })
236
+ }
237
+ ),
238
+ /* @__PURE__ */ jsx(
239
+ "button",
240
+ {
241
+ type: "button",
242
+ onClick: handleLastPage,
243
+ disabled: isLastDisabled,
244
+ onMouseEnter: () => setHoveredButton("last"),
245
+ onMouseLeave: () => setHoveredButton(null),
246
+ onMouseDown: () => setActiveButton("last"),
247
+ onMouseUp: () => setActiveButton(null),
248
+ onFocus: () => setFocusedButton("last"),
249
+ onBlur: () => setFocusedButton(null),
250
+ style: getButtonStyle("last", isLastDisabled),
251
+ "aria-label": "Go to last page",
252
+ children: /* @__PURE__ */ jsx(ChevronsRight, { size: 16, color: "#2f2f2f" })
253
+ }
254
+ )
255
+ ]
256
+ }
257
+ );
258
+ }
259
+ );
260
+ Pagination.displayName = "Pagination";
261
+
262
+ export {
263
+ Pagination
264
+ };
265
+ //# sourceMappingURL=chunk-RRMG2SSZ.mjs.map