@rovula/ui 0.1.0 → 0.1.2
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/cjs/bundle.css +129 -0
- package/dist/cjs/bundle.js +9255 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +1 -0
- package/dist/cjs/types/components/Footer/Footer.d.ts +21 -0
- package/dist/cjs/types/components/Footer/Footer.stories.d.ts +45 -0
- package/dist/cjs/types/components/Footer/index.d.ts +2 -0
- package/dist/cjs/types/components/Icon/Icon.d.ts +1 -1
- package/dist/cjs/types/components/Icon/Icon.stories.d.ts +9 -1
- package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +1 -0
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.d.ts +1 -0
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +2 -0
- package/dist/cjs/types/components/Navbar/Navbar.d.ts +5 -0
- package/dist/cjs/types/components/Navbar/Navbar.stories.d.ts +14 -0
- package/dist/cjs/types/components/PasswordInput/PasswordInput.d.ts +19 -0
- package/dist/cjs/types/components/PasswordInput/PasswordInput.stories.d.ts +396 -0
- package/dist/cjs/types/components/PasswordInput/index.d.ts +2 -0
- package/dist/cjs/types/components/Search/Search.stories.d.ts +1 -0
- package/dist/cjs/types/components/TextInput/TextInput.d.ts +2 -0
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +10 -0
- package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +15 -0
- package/dist/cjs/types/icons/index.d.ts +1 -0
- package/dist/cjs/types/icons/lucideIconNames.d.ts +9 -0
- package/dist/cjs/types/index.d.ts +7 -1
- package/dist/cjs/types/utils/colors.d.ts +330 -0
- package/dist/components/Footer/Footer.js +11 -0
- package/dist/components/Footer/Footer.stories.js +34 -0
- package/dist/components/Footer/index.js +2 -0
- package/dist/components/Icon/Icon.js +28 -11
- package/dist/components/Icon/Icon.stories.js +39 -0
- package/dist/components/Navbar/Navbar.js +18 -4
- package/dist/components/Navbar/Navbar.stories.js +16 -9
- package/dist/components/PasswordInput/PasswordInput.js +36 -0
- package/dist/components/PasswordInput/PasswordInput.stories.js +67 -0
- package/dist/components/PasswordInput/index.js +1 -0
- package/dist/components/TextArea/TextArea.styles.js +1 -1
- package/dist/components/TextInput/TextInput.js +33 -24
- package/dist/components/TextInput/TextInput.stories.js +14 -2
- package/dist/components/TextInput/TextInput.styles.js +25 -10
- package/dist/esm/bundle.css +129 -0
- package/dist/esm/bundle.js +9255 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +1 -0
- package/dist/esm/types/components/Footer/Footer.d.ts +21 -0
- package/dist/esm/types/components/Footer/Footer.stories.d.ts +45 -0
- package/dist/esm/types/components/Footer/index.d.ts +2 -0
- package/dist/esm/types/components/Icon/Icon.d.ts +1 -1
- package/dist/esm/types/components/Icon/Icon.stories.d.ts +9 -1
- package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +1 -0
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.d.ts +1 -0
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +2 -0
- package/dist/esm/types/components/Navbar/Navbar.d.ts +5 -0
- package/dist/esm/types/components/Navbar/Navbar.stories.d.ts +14 -0
- package/dist/esm/types/components/PasswordInput/PasswordInput.d.ts +19 -0
- package/dist/esm/types/components/PasswordInput/PasswordInput.stories.d.ts +396 -0
- package/dist/esm/types/components/PasswordInput/index.d.ts +2 -0
- package/dist/esm/types/components/Search/Search.stories.d.ts +1 -0
- package/dist/esm/types/components/TextInput/TextInput.d.ts +2 -0
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +10 -0
- package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +15 -0
- package/dist/esm/types/icons/index.d.ts +1 -0
- package/dist/esm/types/icons/lucideIconNames.d.ts +9 -0
- package/dist/esm/types/index.d.ts +7 -1
- package/dist/esm/types/utils/colors.d.ts +330 -0
- package/dist/icons/index.js +1 -0
- package/dist/icons/lucideIconNames.js +12 -0
- package/dist/index.d.ts +389 -2
- package/dist/index.js +4 -0
- package/dist/src/theme/global.css +200 -24
- package/dist/utils/colors.js +369 -0
- package/package.json +2 -1
- package/src/components/Footer/Footer.stories.tsx +119 -0
- package/src/components/Footer/Footer.tsx +122 -0
- package/src/components/Footer/index.ts +3 -0
- package/src/components/Icon/Icon.stories.tsx +89 -0
- package/src/components/Icon/Icon.tsx +44 -23
- package/src/components/Navbar/Navbar.stories.tsx +109 -55
- package/src/components/Navbar/Navbar.tsx +41 -3
- package/src/components/PasswordInput/PasswordInput.stories.tsx +111 -0
- package/src/components/PasswordInput/PasswordInput.tsx +50 -0
- package/src/components/PasswordInput/index.ts +2 -0
- package/src/components/TextArea/TextArea.styles.ts +1 -1
- package/src/components/TextInput/TextInput.stories.tsx +60 -2
- package/src/components/TextInput/TextInput.styles.ts +36 -19
- package/src/components/TextInput/TextInput.tsx +83 -55
- package/src/icons/index.ts +1 -0
- package/src/icons/lucideIconNames.ts +14 -0
- package/src/index.ts +15 -1
- package/src/theme/themes/skyller/typography.css +24 -24
- package/src/theme/tokens/baseline.css +1 -0
- package/src/theme/tokens/components/footer.css +9 -0
- package/src/theme/tokens/components/navbar.css +2 -1
- package/src/types/lucide-react.d.ts +5 -0
- package/src/utils/colors.ts +383 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef } from "react";
|
|
1
|
+
import React, { useRef, useState } from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import TextInput from "./TextInput";
|
|
4
4
|
import { CalendarIcon } from "@heroicons/react/16/solid";
|
|
@@ -15,7 +15,7 @@ const meta = {
|
|
|
15
15
|
},
|
|
16
16
|
decorators: [
|
|
17
17
|
(Story) => (
|
|
18
|
-
<div className="p-5 flex w-full bg-[
|
|
18
|
+
<div className="p-5 flex h-full w-full bg-[var(--base-color-popup)] ">
|
|
19
19
|
<Story />
|
|
20
20
|
</div>
|
|
21
21
|
),
|
|
@@ -207,3 +207,61 @@ export const CustomIcon = {
|
|
|
207
207
|
);
|
|
208
208
|
},
|
|
209
209
|
} satisfies StoryObj;
|
|
210
|
+
|
|
211
|
+
const KeepFooterSpaceDemo = () => {
|
|
212
|
+
const [hasError, setHasError] = useState(false);
|
|
213
|
+
return (
|
|
214
|
+
<div className="flex flex-col gap-8 w-full max-w-md">
|
|
215
|
+
<p className="text-sm text-text-grey-dark">
|
|
216
|
+
Use <code>keepFooterSpace</code> to always reserve space for the
|
|
217
|
+
footer/helper area, preventing layout shift when an error or helper text
|
|
218
|
+
is shown or hidden.
|
|
219
|
+
</p>
|
|
220
|
+
<div className="flex flex-col gap-4">
|
|
221
|
+
<label className="flex items-center gap-2 cursor-pointer">
|
|
222
|
+
<input
|
|
223
|
+
type="checkbox"
|
|
224
|
+
checked={hasError}
|
|
225
|
+
onChange={(e) => setHasError(e.target.checked)}
|
|
226
|
+
/>
|
|
227
|
+
Show error message
|
|
228
|
+
</label>
|
|
229
|
+
<div className="flex flex-col">
|
|
230
|
+
<div>
|
|
231
|
+
<h4 className="text-sm font-medium mb-2 text-text-grey-dark">
|
|
232
|
+
With keepFooterSpace (layout stays stable)
|
|
233
|
+
</h4>
|
|
234
|
+
<TextInput
|
|
235
|
+
id="with-keep"
|
|
236
|
+
label="Email"
|
|
237
|
+
keepFooterSpace
|
|
238
|
+
error={hasError}
|
|
239
|
+
errorMessage={hasError ? "Please enter a valid email address" : undefined}
|
|
240
|
+
/>
|
|
241
|
+
</div>
|
|
242
|
+
<div>
|
|
243
|
+
<h4 className="text-sm font-medium mb-2 text-text-grey-dark">
|
|
244
|
+
Without keepFooterSpace (layout shifts when error appears)
|
|
245
|
+
</h4>
|
|
246
|
+
<TextInput
|
|
247
|
+
id="no-keep"
|
|
248
|
+
label="Email"
|
|
249
|
+
error={hasError}
|
|
250
|
+
errorMessage={hasError ? "Please enter a valid email address" : undefined}
|
|
251
|
+
/>
|
|
252
|
+
</div>
|
|
253
|
+
<div></div>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export const KeepFooterSpace = {
|
|
261
|
+
args: {
|
|
262
|
+
label: "Email",
|
|
263
|
+
fullwidth: true,
|
|
264
|
+
keepFooterSpace: true,
|
|
265
|
+
},
|
|
266
|
+
render: () => <KeepFooterSpaceDemo />,
|
|
267
|
+
} satisfies StoryObj;
|
|
@@ -39,7 +39,7 @@ export const inputVariant = cva(
|
|
|
39
39
|
],
|
|
40
40
|
},
|
|
41
41
|
error: {
|
|
42
|
-
true: "ring-input-error focus:ring-input-error",
|
|
42
|
+
true: "ring-input-error hover:ring-input-error focus:ring-input-error",
|
|
43
43
|
},
|
|
44
44
|
hasClearIcon: {
|
|
45
45
|
true: "",
|
|
@@ -132,13 +132,13 @@ export const inputVariant = cva(
|
|
|
132
132
|
leftSectionIcon: false, // TODO function style
|
|
133
133
|
rightSectionIcon: false,
|
|
134
134
|
},
|
|
135
|
-
}
|
|
135
|
+
},
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
export const labelVariant = cva(
|
|
139
139
|
[
|
|
140
140
|
"absolute block duration-450 transition-all px-[2px] text-input-default-text",
|
|
141
|
-
"peer-focus:text-input-
|
|
141
|
+
"peer-focus:text-input-default-text peer-focus:bg-input-label-bg", // TODO bg
|
|
142
142
|
],
|
|
143
143
|
{
|
|
144
144
|
variants: {
|
|
@@ -337,11 +337,11 @@ export const labelVariant = cva(
|
|
|
337
337
|
hasLeftSectionIcon: false,
|
|
338
338
|
isFloatingLabel: true,
|
|
339
339
|
},
|
|
340
|
-
}
|
|
340
|
+
},
|
|
341
341
|
);
|
|
342
342
|
|
|
343
343
|
export const helperTextVariant = cva(
|
|
344
|
-
["
|
|
344
|
+
["typography-small1 flex flex-row items-center gap-1"],
|
|
345
345
|
{
|
|
346
346
|
variants: {
|
|
347
347
|
size: {
|
|
@@ -362,12 +362,22 @@ export const helperTextVariant = cva(
|
|
|
362
362
|
disabled: false,
|
|
363
363
|
error: false,
|
|
364
364
|
},
|
|
365
|
-
}
|
|
365
|
+
},
|
|
366
366
|
);
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
const iconInteractiveColorStateClasses = [
|
|
369
|
+
"fill-input-default-text",
|
|
370
|
+
"peer-hover:fill-input-filled-text peer-focus:fill-input-filled-text peer-active:fill-input-filled-text",
|
|
371
|
+
"peer-disabled:fill-input-disable-stroke",
|
|
372
|
+
"[&_svg]:text-input-default-text",
|
|
373
|
+
"peer-hover:[&_svg]:text-input-filled-text peer-focus:[&_svg]:text-input-filled-text peer-active:[&_svg]:text-input-filled-text",
|
|
374
|
+
"peer-disabled:[&_svg]:text-input-disable-stroke",
|
|
375
|
+
];
|
|
376
|
+
|
|
377
|
+
export const inlineEndIconWrapperVariant = cva(
|
|
369
378
|
[
|
|
370
379
|
"absolute inset-y-0 right-0 items-center justify-center hidden peer-focus:flex",
|
|
380
|
+
...iconInteractiveColorStateClasses,
|
|
371
381
|
],
|
|
372
382
|
{
|
|
373
383
|
variants: {
|
|
@@ -380,11 +390,14 @@ export const iconWrapperVariant = cva(
|
|
|
380
390
|
defaultVariants: {
|
|
381
391
|
size: "md",
|
|
382
392
|
},
|
|
383
|
-
}
|
|
393
|
+
},
|
|
384
394
|
);
|
|
385
395
|
|
|
386
|
-
export const
|
|
387
|
-
[
|
|
396
|
+
export const inlineStartIconWrapperVariant = cva(
|
|
397
|
+
[
|
|
398
|
+
"absolute inset-y-0 left-0 items-center justify-center flex",
|
|
399
|
+
...iconInteractiveColorStateClasses,
|
|
400
|
+
],
|
|
388
401
|
{
|
|
389
402
|
variants: {
|
|
390
403
|
size: {
|
|
@@ -396,13 +409,11 @@ export const iconSearchWrapperVariant = cva(
|
|
|
396
409
|
defaultVariants: {
|
|
397
410
|
size: "md",
|
|
398
411
|
},
|
|
399
|
-
}
|
|
412
|
+
},
|
|
400
413
|
);
|
|
401
414
|
|
|
402
|
-
export const
|
|
403
|
-
[
|
|
404
|
-
"cursor-pointer z-50 fill-input-active-stroke hover:fill-input-default-text",
|
|
405
|
-
],
|
|
415
|
+
export const iconActionVariant = cva(
|
|
416
|
+
["cursor-pointer z-50"],
|
|
406
417
|
{
|
|
407
418
|
variants: {
|
|
408
419
|
size: {
|
|
@@ -414,14 +425,14 @@ export const iconVariant = cva(
|
|
|
414
425
|
defaultVariants: {
|
|
415
426
|
size: "md",
|
|
416
427
|
},
|
|
417
|
-
}
|
|
428
|
+
},
|
|
418
429
|
);
|
|
419
430
|
|
|
420
|
-
export const
|
|
431
|
+
export const segmentedIconWrapperVariant = cva(
|
|
421
432
|
[
|
|
422
433
|
"cursor-pointer",
|
|
423
434
|
"absolute items-center justify-center flex",
|
|
424
|
-
|
|
435
|
+
...iconInteractiveColorStateClasses,
|
|
425
436
|
],
|
|
426
437
|
{
|
|
427
438
|
variants: {
|
|
@@ -499,5 +510,11 @@ export const sectionIconWrapperVariant = cva(
|
|
|
499
510
|
error: false,
|
|
500
511
|
position: "end",
|
|
501
512
|
},
|
|
502
|
-
}
|
|
513
|
+
},
|
|
503
514
|
);
|
|
515
|
+
|
|
516
|
+
// Backward-compatible aliases (can be removed in a future major version)
|
|
517
|
+
export const iconWrapperVariant = inlineEndIconWrapperVariant;
|
|
518
|
+
export const iconSearchWrapperVariant = inlineStartIconWrapperVariant;
|
|
519
|
+
export const iconVariant = iconActionVariant;
|
|
520
|
+
export const sectionIconWrapperVariant = segmentedIconWrapperVariant;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
FC,
|
|
3
2
|
ReactNode,
|
|
4
3
|
forwardRef,
|
|
5
4
|
useCallback,
|
|
@@ -9,18 +8,18 @@ import React, {
|
|
|
9
8
|
} from "react";
|
|
10
9
|
import {
|
|
11
10
|
helperTextVariant,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
iconActionVariant,
|
|
12
|
+
inlineEndIconWrapperVariant,
|
|
13
|
+
inlineStartIconWrapperVariant,
|
|
15
14
|
inputVariant,
|
|
16
15
|
labelVariant,
|
|
17
|
-
|
|
16
|
+
segmentedIconWrapperVariant,
|
|
18
17
|
} from "./TextInput.styles";
|
|
19
18
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from "
|
|
19
|
+
CircleAlert,
|
|
20
|
+
CircleX,
|
|
21
|
+
Search,
|
|
22
|
+
} from "lucide-react";
|
|
24
23
|
import { cn } from "@/utils/cn";
|
|
25
24
|
|
|
26
25
|
export type InputProps = {
|
|
@@ -39,6 +38,7 @@ export type InputProps = {
|
|
|
39
38
|
required?: boolean;
|
|
40
39
|
isFloatingLabel?: boolean;
|
|
41
40
|
keepCloseIconOnValue?: boolean;
|
|
41
|
+
keepFooterSpace?: boolean;
|
|
42
42
|
hasClearIcon?: boolean;
|
|
43
43
|
hasSearchIcon?: boolean;
|
|
44
44
|
startIcon?: ReactNode;
|
|
@@ -76,6 +76,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
76
76
|
required = true,
|
|
77
77
|
isFloatingLabel = true,
|
|
78
78
|
keepCloseIconOnValue = false,
|
|
79
|
+
keepFooterSpace = true,
|
|
79
80
|
hasClearIcon = true,
|
|
80
81
|
hasSearchIcon = false,
|
|
81
82
|
startIcon,
|
|
@@ -118,20 +119,26 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
118
119
|
hasLeftSectionIcon: iconMode === "solid" ? hasLeftSectionIcon : false,
|
|
119
120
|
isFloatingLabel,
|
|
120
121
|
});
|
|
121
|
-
const helperTextClassname = helperTextVariant({
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
const helperTextClassname = helperTextVariant({
|
|
123
|
+
size,
|
|
124
|
+
error,
|
|
125
|
+
disabled,
|
|
126
|
+
});
|
|
127
|
+
const inlineEndIconWrapperClassname = inlineEndIconWrapperVariant({ size });
|
|
128
|
+
const inlineStartIconWrapperClassname = inlineStartIconWrapperVariant({
|
|
129
|
+
size,
|
|
130
|
+
});
|
|
131
|
+
const iconActionClassname = iconActionVariant({ size });
|
|
125
132
|
|
|
126
133
|
// TODO wait for clearify aboutm start,end, search and clearIcon with iconMode
|
|
127
134
|
|
|
128
|
-
const
|
|
135
|
+
const startSegmentIconWrapperClassname = segmentedIconWrapperVariant({
|
|
129
136
|
size,
|
|
130
137
|
rounded,
|
|
131
138
|
error,
|
|
132
139
|
position: "start",
|
|
133
140
|
});
|
|
134
|
-
const
|
|
141
|
+
const endSegmentIconWrapperClassname = segmentedIconWrapperVariant({
|
|
135
142
|
size,
|
|
136
143
|
rounded,
|
|
137
144
|
error,
|
|
@@ -176,7 +183,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
176
183
|
return (
|
|
177
184
|
<div
|
|
178
185
|
className={cn(
|
|
179
|
-
|
|
186
|
+
inlineStartIconWrapperClassname,
|
|
180
187
|
"flex",
|
|
181
188
|
classes?.iconSearchWrapper
|
|
182
189
|
)}
|
|
@@ -190,12 +197,12 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
190
197
|
return (
|
|
191
198
|
<div
|
|
192
199
|
className={cn(
|
|
193
|
-
|
|
200
|
+
inlineStartIconWrapperClassname,
|
|
194
201
|
classes?.iconSearchWrapper
|
|
195
202
|
)}
|
|
196
203
|
>
|
|
197
204
|
<div
|
|
198
|
-
className={cn(
|
|
205
|
+
className={cn(iconActionClassname, classes?.icon)}
|
|
199
206
|
onClick={handleOnClickLeftSectionIcon}
|
|
200
207
|
>
|
|
201
208
|
{startIcon}
|
|
@@ -206,7 +213,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
206
213
|
|
|
207
214
|
return (
|
|
208
215
|
<div
|
|
209
|
-
className={cn(
|
|
216
|
+
className={cn(
|
|
217
|
+
startSegmentIconWrapperClassname,
|
|
218
|
+
classes?.startIconWrapper
|
|
219
|
+
)}
|
|
210
220
|
onClick={handleOnClickLeftSectionIcon}
|
|
211
221
|
>
|
|
212
222
|
{startIcon}
|
|
@@ -216,9 +226,9 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
216
226
|
hasLeftSectionIcon,
|
|
217
227
|
startIcon,
|
|
218
228
|
iconMode,
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
229
|
+
inlineStartIconWrapperClassname,
|
|
230
|
+
startSegmentIconWrapperClassname,
|
|
231
|
+
iconActionClassname,
|
|
222
232
|
renderStartIcon,
|
|
223
233
|
handleOnClickLeftSectionIcon,
|
|
224
234
|
]);
|
|
@@ -229,7 +239,11 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
229
239
|
if (renderEndIcon) {
|
|
230
240
|
return (
|
|
231
241
|
<div
|
|
232
|
-
className={cn(
|
|
242
|
+
className={cn(
|
|
243
|
+
inlineEndIconWrapperClassname,
|
|
244
|
+
"flex",
|
|
245
|
+
classes?.iconWrapper
|
|
246
|
+
)}
|
|
233
247
|
>
|
|
234
248
|
{renderEndIcon()}
|
|
235
249
|
</div>
|
|
@@ -239,10 +253,14 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
239
253
|
if (iconMode === "flat") {
|
|
240
254
|
return (
|
|
241
255
|
<div
|
|
242
|
-
className={cn(
|
|
256
|
+
className={cn(
|
|
257
|
+
inlineEndIconWrapperClassname,
|
|
258
|
+
"flex",
|
|
259
|
+
classes?.iconWrapper
|
|
260
|
+
)}
|
|
243
261
|
>
|
|
244
262
|
<div
|
|
245
|
-
className={cn(
|
|
263
|
+
className={cn(iconActionClassname, classes?.icon)}
|
|
246
264
|
onClick={handleOnClickRightSectionIcon}
|
|
247
265
|
>
|
|
248
266
|
{endIcon}
|
|
@@ -253,7 +271,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
253
271
|
|
|
254
272
|
return (
|
|
255
273
|
<div
|
|
256
|
-
className={cn(
|
|
274
|
+
className={cn(endSegmentIconWrapperClassname, classes?.endIconWrapper)}
|
|
257
275
|
onClick={handleOnClickRightSectionIcon}
|
|
258
276
|
>
|
|
259
277
|
{endIcon}
|
|
@@ -263,9 +281,9 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
263
281
|
hasRightSectionIcon,
|
|
264
282
|
endIcon,
|
|
265
283
|
iconMode,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
284
|
+
inlineEndIconWrapperClassname,
|
|
285
|
+
endSegmentIconWrapperClassname,
|
|
286
|
+
iconActionClassname,
|
|
269
287
|
renderEndIcon,
|
|
270
288
|
handleOnClickRightSectionIcon,
|
|
271
289
|
]);
|
|
@@ -273,18 +291,6 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
273
291
|
return (
|
|
274
292
|
<div className={`inline-flex flex-col ${fullwidth ? "w-full" : ""}`}>
|
|
275
293
|
<div className="relative">
|
|
276
|
-
{hasSearchIcon && !hasLeftSectionIcon && (
|
|
277
|
-
<div
|
|
278
|
-
className={cn(
|
|
279
|
-
iconSearchWrapperClassname,
|
|
280
|
-
classes?.iconSearchWrapper
|
|
281
|
-
)}
|
|
282
|
-
>
|
|
283
|
-
<MagnifyingGlassIcon
|
|
284
|
-
className={cn(iconClassname, classes?.icon)}
|
|
285
|
-
/>
|
|
286
|
-
</div>
|
|
287
|
-
)}
|
|
288
294
|
<input
|
|
289
295
|
{...props}
|
|
290
296
|
placeholder=" "
|
|
@@ -294,19 +300,33 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
294
300
|
disabled={disabled}
|
|
295
301
|
className={cn(inputClassname, props.className)}
|
|
296
302
|
/>
|
|
303
|
+
{hasSearchIcon && !hasLeftSectionIcon && (
|
|
304
|
+
<div
|
|
305
|
+
className={cn(
|
|
306
|
+
inlineStartIconWrapperClassname,
|
|
307
|
+
classes?.iconSearchWrapper
|
|
308
|
+
)}
|
|
309
|
+
>
|
|
310
|
+
<Search className={cn(iconActionClassname, classes?.icon)} />
|
|
311
|
+
</div>
|
|
312
|
+
)}
|
|
297
313
|
{startIconElement}
|
|
298
314
|
|
|
299
315
|
{hasClearIcon && !hasRightSectionIcon && (
|
|
300
316
|
<div
|
|
301
|
-
className={cn(
|
|
317
|
+
className={cn(inlineEndIconWrapperClassname, classes?.iconWrapper)}
|
|
302
318
|
style={{
|
|
303
319
|
display:
|
|
304
320
|
keepCloseIconOnValue && props.value ? "flex" : undefined,
|
|
305
321
|
}}
|
|
306
322
|
>
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
323
|
+
<CircleX
|
|
324
|
+
className={cn(
|
|
325
|
+
iconActionClassname,
|
|
326
|
+
// 'fill-none stroke-current',
|
|
327
|
+
// "fill-none stroke-input-default-text hover:stroke-input-filled-text active:stroke-input-filled-text",
|
|
328
|
+
classes?.icon
|
|
329
|
+
)}
|
|
310
330
|
onMouseDown={handleClearInput}
|
|
311
331
|
/>
|
|
312
332
|
</div>
|
|
@@ -317,7 +337,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
317
337
|
{label}{" "}
|
|
318
338
|
{required && (
|
|
319
339
|
<span
|
|
320
|
-
className={cn("text-error", {
|
|
340
|
+
className={cn("text-input-error", {
|
|
321
341
|
"text-input-disable-text": disabled,
|
|
322
342
|
})}
|
|
323
343
|
>
|
|
@@ -326,16 +346,24 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
326
346
|
)}
|
|
327
347
|
</label>
|
|
328
348
|
</div>
|
|
329
|
-
{(errorMessage || helperText) && (
|
|
349
|
+
{(errorMessage || helperText || keepFooterSpace) && (
|
|
330
350
|
<span className={helperTextClassname}>
|
|
331
|
-
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
351
|
+
{(errorMessage || helperText) && (
|
|
352
|
+
<span className="h-full shrink-0">
|
|
353
|
+
<CircleAlert
|
|
354
|
+
width={14}
|
|
355
|
+
height={14}
|
|
356
|
+
className={cn(
|
|
357
|
+
"fill-none",
|
|
358
|
+
error ? "stroke-input-error" : "stroke-input-filled-text"
|
|
359
|
+
)}
|
|
360
|
+
/>
|
|
361
|
+
</span>
|
|
362
|
+
)}
|
|
363
|
+
{keepFooterSpace && !error && !helperText && (
|
|
364
|
+
<span className="block min-h-[14px]" aria-hidden />
|
|
365
|
+
)}
|
|
366
|
+
{(error ? errorMessage : helperText) || ''}
|
|
339
367
|
</span>
|
|
340
368
|
)}
|
|
341
369
|
</div>
|
package/src/icons/index.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get all available Lucide icon names (kebab-case).
|
|
3
|
+
* Use for autocomplete, validation, or browsing.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const names = await getLucideIconNames();
|
|
7
|
+
* names.includes("eye-closed"); // true
|
|
8
|
+
*/
|
|
9
|
+
export async function getLucideIconNames(): Promise<string[]> {
|
|
10
|
+
const { default: dynamicIconImports } = await import(
|
|
11
|
+
"lucide-react/dynamicIconImports"
|
|
12
|
+
);
|
|
13
|
+
return Object.keys(dynamicIconImports);
|
|
14
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import "./icons/iconConfig";
|
|
|
6
6
|
export { default as Button } from "./components/Button/Button";
|
|
7
7
|
export { default as TextInput } from "./components/TextInput/TextInput";
|
|
8
8
|
export { default as MaskedTextInput } from "./components/MaskedTextInput";
|
|
9
|
+
export { default as PasswordInput } from "./components/PasswordInput";
|
|
9
10
|
export { NumberInput } from "./components/NumberInput/NumberInput";
|
|
10
11
|
export { default as TextArea } from "./components/TextArea/TextArea";
|
|
11
12
|
export { default as Text } from "./components/Text/Text";
|
|
@@ -15,6 +16,7 @@ export { Checkbox } from "./components/Checkbox/Checkbox";
|
|
|
15
16
|
export { Label } from "./components/Label/Label";
|
|
16
17
|
export { Input } from "./components/Input/Input";
|
|
17
18
|
export { Navbar } from "./components/Navbar";
|
|
19
|
+
export { Footer } from "./components/Footer";
|
|
18
20
|
export { default as ActionButton } from "./components/ActionButton/ActionButton";
|
|
19
21
|
export { Avatar, AvatarGroup } from "./components/Avatar";
|
|
20
22
|
export { Collapsible } from "./components/Collapsible";
|
|
@@ -50,6 +52,7 @@ export * from "./components/RadioGroup/RadioGroup";
|
|
|
50
52
|
// Export component types
|
|
51
53
|
export type { ButtonProps } from "./components/Button/Button";
|
|
52
54
|
export type { InputProps } from "./components/TextInput/TextInput";
|
|
55
|
+
export type { PasswordInputProps } from "./components/PasswordInput/PasswordInput";
|
|
53
56
|
export type {
|
|
54
57
|
MaskedTextInputProps,
|
|
55
58
|
MaskRule,
|
|
@@ -57,7 +60,8 @@ export type {
|
|
|
57
60
|
export type { NumberInputProps } from "./components/NumberInput/NumberInput";
|
|
58
61
|
export type { TextAreaProps } from "./components/TextArea/TextArea";
|
|
59
62
|
export type { DropdownProps, Options } from "./components/Dropdown/Dropdown";
|
|
60
|
-
export type { NavbarProps } from "./components/Navbar/Navbar";
|
|
63
|
+
export type { NavbarProps, NavbarVariant } from "./components/Navbar/Navbar";
|
|
64
|
+
export type { FooterProps, FooterVariant } from "./components/Footer/Footer";
|
|
61
65
|
export type { AvatarProps } from "./components/Avatar/Avatar";
|
|
62
66
|
export type { AvatarGroupProps } from "./components/Avatar/AvatarGroup";
|
|
63
67
|
|
|
@@ -75,6 +79,16 @@ export * from "./hooks";
|
|
|
75
79
|
|
|
76
80
|
export { cn } from "./utils/cn";
|
|
77
81
|
|
|
82
|
+
export {
|
|
83
|
+
srgbToHex,
|
|
84
|
+
getThemeColor,
|
|
85
|
+
getThemeColors,
|
|
86
|
+
THEME_COLOR_KEYS,
|
|
87
|
+
type ThemeColorKey,
|
|
88
|
+
} from "./utils/colors";
|
|
89
|
+
|
|
90
|
+
export { getLucideIconNames } from "./icons/lucideIconNames";
|
|
91
|
+
|
|
78
92
|
// const mainPreset = require("./theme/main-preset");
|
|
79
93
|
|
|
80
94
|
// export { mainPreset };
|
|
@@ -3,28 +3,28 @@
|
|
|
3
3
|
/* Typography */
|
|
4
4
|
/* ------------------------------------------------------------------ */
|
|
5
5
|
|
|
6
|
-
--h1-family: "
|
|
7
|
-
--h2-family: "
|
|
8
|
-
--h3-family: "
|
|
9
|
-
--h4-family: "
|
|
10
|
-
--h5-family: "
|
|
11
|
-
--h6-family: "
|
|
12
|
-
--subtitle2-family: "
|
|
13
|
-
--subtitle3-family: "
|
|
14
|
-
--subtitle4-family: "
|
|
15
|
-
--subtitle5-family: "
|
|
16
|
-
--subtitle6-family: "
|
|
17
|
-
--body1-family: "
|
|
18
|
-
--body2-family: "
|
|
19
|
-
--body3-family: "
|
|
20
|
-
--body4-family: "
|
|
21
|
-
--small1-family: "
|
|
22
|
-
--small2-family: "
|
|
23
|
-
--small3-family: "
|
|
24
|
-
--small4-family: "
|
|
25
|
-
--small5-family: "
|
|
26
|
-
--label-label1-family: "
|
|
27
|
-
--label-label2-family: "
|
|
28
|
-
--button-button-l-family: "
|
|
29
|
-
--button-button-ms-family: "
|
|
6
|
+
--h1-family: "Montserrat";
|
|
7
|
+
--h2-family: "Montserrat";
|
|
8
|
+
--h3-family: "Montserrat";
|
|
9
|
+
--h4-family: "Montserrat";
|
|
10
|
+
--h5-family: "Montserrat";
|
|
11
|
+
--h6-family: "Montserrat";
|
|
12
|
+
--subtitle2-family: "Montserrat";
|
|
13
|
+
--subtitle3-family: "Montserrat";
|
|
14
|
+
--subtitle4-family: "Montserrat";
|
|
15
|
+
--subtitle5-family: "Montserrat";
|
|
16
|
+
--subtitle6-family: "Montserrat";
|
|
17
|
+
--body1-family: "Montserrat";
|
|
18
|
+
--body2-family: "Montserrat";
|
|
19
|
+
--body3-family: "Montserrat";
|
|
20
|
+
--body4-family: "Montserrat";
|
|
21
|
+
--small1-family: "Montserrat";
|
|
22
|
+
--small2-family: "Montserrat";
|
|
23
|
+
--small3-family: "Montserrat";
|
|
24
|
+
--small4-family: "Montserrat";
|
|
25
|
+
--small5-family: "Montserrat";
|
|
26
|
+
--label-label1-family: "Montserrat";
|
|
27
|
+
--label-label2-family: "Montserrat";
|
|
28
|
+
--button-button-l-family: "Montserrat";
|
|
29
|
+
--button-button-ms-family: "Montserrat";
|
|
30
30
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* Footer */
|
|
3
|
+
--footer-height: 58px;
|
|
4
|
+
--footer-height-simple: 48px;
|
|
5
|
+
--footer-bg-color: var(--state-color-primary-default);
|
|
6
|
+
--footer-text-color: var(--primary-foreground);
|
|
7
|
+
--footer-border-color: var(--primary-foreground);
|
|
8
|
+
--footer-gap: 16px;
|
|
9
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
|
|
2
|
+
/* Navbar */
|
|
3
3
|
--navbar-height: 58px;
|
|
4
4
|
--navbar-bg-color: var(--primary-default);
|
|
5
5
|
--navbar-text-color: var(--primary-foreground);
|
|
6
6
|
--navbar-border-color: var(--primary-foreground);
|
|
7
7
|
--navbar-gap: 16px;
|
|
8
|
+
--navbar-shadow-scrolled: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
8
9
|
}
|