@dt-dds/react-text-field 1.0.0-beta.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,413 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+
33
+ // src/TextField.tsx
34
+ import { Icon } from "@dt-dds/react-icon";
35
+ import { IconButton } from "@dt-dds/react-icon-button";
36
+ import { LabelField } from "@dt-dds/react-label-field";
37
+ import { Typography } from "@dt-dds/react-typography";
38
+ import {
39
+ useEffect,
40
+ useState
41
+ } from "react";
42
+
43
+ // src/TextField.styled.ts
44
+ import styled from "@emotion/styled";
45
+
46
+ // src/constants/helpers.ts
47
+ var getThemedBackgroundFill = (backgroundFill, theme) => ({
48
+ default: theme.palette.surface.default,
49
+ contrast: theme.palette.surface.contrast,
50
+ light: theme.palette.surface.light
51
+ })[backgroundFill] || theme.palette.surface.default;
52
+
53
+ // src/TextField.styled.ts
54
+ var TextFieldStyled = styled.div`
55
+ ${({ theme, isFloatingLabel = true, hasPrefix = false }) => `
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: ${theme.spacing["5xs"]};
59
+ width: 100%;
60
+ position: relative;
61
+
62
+
63
+ ${hasPrefix ? `
64
+ label {
65
+ left: 0;
66
+ padding-left: ${isFloatingLabel ? theme.spacing.l : ""};
67
+ }
68
+ ` : ""}
69
+
70
+ i {
71
+ color: ${theme.palette.content.medium};
72
+ }
73
+
74
+ :has(input[disabled]) {
75
+ i, label > span {
76
+ color: ${theme.palette.content.light};
77
+ }
78
+ }
79
+
80
+ :has(input[readonly]:not(input[disabled])) {
81
+ label, label > span {
82
+ color: ${isFloatingLabel ? theme.palette.content.medium : theme.palette.content.default};
83
+ }
84
+ }
85
+ `}
86
+
87
+ input[type="search"]::-webkit-search-decoration,
88
+ input[type="search"]::-webkit-search-cancel-button,
89
+ input[type="search"]::-webkit-search-results-button,
90
+ input[type="search"]::-webkit-search-results-decoration {
91
+ display: none;
92
+ }
93
+ `;
94
+ var InputFieldStyled = styled.input`
95
+ ${({ theme, isFloatingLabel, isSearchType }) => `
96
+ ${theme.fontStyles.body2}
97
+ border: 0;
98
+ outline: 0;
99
+ width: 100%;
100
+ background-color: inherit;
101
+
102
+
103
+
104
+ input:-webkit-autofill,
105
+ input:-webkit-autofill:hover,
106
+ input:-webkit-autofill:focus,
107
+ input:-webkit-autofill:active {
108
+ transition: background-color 5000s ease-in-out 0s;
109
+ }
110
+
111
+ &::placeholder {
112
+ color: ${isFloatingLabel ? "transparent" : theme.palette.content.medium};
113
+ }
114
+
115
+ padding: ${isFloatingLabel && !isSearchType ? `${theme.spacing.xs} 0 ${theme.spacing["4xs"]} 0` : ""};
116
+
117
+ `}
118
+ `;
119
+ var InputExtraPrefixStyled = styled.div`
120
+ ${({ theme, onClick }) => {
121
+ const isClickable = !!onClick;
122
+ return `
123
+ display: flex;
124
+ cursor: ${isClickable ? "pointer" : "default"};
125
+
126
+ ${isClickable && `
127
+ &:hover > i {
128
+ color: ${theme.palette.content.dark};
129
+ }
130
+ `}
131
+
132
+ `;
133
+ }}
134
+ `;
135
+ var InputExtraSuffixStyled = styled.div`
136
+ ${({ theme, onClick }) => {
137
+ const isClickable = !!onClick;
138
+ return `
139
+ display: flex;
140
+ cursor: ${isClickable ? "pointer" : "default"};
141
+
142
+ ${isClickable && `
143
+ &:hover > i {
144
+ color: ${theme.palette.content.dark};
145
+ }
146
+ `}
147
+ `;
148
+ }}
149
+ `;
150
+ var TextFieldMessageStyled = styled.div`
151
+ padding-left: ${({ theme }) => theme.spacing["2xs"]};
152
+ `;
153
+ var ResetInputIconStyled = styled.div`
154
+ ${({ theme }) => `
155
+ cursor: pointer;
156
+ display: flex;
157
+
158
+ :hover > i {
159
+ color: ${theme.palette.content.dark}
160
+ }
161
+ `}
162
+ `;
163
+ var InputWrapperStyled = styled.div`
164
+ ${({ theme, isFloatingLabel, variant, backgroundFill, hasError }) => {
165
+ const borderColor = hasError ? theme.palette.error.default : theme.palette.border.medium;
166
+ const borderFocusColor = hasError ? theme.palette.error.default : theme.palette.border.dark;
167
+ return `
168
+ display:flex;
169
+ flex-direction: row;
170
+ align-items: center;
171
+ min-width: 198px;
172
+ width: 100%;
173
+ height: 54px;
174
+ color: ${theme.palette.content.default};
175
+ gap: ${theme.spacing["4xs"]};
176
+ background-color: ${getThemedBackgroundFill(backgroundFill, theme)};
177
+
178
+ padding-inline: ${theme.spacing["3xs"]};
179
+
180
+ ${variant === "outlined" ? `border-radius: ${theme.shape.formField};
181
+ border: 1px solid ${borderColor};
182
+ &:focus-within, &:hover { { border: 1px solid ${borderFocusColor}};
183
+ ` : `border-radius: ${theme.shape.formField} ${theme.shape.formField} 0 0;
184
+ border-bottom: 1px solid ${borderColor};
185
+ &:focus-within, &:hover { { border-bottom: 1px solid ${borderFocusColor}};
186
+ `};
187
+
188
+ &:has(input[readonly]:not([disabled])) {
189
+ background-color: ${theme.palette.surface.default};
190
+ color: ${theme.palette.content.medium};
191
+ }
192
+
193
+ &:has(input[disabled]), &:has(input[disabled]) > * {
194
+ color: ${theme.palette.content.light};
195
+ background-color: ${theme.palette.surface.light};
196
+ border-color: ${theme.palette.border.default};
197
+ cursor: not-allowed;
198
+
199
+ input::placeholder {
200
+ color: ${isFloatingLabel ? "transparent" : theme.palette.content.light};
201
+ }
202
+ }
203
+ `;
204
+ }}
205
+ `;
206
+
207
+ // src/TextField.tsx
208
+ import { jsx, jsxs } from "react/jsx-runtime";
209
+ var TextField = (_a) => {
210
+ var _b = _a, {
211
+ hasError = false,
212
+ extraPrefix,
213
+ extraSuffix,
214
+ label,
215
+ isFloatingLabel = true,
216
+ name,
217
+ id,
218
+ required,
219
+ requiredMessage,
220
+ style,
221
+ children,
222
+ initialValue,
223
+ inputRef,
224
+ message: messageProp = "",
225
+ type = "text",
226
+ variant = "outlined",
227
+ backgroundFill = "default",
228
+ disabled = false,
229
+ onChange = () => null,
230
+ onResetInput = () => null
231
+ } = _b, rest = __objRest(_b, [
232
+ "hasError",
233
+ "extraPrefix",
234
+ "extraSuffix",
235
+ "label",
236
+ "isFloatingLabel",
237
+ "name",
238
+ "id",
239
+ "required",
240
+ "requiredMessage",
241
+ "style",
242
+ "children",
243
+ "initialValue",
244
+ "inputRef",
245
+ "message",
246
+ "type",
247
+ "variant",
248
+ "backgroundFill",
249
+ "disabled",
250
+ "onChange",
251
+ "onResetInput"
252
+ ]);
253
+ const [activeInput, setActiveInput] = useState(false);
254
+ const [inputValue, setInputValue] = useState("");
255
+ const [hasRequiredError, setHasRequiredError] = useState(false);
256
+ const textFieldId = id != null ? id : label.replaceAll(" ", "-").toLowerCase();
257
+ useEffect(() => {
258
+ if (!!initialValue) {
259
+ setInputValue(initialValue);
260
+ setHasRequiredError(false);
261
+ } else {
262
+ setInputValue("");
263
+ }
264
+ }, [initialValue]);
265
+ const handleChange = (event) => {
266
+ setInputValue(event.target.value);
267
+ setHasRequiredError(false);
268
+ if (onChange) {
269
+ onChange(event);
270
+ }
271
+ };
272
+ const onFocus = (event) => {
273
+ if (!rest.readOnly) {
274
+ setActiveInput(true);
275
+ }
276
+ if (rest.onFocus) {
277
+ rest.onFocus(event);
278
+ }
279
+ };
280
+ const onBlur = (event) => {
281
+ const isEmptyOrOnlySpaces = event.currentTarget.value.trim().length === 0;
282
+ if (isEmptyOrOnlySpaces) {
283
+ setActiveInput(false);
284
+ if (required && requiredMessage) {
285
+ setHasRequiredError(true);
286
+ }
287
+ }
288
+ if (rest.onBlur) {
289
+ rest.onBlur(event);
290
+ }
291
+ };
292
+ const handleResetInput = () => {
293
+ setInputValue("");
294
+ setActiveInput(false);
295
+ onResetInput();
296
+ };
297
+ const handleResetIconEnter = (event) => event.code === "Enter" && handleResetInput();
298
+ const handleExtraPreffixEnter = (event) => event.code === "Enter" && (extraPrefix == null ? void 0 : extraPrefix.onClick) && extraPrefix.onClick(inputValue);
299
+ const handleExtraSuffixEnter = (event) => event.code === "Enter" && (extraSuffix == null ? void 0 : extraSuffix.onClick) && extraSuffix.onClick(inputValue);
300
+ const messageColor = disabled ? "content.light" : "content.medium";
301
+ const showError = hasError || hasRequiredError;
302
+ const message = hasRequiredError ? requiredMessage != null ? requiredMessage : messageProp : messageProp;
303
+ const isActiveInput = activeInput || !!inputValue.trim();
304
+ const isSearchType = type === "search";
305
+ const extraPreffixOnClick = (extraPrefix == null ? void 0 : extraPrefix.onClick) ? extraPrefix.onClick : null;
306
+ const extraSuffixOnClick = (extraSuffix == null ? void 0 : extraSuffix.onClick) ? extraSuffix.onClick : null;
307
+ return /* @__PURE__ */ jsxs(
308
+ TextFieldStyled,
309
+ {
310
+ hasPrefix: !!extraPrefix,
311
+ isFloatingLabel,
312
+ style,
313
+ children: [
314
+ !isActiveInput || !isFloatingLabel || !isSearchType ? /* @__PURE__ */ jsx(
315
+ LabelField,
316
+ {
317
+ hasError: showError,
318
+ htmlFor: textFieldId,
319
+ isActive: isActiveInput || type === "date",
320
+ isDisabled: disabled,
321
+ isFloating: isFloatingLabel,
322
+ isRequired: required,
323
+ children: label
324
+ }
325
+ ) : null,
326
+ /* @__PURE__ */ jsxs(
327
+ InputWrapperStyled,
328
+ {
329
+ backgroundFill,
330
+ "data-testid": "input-wrapper",
331
+ hasError: showError,
332
+ isFloatingLabel,
333
+ variant,
334
+ children: [
335
+ (extraPrefix == null ? void 0 : extraPrefix.component) ? /* @__PURE__ */ jsx(
336
+ InputExtraPrefixStyled,
337
+ __spreadProps(__spreadValues({
338
+ "data-testid": "extra-preffix"
339
+ }, !!extraPreffixOnClick && {
340
+ tabIndex: 0,
341
+ onClick: () => extraPreffixOnClick(inputValue),
342
+ onKeyDown: handleExtraPreffixEnter
343
+ }), {
344
+ children: extraPrefix.component
345
+ })
346
+ ) : null,
347
+ /* @__PURE__ */ jsx(
348
+ InputFieldStyled,
349
+ __spreadProps(__spreadValues({
350
+ "data-error": showError,
351
+ "data-testid": "input-field",
352
+ disabled,
353
+ id: textFieldId,
354
+ isFloatingLabel,
355
+ isSearchType,
356
+ name: name != null ? name : textFieldId,
357
+ ref: inputRef,
358
+ type,
359
+ value: inputValue
360
+ }, rest), {
361
+ onBlur,
362
+ onChange: handleChange,
363
+ onFocus
364
+ })
365
+ ),
366
+ isSearchType && !!inputValue ? /* @__PURE__ */ jsx(
367
+ ResetInputIconStyled,
368
+ {
369
+ "data-testid": "reset-icon",
370
+ onKeyDown: handleResetIconEnter,
371
+ tabIndex: 0,
372
+ children: /* @__PURE__ */ jsx(IconButton, { onClick: handleResetInput, children: /* @__PURE__ */ jsx(Icon, { code: "close_small" }) })
373
+ }
374
+ ) : null,
375
+ (extraSuffix == null ? void 0 : extraSuffix.component) ? /* @__PURE__ */ jsx(
376
+ InputExtraSuffixStyled,
377
+ __spreadProps(__spreadValues({
378
+ "data-testid": "extra-suffix"
379
+ }, !!extraSuffixOnClick && {
380
+ tabIndex: 0,
381
+ onClick: () => extraSuffixOnClick(inputValue),
382
+ onKeyDown: handleExtraSuffixEnter
383
+ }), {
384
+ children: extraSuffix.component
385
+ })
386
+ ) : null
387
+ ]
388
+ }
389
+ ),
390
+ message ? /* @__PURE__ */ jsx(TextFieldMessageStyled, { children: /* @__PURE__ */ jsx(
391
+ Typography,
392
+ {
393
+ color: showError ? "error.default" : messageColor,
394
+ element: "span",
395
+ fontStyles: "body3",
396
+ children: message
397
+ }
398
+ ) }) : null,
399
+ children
400
+ ]
401
+ }
402
+ );
403
+ };
404
+ export {
405
+ InputExtraPrefixStyled,
406
+ InputExtraSuffixStyled,
407
+ InputFieldStyled,
408
+ InputWrapperStyled,
409
+ ResetInputIconStyled,
410
+ TextField,
411
+ TextFieldMessageStyled,
412
+ TextFieldStyled
413
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@dt-dds/react-text-field",
3
+ "version": "1.0.0-beta.49",
4
+ "license": "MIT",
5
+ "exports": {
6
+ ".": "./dist/index.js"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.mjs",
10
+ "types": "./dist/index.d.ts",
11
+ "files": [
12
+ "dist/**"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsup",
16
+ "dev": "tsup --watch",
17
+ "lint": "eslint --cache .",
18
+ "test": "jest",
19
+ "test:report": "open ./jest-coverage/lcov-report/index.html",
20
+ "test:update:snapshot": "jest -u"
21
+ },
22
+ "dependencies": {
23
+ "@dt-dds/react-core": "1.0.0-beta.41",
24
+ "@dt-dds/react-spinner": "1.0.0-beta.44",
25
+ "@dt-dds/react-label-field": "1.0.0-beta.37",
26
+ "@dt-dds/react-typography": "1.0.0-beta.32",
27
+ "@dt-dds/react-icon-button": "1.0.0-beta.9",
28
+ "@dt-dds/react-icon": "1.0.0-beta.42"
29
+ },
30
+ "devDependencies": {
31
+ "@babel/core": "^7.22.9",
32
+ "@babel/preset-env": "^7.22.9",
33
+ "@babel/preset-react": "^7.22.5",
34
+ "@babel/preset-typescript": "^7.23.3",
35
+ "@emotion/babel-plugin": "^11.11.0",
36
+ "@emotion/css": "^11.7.1",
37
+ "@emotion/jest": "^11.10.0",
38
+ "@emotion/react": "^11.8.2",
39
+ "@emotion/styled": "^11.8.1",
40
+ "@types/react": "^18.0.9",
41
+ "@types/react-dom": "^18.0.4",
42
+ "babel-loader": "^8.3.0",
43
+ "eslint-config-custom": "*",
44
+ "eslint-plugin-storybook": "^9.1.0",
45
+ "jest-config": "*",
46
+ "react": "^18.1.0",
47
+ "react-dom": "^18.2.0",
48
+ "tsconfig": "*",
49
+ "tsup": "^6.6.3",
50
+ "typescript": "^4.5.3"
51
+ },
52
+ "peerDependencies": {
53
+ "@emotion/css": "^11.7.1",
54
+ "@emotion/react": "^11.8.2",
55
+ "@emotion/styled": "^11.8.1",
56
+ "react": ">=17.0.2",
57
+ "react-dom": ">=17.0.2"
58
+ }
59
+ }