@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,68 @@
1
+ import * as React from 'react';
2
+
3
+ type NumericInputState = 'default' | 'error' | 'success';
4
+ interface NumericInputProps {
5
+ /**
6
+ * The label for the numeric input
7
+ */
8
+ label?: string;
9
+ /**
10
+ * The current value
11
+ */
12
+ value?: number;
13
+ /**
14
+ * Callback when value changes
15
+ */
16
+ onChange?: (value: number | undefined) => void;
17
+ /**
18
+ * Minimum allowed value
19
+ */
20
+ min?: number;
21
+ /**
22
+ * Maximum allowed value
23
+ */
24
+ max?: number;
25
+ /**
26
+ * Step increment/decrement value
27
+ * @default 1
28
+ */
29
+ step?: number;
30
+ /**
31
+ * The validation state
32
+ * @default 'default'
33
+ */
34
+ state?: NumericInputState;
35
+ /**
36
+ * Optional error message
37
+ */
38
+ error?: string;
39
+ /**
40
+ * Optional helper text
41
+ */
42
+ helperText?: string;
43
+ /**
44
+ * Whether the input is disabled
45
+ */
46
+ disabled?: boolean;
47
+ /**
48
+ * Custom className
49
+ */
50
+ className?: string;
51
+ /**
52
+ * Custom style
53
+ */
54
+ style?: React.CSSProperties;
55
+ /**
56
+ * Test ID for testing
57
+ */
58
+ 'data-testid'?: string;
59
+ }
60
+ /**
61
+ * NumericInput component - Arbor Design System
62
+ *
63
+ * A number input with increment/decrement buttons.
64
+ * Enforces numeric rules (min, max, step) and prevents non-numeric input.
65
+ */
66
+ declare const NumericInput: React.ForwardRefExoticComponent<NumericInputProps & React.RefAttributes<HTMLDivElement>>;
67
+
68
+ export { NumericInput, type NumericInputProps, type NumericInputState };
@@ -0,0 +1,68 @@
1
+ import * as React from 'react';
2
+
3
+ type NumericInputState = 'default' | 'error' | 'success';
4
+ interface NumericInputProps {
5
+ /**
6
+ * The label for the numeric input
7
+ */
8
+ label?: string;
9
+ /**
10
+ * The current value
11
+ */
12
+ value?: number;
13
+ /**
14
+ * Callback when value changes
15
+ */
16
+ onChange?: (value: number | undefined) => void;
17
+ /**
18
+ * Minimum allowed value
19
+ */
20
+ min?: number;
21
+ /**
22
+ * Maximum allowed value
23
+ */
24
+ max?: number;
25
+ /**
26
+ * Step increment/decrement value
27
+ * @default 1
28
+ */
29
+ step?: number;
30
+ /**
31
+ * The validation state
32
+ * @default 'default'
33
+ */
34
+ state?: NumericInputState;
35
+ /**
36
+ * Optional error message
37
+ */
38
+ error?: string;
39
+ /**
40
+ * Optional helper text
41
+ */
42
+ helperText?: string;
43
+ /**
44
+ * Whether the input is disabled
45
+ */
46
+ disabled?: boolean;
47
+ /**
48
+ * Custom className
49
+ */
50
+ className?: string;
51
+ /**
52
+ * Custom style
53
+ */
54
+ style?: React.CSSProperties;
55
+ /**
56
+ * Test ID for testing
57
+ */
58
+ 'data-testid'?: string;
59
+ }
60
+ /**
61
+ * NumericInput component - Arbor Design System
62
+ *
63
+ * A number input with increment/decrement buttons.
64
+ * Enforces numeric rules (min, max, step) and prevents non-numeric input.
65
+ */
66
+ declare const NumericInput: React.ForwardRefExoticComponent<NumericInputProps & React.RefAttributes<HTMLDivElement>>;
67
+
68
+ export { NumericInput, type NumericInputProps, type NumericInputState };
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/NumericInput/index.ts
31
+ var NumericInput_exports = {};
32
+ __export(NumericInput_exports, {
33
+ NumericInput: () => NumericInput
34
+ });
35
+ module.exports = __toCommonJS(NumericInput_exports);
36
+
37
+ // src/NumericInput/NumericInput.tsx
38
+ var React = __toESM(require("react"));
39
+ var import_clsx = require("clsx");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ var labelStyles = {
42
+ display: "block",
43
+ fontSize: "13px",
44
+ fontWeight: "600",
45
+ color: "#2f2f2f",
46
+ marginBottom: "4px",
47
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
48
+ };
49
+ var helperTextStyles = {
50
+ fontSize: "13px",
51
+ margin: "0",
52
+ marginTop: "2px",
53
+ color: "#595959",
54
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
55
+ lineHeight: "1.4"
56
+ };
57
+ var errorTextStyles = {
58
+ ...helperTextStyles,
59
+ color: "#a62323",
60
+ // destructive-600
61
+ display: "flex",
62
+ alignItems: "center",
63
+ gap: "4px"
64
+ };
65
+ var containerStyles = {
66
+ base: {
67
+ display: "flex",
68
+ alignItems: "center",
69
+ height: "46px",
70
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
71
+ backgroundColor: "#ffffff",
72
+ borderRadius: "8px",
73
+ transition: "all 0.2s ease-in-out",
74
+ overflow: "hidden"
75
+ },
76
+ states: {
77
+ default: {
78
+ border: "1px solid #d1d1d1"
79
+ // grey-300
80
+ },
81
+ defaultFocus: {
82
+ borderColor: "#3cad51",
83
+ // brand-500
84
+ outline: "3px solid rgba(60, 173, 81, 0.2)"
85
+ },
86
+ error: {
87
+ border: "1px solid #c93232"
88
+ // destructive-500
89
+ },
90
+ errorFocus: {
91
+ borderColor: "#c93232",
92
+ outline: "3px solid rgba(201, 50, 50, 0.2)"
93
+ },
94
+ success: {
95
+ border: "1px solid #16a33d"
96
+ // success-500
97
+ },
98
+ successFocus: {
99
+ borderColor: "#16a33d",
100
+ outline: "3px solid rgba(22, 163, 61, 0.2)"
101
+ },
102
+ disabled: {
103
+ backgroundColor: "#f8f8f8",
104
+ // grey-050
105
+ borderColor: "#efefef",
106
+ // grey-100
107
+ cursor: "not-allowed"
108
+ }
109
+ }
110
+ };
111
+ var buttonStyles = {
112
+ width: "46px",
113
+ height: "100%",
114
+ border: "none",
115
+ background: "transparent",
116
+ cursor: "pointer",
117
+ fontSize: "16px",
118
+ color: "#2f2f2f",
119
+ display: "flex",
120
+ alignItems: "center",
121
+ justifyContent: "center",
122
+ transition: "background-color 0.2s",
123
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
124
+ userSelect: "none"
125
+ };
126
+ var inputStyles = {
127
+ flex: 1,
128
+ border: "none",
129
+ outline: "none",
130
+ background: "transparent",
131
+ textAlign: "center",
132
+ fontSize: "13px",
133
+ color: "#2f2f2f",
134
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
135
+ padding: "0 8px",
136
+ appearance: "textfield"
137
+ };
138
+ var NumericInput = React.forwardRef(
139
+ ({
140
+ label,
141
+ value,
142
+ onChange,
143
+ min,
144
+ max,
145
+ step = 1,
146
+ state = "default",
147
+ error,
148
+ helperText,
149
+ disabled = false,
150
+ className,
151
+ style,
152
+ "data-testid": dataTestId
153
+ }, ref) => {
154
+ const [isFocused, setIsFocused] = React.useState(false);
155
+ const inputRef = React.useRef(null);
156
+ const inputId = React.useId();
157
+ const helperTextId = React.useId();
158
+ const errorId = React.useId();
159
+ const clampValue = (val) => {
160
+ let clamped = val;
161
+ if (min !== void 0 && clamped < min) clamped = min;
162
+ if (max !== void 0 && clamped > max) clamped = max;
163
+ return clamped;
164
+ };
165
+ const handleIncrement = () => {
166
+ if (disabled) return;
167
+ const currentValue = value ?? 0;
168
+ const newValue = currentValue + step;
169
+ const clampedValue = clampValue(newValue);
170
+ if (clampedValue !== currentValue) {
171
+ onChange?.(clampedValue);
172
+ }
173
+ };
174
+ const handleDecrement = () => {
175
+ if (disabled) return;
176
+ const currentValue = value ?? 0;
177
+ const newValue = currentValue - step;
178
+ const clampedValue = clampValue(newValue);
179
+ if (clampedValue !== currentValue) {
180
+ onChange?.(clampedValue);
181
+ }
182
+ };
183
+ const handleInputChange = (e) => {
184
+ const inputValue = e.target.value;
185
+ if (inputValue === "" || inputValue === "-") {
186
+ onChange?.(void 0);
187
+ return;
188
+ }
189
+ const numValue = parseFloat(inputValue);
190
+ if (!isNaN(numValue)) {
191
+ const clampedValue = clampValue(numValue);
192
+ onChange?.(clampedValue);
193
+ }
194
+ };
195
+ const handleKeyDown = (e) => {
196
+ const allowedKeys = ["Backspace", "Delete", "Tab", "Escape", "Enter", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "-", "."];
197
+ if (allowedKeys.includes(e.key)) {
198
+ if (e.key === "ArrowUp") {
199
+ e.preventDefault();
200
+ handleIncrement();
201
+ } else if (e.key === "ArrowDown") {
202
+ e.preventDefault();
203
+ handleDecrement();
204
+ }
205
+ return;
206
+ }
207
+ if (!/^[0-9]$/.test(e.key)) {
208
+ e.preventDefault();
209
+ }
210
+ };
211
+ const currentState = error ? "error" : state;
212
+ const stateStyles = containerStyles.states[currentState];
213
+ const focusStyles = currentState === "error" ? containerStyles.states.errorFocus : currentState === "success" ? containerStyles.states.successFocus : containerStyles.states.defaultFocus;
214
+ const containerStyle = {
215
+ ...containerStyles.base,
216
+ ...stateStyles,
217
+ ...isFocused && !disabled && focusStyles,
218
+ ...disabled && containerStyles.states.disabled
219
+ };
220
+ const isDecrementDisabled = disabled || min !== void 0 && value !== void 0 && value <= min;
221
+ const isIncrementDisabled = disabled || max !== void 0 && value !== void 0 && value >= max;
222
+ const getButtonStyle = (isDisabled) => {
223
+ const baseStyle = {
224
+ ...buttonStyles,
225
+ cursor: isDisabled ? "not-allowed" : "pointer",
226
+ color: isDisabled ? "#7e7e7e" : "#2f2f2f"
227
+ };
228
+ if (currentState === "success" && !isDisabled) {
229
+ return {
230
+ ...baseStyle,
231
+ color: "#16a33d",
232
+ // success-500
233
+ border: "2px solid #16a33d",
234
+ borderRadius: "50%",
235
+ width: "32px",
236
+ height: "32px"
237
+ };
238
+ }
239
+ return baseStyle;
240
+ };
241
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_clsx.clsx)("arbor-numeric-input-wrapper", className), style, ref, "data-testid": dataTestId, children: [
242
+ label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: inputId, style: labelStyles, children: label }),
243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: containerStyle, children: [
244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
245
+ "button",
246
+ {
247
+ type: "button",
248
+ onClick: handleDecrement,
249
+ disabled: isDecrementDisabled,
250
+ style: getButtonStyle(isDecrementDisabled),
251
+ onMouseEnter: (e) => {
252
+ if (!isDecrementDisabled) {
253
+ e.currentTarget.style.backgroundColor = "#f8f8f8";
254
+ e.currentTarget.style.borderRadius = "99px";
255
+ }
256
+ },
257
+ onMouseLeave: (e) => {
258
+ e.currentTarget.style.backgroundColor = "transparent";
259
+ e.currentTarget.style.borderRadius = currentState === "success" ? "50%" : "0";
260
+ },
261
+ "aria-label": "Decrement",
262
+ children: "\u2212"
263
+ }
264
+ ),
265
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
266
+ "input",
267
+ {
268
+ ref: inputRef,
269
+ id: inputId,
270
+ type: "text",
271
+ inputMode: "numeric",
272
+ value: value !== void 0 ? value : "",
273
+ onChange: handleInputChange,
274
+ onKeyDown: handleKeyDown,
275
+ onFocus: () => setIsFocused(true),
276
+ onBlur: () => setIsFocused(false),
277
+ disabled,
278
+ "aria-invalid": error ? "true" : "false",
279
+ "aria-describedby": error ? errorId : helperText ? helperTextId : void 0,
280
+ style: {
281
+ ...inputStyles,
282
+ color: disabled ? "#7e7e7e" : "#2f2f2f",
283
+ cursor: disabled ? "not-allowed" : "text"
284
+ }
285
+ }
286
+ ),
287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
288
+ "button",
289
+ {
290
+ type: "button",
291
+ onClick: handleIncrement,
292
+ disabled: isIncrementDisabled,
293
+ style: getButtonStyle(isIncrementDisabled),
294
+ onMouseEnter: (e) => {
295
+ if (!isIncrementDisabled) {
296
+ e.currentTarget.style.backgroundColor = "#f8f8f8";
297
+ e.currentTarget.style.borderRadius = "99px";
298
+ }
299
+ },
300
+ onMouseLeave: (e) => {
301
+ e.currentTarget.style.backgroundColor = "transparent";
302
+ e.currentTarget.style.borderRadius = currentState === "success" ? "50%" : "0";
303
+ },
304
+ "aria-label": "Increment",
305
+ children: "+"
306
+ }
307
+ )
308
+ ] }),
309
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: errorId, style: errorTextStyles, children: error }),
310
+ helperText && !error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: helperTextId, style: helperTextStyles, children: helperText })
311
+ ] });
312
+ }
313
+ );
314
+ NumericInput.displayName = "NumericInput";
315
+ // Annotate the CommonJS export names for ESM import in node:
316
+ 0 && (module.exports = {
317
+ NumericInput
318
+ });
319
+ //# sourceMappingURL=NumericInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/NumericInput/index.ts","../src/NumericInput/NumericInput.tsx"],"sourcesContent":["export { NumericInput } from './NumericInput';\nexport type { NumericInputProps, NumericInputState } from './NumericInput';\n","import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport type NumericInputState = 'default' | 'error' | 'success';\n\nexport interface NumericInputProps {\n /**\n * The label for the numeric input\n */\n label?: string;\n /**\n * The current value\n */\n value?: number;\n /**\n * Callback when value changes\n */\n onChange?: (value: number | undefined) => void;\n /**\n * Minimum allowed value\n */\n min?: number;\n /**\n * Maximum allowed value\n */\n max?: number;\n /**\n * Step increment/decrement value\n * @default 1\n */\n step?: number;\n /**\n * The validation state\n * @default 'default'\n */\n state?: NumericInputState;\n /**\n * Optional error message\n */\n error?: string;\n /**\n * Optional helper text\n */\n helperText?: string;\n /**\n * Whether the input 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\nconst labelStyles: React.CSSProperties = {\n display: 'block',\n fontSize: '13px',\n fontWeight: '600',\n color: '#2f2f2f',\n marginBottom: '4px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n};\n\nconst helperTextStyles: React.CSSProperties = {\n fontSize: '13px',\n margin: '0',\n marginTop: '2px',\n color: '#595959',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n lineHeight: '1.4',\n};\n\nconst errorTextStyles: React.CSSProperties = {\n ...helperTextStyles,\n color: '#a62323', // destructive-600\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n};\n\nconst containerStyles = {\n base: {\n display: 'flex',\n alignItems: 'center',\n height: '46px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n backgroundColor: '#ffffff',\n borderRadius: '8px',\n transition: 'all 0.2s ease-in-out',\n overflow: 'hidden',\n },\n states: {\n default: {\n border: '1px solid #d1d1d1', // grey-300\n },\n defaultFocus: {\n borderColor: '#3cad51', // brand-500\n outline: '3px solid rgba(60, 173, 81, 0.2)',\n },\n error: {\n border: '1px solid #c93232', // destructive-500\n },\n errorFocus: {\n borderColor: '#c93232',\n outline: '3px solid rgba(201, 50, 50, 0.2)',\n },\n success: {\n border: '1px solid #16a33d', // success-500\n },\n successFocus: {\n borderColor: '#16a33d',\n outline: '3px solid rgba(22, 163, 61, 0.2)',\n },\n disabled: {\n backgroundColor: '#f8f8f8', // grey-050\n borderColor: '#efefef', // grey-100\n cursor: 'not-allowed',\n },\n },\n};\n\nconst buttonStyles: React.CSSProperties = {\n width: '46px',\n height: '100%',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n fontSize: '16px',\n color: '#2f2f2f',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'background-color 0.2s',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n userSelect: 'none' as const,\n};\n\nconst inputStyles: React.CSSProperties = {\n flex: 1,\n border: 'none',\n outline: 'none',\n background: 'transparent',\n textAlign: 'center',\n fontSize: '13px',\n color: '#2f2f2f',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n padding: '0 8px',\n appearance: 'textfield' as any,\n};\n\n/**\n * NumericInput component - Arbor Design System\n *\n * A number input with increment/decrement buttons.\n * Enforces numeric rules (min, max, step) and prevents non-numeric input.\n */\nexport const NumericInput = React.forwardRef<HTMLDivElement, NumericInputProps>(\n (\n {\n label,\n value,\n onChange,\n min,\n max,\n step = 1,\n state = 'default',\n error,\n helperText,\n disabled = false,\n className,\n style,\n 'data-testid': dataTestId,\n },\n ref\n ) => {\n const [isFocused, setIsFocused] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n const inputId = React.useId();\n const helperTextId = React.useId();\n const errorId = React.useId();\n\n const clampValue = (val: number): number => {\n let clamped = val;\n if (min !== undefined && clamped < min) clamped = min;\n if (max !== undefined && clamped > max) clamped = max;\n return clamped;\n };\n\n const handleIncrement = () => {\n if (disabled) return;\n const currentValue = value ?? 0;\n const newValue = currentValue + step;\n const clampedValue = clampValue(newValue);\n if (clampedValue !== currentValue) {\n onChange?.(clampedValue);\n }\n };\n\n const handleDecrement = () => {\n if (disabled) return;\n const currentValue = value ?? 0;\n const newValue = currentValue - step;\n const clampedValue = clampValue(newValue);\n if (clampedValue !== currentValue) {\n onChange?.(clampedValue);\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n\n // Allow empty input\n if (inputValue === '' || inputValue === '-') {\n onChange?.(undefined);\n return;\n }\n\n // Parse as number\n const numValue = parseFloat(inputValue);\n\n // Only update if it's a valid number\n if (!isNaN(numValue)) {\n const clampedValue = clampValue(numValue);\n onChange?.(clampedValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Allow: backspace, delete, tab, escape, enter, minus sign, decimal point\n const allowedKeys = ['Backspace', 'Delete', 'Tab', 'Escape', 'Enter', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', '-', '.'];\n\n if (allowedKeys.includes(e.key)) {\n // Handle arrow keys for increment/decrement\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n handleIncrement();\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n handleDecrement();\n }\n return;\n }\n\n // Only allow numbers\n if (!/^[0-9]$/.test(e.key)) {\n e.preventDefault();\n }\n };\n\n const currentState = error ? 'error' : state;\n const stateStyles = containerStyles.states[currentState];\n const focusStyles =\n currentState === 'error'\n ? containerStyles.states.errorFocus\n : currentState === 'success'\n ? containerStyles.states.successFocus\n : containerStyles.states.defaultFocus;\n\n const containerStyle: React.CSSProperties = {\n ...containerStyles.base,\n ...stateStyles,\n ...(isFocused && !disabled && focusStyles),\n ...(disabled && containerStyles.states.disabled),\n };\n\n const isDecrementDisabled = disabled || (min !== undefined && value !== undefined && value <= min);\n const isIncrementDisabled = disabled || (max !== undefined && value !== undefined && value >= max);\n\n // Button styles for success state (green outlined circles)\n const getButtonStyle = (isDisabled: boolean) => {\n const baseStyle: React.CSSProperties = {\n ...buttonStyles,\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n color: isDisabled ? '#7e7e7e' : '#2f2f2f',\n };\n\n // Add green circle border for success state\n if (currentState === 'success' && !isDisabled) {\n return {\n ...baseStyle,\n color: '#16a33d', // success-500\n border: '2px solid #16a33d',\n borderRadius: '50%',\n width: '32px',\n height: '32px',\n };\n }\n\n return baseStyle;\n };\n\n return (\n <div className={clsx('arbor-numeric-input-wrapper', className)} style={style} ref={ref} data-testid={dataTestId}>\n {label && (\n <label htmlFor={inputId} style={labelStyles}>\n {label}\n </label>\n )}\n\n <div style={containerStyle}>\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={isDecrementDisabled}\n style={getButtonStyle(isDecrementDisabled)}\n onMouseEnter={(e) => {\n if (!isDecrementDisabled) {\n e.currentTarget.style.backgroundColor = '#f8f8f8';\n e.currentTarget.style.borderRadius = '99px';\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n e.currentTarget.style.borderRadius = currentState === 'success' ? '50%' : '0';\n }}\n aria-label=\"Decrement\"\n >\n −\n </button>\n\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n inputMode=\"numeric\"\n value={value !== undefined ? value : ''}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n disabled={disabled}\n aria-invalid={error ? 'true' : 'false'}\n aria-describedby={error ? errorId : helperText ? helperTextId : undefined}\n style={{\n ...inputStyles,\n color: disabled ? '#7e7e7e' : '#2f2f2f',\n cursor: disabled ? 'not-allowed' : 'text',\n }}\n />\n\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={isIncrementDisabled}\n style={getButtonStyle(isIncrementDisabled)}\n onMouseEnter={(e) => {\n if (!isIncrementDisabled) {\n e.currentTarget.style.backgroundColor = '#f8f8f8';\n e.currentTarget.style.borderRadius = '99px';\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n e.currentTarget.style.borderRadius = currentState === 'success' ? '50%' : '0';\n }}\n aria-label=\"Increment\"\n >\n +\n </button>\n </div>\n\n {error && (\n <p id={errorId} style={errorTextStyles}>\n {error}\n </p>\n )}\n\n {helperText && !error && (\n <p id={helperTextId} style={helperTextStyles}>\n {helperText}\n </p>\n )}\n </div>\n );\n }\n);\n\nNumericInput.displayName = 'NumericInput';\n"],"mappings":"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","names":[]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ NumericInput
3
+ } from "./chunk-5BUXFTPW.mjs";
4
+ export {
5
+ NumericInput
6
+ };
7
+ //# sourceMappingURL=NumericInput.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+
3
+ interface PaginationProps {
4
+ /**
5
+ * Current page number (1-indexed)
6
+ */
7
+ currentPage: number;
8
+ /**
9
+ * Total number of pages
10
+ */
11
+ totalPages: number;
12
+ /**
13
+ * Callback when page changes
14
+ */
15
+ onPageChange: (page: number) => void;
16
+ /**
17
+ * Custom className
18
+ */
19
+ className?: string;
20
+ /**
21
+ * Custom style
22
+ */
23
+ style?: React.CSSProperties;
24
+ /**
25
+ * Test ID for testing
26
+ */
27
+ 'data-testid'?: string;
28
+ }
29
+ /**
30
+ * Pagination component - Arbor Design System
31
+ *
32
+ * A pagination control with first/previous/next/last buttons and a page input field.
33
+ */
34
+ declare const Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLDivElement>>;
35
+
36
+ export { Pagination, type PaginationProps };
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+
3
+ interface PaginationProps {
4
+ /**
5
+ * Current page number (1-indexed)
6
+ */
7
+ currentPage: number;
8
+ /**
9
+ * Total number of pages
10
+ */
11
+ totalPages: number;
12
+ /**
13
+ * Callback when page changes
14
+ */
15
+ onPageChange: (page: number) => void;
16
+ /**
17
+ * Custom className
18
+ */
19
+ className?: string;
20
+ /**
21
+ * Custom style
22
+ */
23
+ style?: React.CSSProperties;
24
+ /**
25
+ * Test ID for testing
26
+ */
27
+ 'data-testid'?: string;
28
+ }
29
+ /**
30
+ * Pagination component - Arbor Design System
31
+ *
32
+ * A pagination control with first/previous/next/last buttons and a page input field.
33
+ */
34
+ declare const Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLDivElement>>;
35
+
36
+ export { Pagination, type PaginationProps };