@rovula/ui 0.1.0 → 0.1.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.
- package/dist/cjs/bundle.css +65 -0
- package/dist/cjs/bundle.js +9261 -3
- package/dist/cjs/bundle.js.map +1 -1
- 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/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 +395 -0
- package/dist/cjs/types/components/PasswordInput/index.d.ts +2 -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/esm/bundle.css +65 -0
- package/dist/esm/bundle.js +9261 -3
- package/dist/esm/bundle.js.map +1 -1
- 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/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 +395 -0
- package/dist/esm/types/components/PasswordInput/index.d.ts +2 -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 +386 -2
- package/dist/index.js +4 -0
- package/dist/src/theme/global.css +117 -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/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
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import PasswordInput from "./PasswordInput";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/PasswordInput",
|
|
7
|
+
component: PasswordInput,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "fullscreen",
|
|
11
|
+
},
|
|
12
|
+
decorators: [
|
|
13
|
+
(Story) => (
|
|
14
|
+
<div className="p-5 flex w-full bg-[rgb(var(--base-bg-2))]">
|
|
15
|
+
<Story />
|
|
16
|
+
</div>
|
|
17
|
+
),
|
|
18
|
+
],
|
|
19
|
+
} satisfies Meta<typeof PasswordInput>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
export const Default = {
|
|
24
|
+
args: {
|
|
25
|
+
label: "Password",
|
|
26
|
+
placeholder: "Enter your password",
|
|
27
|
+
fullwidth: true,
|
|
28
|
+
},
|
|
29
|
+
render: (args) => (
|
|
30
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
31
|
+
<PasswordInput id="1" size="lg" {...args} />
|
|
32
|
+
<PasswordInput id="2" size="md" {...args} />
|
|
33
|
+
<PasswordInput id="3" size="sm" {...args} />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
} satisfies StoryObj;
|
|
37
|
+
|
|
38
|
+
export const WithHelperText = {
|
|
39
|
+
args: {
|
|
40
|
+
label: "Password",
|
|
41
|
+
placeholder: "Enter your password",
|
|
42
|
+
helperText: "Must be at least 8 characters",
|
|
43
|
+
fullwidth: true,
|
|
44
|
+
},
|
|
45
|
+
render: (args) => (
|
|
46
|
+
<div className="w-full max-w-md">
|
|
47
|
+
<PasswordInput id="1" size="md" {...args} />
|
|
48
|
+
</div>
|
|
49
|
+
),
|
|
50
|
+
} satisfies StoryObj;
|
|
51
|
+
|
|
52
|
+
export const WithError = {
|
|
53
|
+
args: {
|
|
54
|
+
label: "Password",
|
|
55
|
+
placeholder: "Enter your password",
|
|
56
|
+
error: true,
|
|
57
|
+
errorMessage: "Password is required",
|
|
58
|
+
fullwidth: true,
|
|
59
|
+
},
|
|
60
|
+
render: (args) => (
|
|
61
|
+
<div className="w-full max-w-md">
|
|
62
|
+
<PasswordInput id="1" size="md" {...args} />
|
|
63
|
+
</div>
|
|
64
|
+
),
|
|
65
|
+
} satisfies StoryObj;
|
|
66
|
+
|
|
67
|
+
export const Disabled = {
|
|
68
|
+
args: {
|
|
69
|
+
label: "Password",
|
|
70
|
+
value: "secret123",
|
|
71
|
+
disabled: true,
|
|
72
|
+
fullwidth: true,
|
|
73
|
+
},
|
|
74
|
+
render: (args) => (
|
|
75
|
+
<div className="w-full max-w-md">
|
|
76
|
+
<PasswordInput id="1" size="md" {...args} />
|
|
77
|
+
</div>
|
|
78
|
+
),
|
|
79
|
+
} satisfies StoryObj;
|
|
80
|
+
|
|
81
|
+
export const CustomIcons = {
|
|
82
|
+
args: {
|
|
83
|
+
label: "Password",
|
|
84
|
+
placeholder: "Enter your password",
|
|
85
|
+
fullwidth: true,
|
|
86
|
+
},
|
|
87
|
+
render: (args) => (
|
|
88
|
+
<div className="w-full max-w-md">
|
|
89
|
+
<PasswordInput
|
|
90
|
+
{...args}
|
|
91
|
+
id="1"
|
|
92
|
+
hideIcon={<span className="text-sm">👁</span>}
|
|
93
|
+
showIcon={<span className="text-sm">🙈</span>}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
),
|
|
97
|
+
} satisfies StoryObj;
|
|
98
|
+
|
|
99
|
+
export const WithoutToggle = {
|
|
100
|
+
args: {
|
|
101
|
+
label: "Password",
|
|
102
|
+
placeholder: "Enter your password",
|
|
103
|
+
showToggle: false,
|
|
104
|
+
fullwidth: true,
|
|
105
|
+
},
|
|
106
|
+
render: (args) => (
|
|
107
|
+
<div className="w-full max-w-md">
|
|
108
|
+
<PasswordInput id="1" size="md" {...args} />
|
|
109
|
+
</div>
|
|
110
|
+
),
|
|
111
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { forwardRef, useImperativeHandle, useRef, useState } from "react";
|
|
2
|
+
import TextInput, { InputProps } from "../TextInput/TextInput";
|
|
3
|
+
import Icon from "../Icon/Icon";
|
|
4
|
+
|
|
5
|
+
export type PasswordInputProps = Omit<InputProps, "type"> & {
|
|
6
|
+
/** Show toggle visibility button. Default: true */
|
|
7
|
+
showToggle?: boolean;
|
|
8
|
+
/** Icon when password is hidden (click to reveal). Default: Icon eye (lucide) */
|
|
9
|
+
hideIcon?: React.ReactNode;
|
|
10
|
+
/** Icon when password is visible (click to hide). Default: Icon eye-off (lucide) */
|
|
11
|
+
showIcon?: React.ReactNode;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(
|
|
15
|
+
({ showToggle = true, hasClearIcon = false, hideIcon, showIcon, endIcon, renderEndIcon, onClickEndIcon, ...props }, ref) => {
|
|
16
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
17
|
+
const [visible, setVisible] = useState(false);
|
|
18
|
+
|
|
19
|
+
useImperativeHandle(ref, () => inputRef?.current as HTMLInputElement);
|
|
20
|
+
|
|
21
|
+
const handleToggleVisibility = () => {
|
|
22
|
+
if (props.disabled) return;
|
|
23
|
+
setVisible((v) => !v);
|
|
24
|
+
inputRef.current?.focus();
|
|
25
|
+
onClickEndIcon?.();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const toggleIcon = visible
|
|
29
|
+
? showIcon ?? <Icon name="eye" type="lucide" size="inherit" className="size-full" aria-label="Hide password" />
|
|
30
|
+
: hideIcon ?? <Icon name="eye-closed" type="lucide" size="inherit" className="size-full" aria-label="Show password" />;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<TextInput
|
|
34
|
+
iconMode="flat"
|
|
35
|
+
{...props}
|
|
36
|
+
ref={inputRef}
|
|
37
|
+
type={visible ? "text" : "password"}
|
|
38
|
+
hasClearIcon={hasClearIcon}
|
|
39
|
+
endIcon={showToggle ? toggleIcon : endIcon}
|
|
40
|
+
renderEndIcon={renderEndIcon}
|
|
41
|
+
onClickEndIcon={showToggle ? handleToggleVisibility : onClickEndIcon}
|
|
42
|
+
autoComplete={props.autoComplete ?? "current-password"}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
PasswordInput.displayName = "PasswordInput";
|
|
49
|
+
|
|
50
|
+
export default PasswordInput;
|
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
|
}
|