ml-ui-lib 1.0.30 → 1.0.32

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.
@@ -1,3 +1,4 @@
1
+ /* === Base Button === */
1
2
  .btn {
2
3
  border: none;
3
4
  border-radius: 25px;
@@ -5,48 +6,199 @@
5
6
  cursor: pointer;
6
7
  font-size: 16px;
7
8
  font-weight: 500;
8
- /* margin: 10px; */
9
- }
10
-
11
- .btn:hover {
12
- transform: translateY(-3px);
9
+ transition: all 0.2s ease;
10
+ position: relative;
11
+ display: inline-flex;
12
+ align-items: center;
13
+ justify-content: center;
14
+ min-width: 120px;
15
+ overflow: hidden;
13
16
  }
14
17
 
15
18
  /* Disabled state */
16
19
  .btn:disabled {
17
20
  opacity: 0.6;
18
21
  cursor: not-allowed;
19
- transform: none; /* disable hover translate */
20
22
  }
21
23
 
22
24
  /* Variants */
23
25
  .btn-default {
24
26
  background: #ffffff;
25
27
  color: #5d5d5d;
26
- border: solid 1px #5d5d5d;
28
+ border: 1px solid #5d5d5d;
27
29
  }
28
30
 
29
31
  .btn-white {
30
32
  background: #ffffff;
31
33
  color: #5d5d5d;
32
- border: solid 1px #ffffff;
34
+ border: 1px solid #ffffff;
33
35
  }
34
36
 
35
37
  .btn-red {
36
38
  background: #ff0000;
37
39
  color: #ffffff;
38
- border: solid 1px #ff0000;
40
+ border: 1px solid #ff0000;
39
41
  }
40
42
 
41
43
  .btn-black {
42
44
  background: #333333;
43
45
  color: #ffffff;
44
- border: solid 1px #333;
45
-
46
+ border: 1px solid #333;
46
47
  }
47
48
 
48
- .btn-tranparent-white {
49
+ .btn-transparent-white {
49
50
  background: transparent;
50
51
  color: #fff;
51
- border: solid 1px #fff;
52
- }
52
+ border: 1px solid #fff;
53
+ }
54
+
55
+ /* Loading spinner */
56
+ .btn-loader {
57
+ display: flex;
58
+ gap: 4px;
59
+ align-items: center;
60
+ justify-content: center;
61
+ height: 25px;
62
+ }
63
+
64
+ .btn-loader span {
65
+ width: 0.5em;
66
+ height: 0.5em;
67
+ background: currentColor;
68
+ border-radius: 50%;
69
+ animation: pulse 1.2s infinite ease-in-out;
70
+ }
71
+
72
+ .btn-loader span:nth-child(2) {
73
+ animation-delay: 0.15s;
74
+ }
75
+
76
+ .btn-loader span:nth-child(3) {
77
+ animation-delay: 0.3s;
78
+ }
79
+
80
+ @keyframes pulse {
81
+
82
+ 0%,
83
+ 80%,
84
+ 100% {
85
+ transform: scale(0.6);
86
+ opacity: 0.4;
87
+ }
88
+
89
+ 40% {
90
+ transform: scale(1);
91
+ opacity: 1;
92
+ }
93
+ }
94
+
95
+ /* === Arrow Button Base === */
96
+ .btn-arrow {
97
+ position: relative;
98
+ overflow: hidden;
99
+ }
100
+
101
+ /* Background shimmer overlay */
102
+ .btn-arrow::before {
103
+ content: "";
104
+ position: absolute;
105
+ inset: 0;
106
+ z-index: 0;
107
+ border-radius: 25px;
108
+ background: linear-gradient(120deg,
109
+ rgba(255, 255, 255, 0.05) 0%,
110
+ rgba(255, 255, 255, 0.15) 50%,
111
+ rgba(255, 255, 255, 0.05) 100%);
112
+ background-size: 200% 100%;
113
+ transform: translateX(-100%);
114
+ transition: transform 0.4s ease;
115
+ }
116
+
117
+ /* Content above overlay */
118
+ .btn-arrow>* {
119
+ position: relative;
120
+ z-index: 1;
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ }
125
+
126
+ /* Label wrapper for translation */
127
+ .btn-label {
128
+ display: inline-block;
129
+ transition: transform 0.25s ease;
130
+ }
131
+
132
+ /* === Next Button === */
133
+ /* .btn-next {
134
+ composes: btn-arrow;
135
+ } */
136
+
137
+ .btn-next::after {
138
+ content: "→";
139
+ position: absolute;
140
+ top: 50%;
141
+ right: -25px;
142
+ transform: translateY(-50%);
143
+ opacity: 0;
144
+ transition: all 0.25s ease;
145
+ font-size: 16px;
146
+ font-weight: bold;
147
+ color: currentColor;
148
+ }
149
+
150
+ .btn-next:hover::before {
151
+ transform: translateX(0);
152
+ }
153
+
154
+ .btn-next:hover::after {
155
+ opacity: 1;
156
+ background: #ffffff2b;
157
+ position: absolute;
158
+ padding: 15px 4px;
159
+ right: 0px;
160
+ border-radius: 24px;
161
+ }
162
+
163
+ .btn-next:hover .btn-label {
164
+ transform: translateX(-10px);
165
+ }
166
+
167
+ /* label moves left */
168
+
169
+ /* === Previous Button === */
170
+ /* .btn-previous {
171
+ composes: btn-arrow;
172
+ } */
173
+
174
+ .btn-previous::after {
175
+ content: "←";
176
+ position: absolute;
177
+ top: 50%;
178
+ left: -25px;
179
+ transform: translateY(-50%);
180
+ opacity: 0;
181
+ transition: all 0.25s ease;
182
+ font-size: 16px;
183
+ font-weight: bold;
184
+ color: currentColor;
185
+ }
186
+
187
+ .btn-previous:hover::before {
188
+ transform: translateX(0);
189
+ }
190
+
191
+ .btn-previous:hover::after {
192
+ opacity: 1;
193
+ background: #ffffff2b;
194
+ position: absolute;
195
+ padding: 15px 4px;
196
+ left: 0px;
197
+ border-radius: 24px;
198
+ }
199
+
200
+ .btn-previous:hover .btn-label {
201
+ transform: translateX(10px);
202
+ }
203
+
204
+ /* label moves right */
@@ -1,13 +1,17 @@
1
1
  import React from "react";
2
2
  import "./Button.css";
3
+ type ButtonAnimation = "default" | "loading" | "next" | "previous" | "see-more" | "view-more";
3
4
  export interface ButtonProps {
4
5
  label: string;
5
6
  variant?: "default" | "white" | "red" | "black" | "transparent-white";
6
7
  onClick?: () => void;
7
8
  disabled?: boolean;
8
- /** Optional custom colors */
9
+ animationStyle?: ButtonAnimation;
10
+ /** Loading trigger */
11
+ loading?: boolean;
9
12
  bgColor?: string;
10
13
  textColor?: string;
11
14
  borderColor?: string;
12
15
  }
13
16
  export declare const Button: React.FC<ButtonProps>;
17
+ export {};
@@ -1,10 +1,14 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import "./Button.css";
3
- export const Button = ({ label, variant = "default", onClick, disabled = false, bgColor, textColor, borderColor }) => {
3
+ export const Button = ({ label, variant = "default", onClick, disabled = false, animationStyle = "default", loading = false, bgColor, textColor, borderColor }) => {
4
4
  const customStyle = {
5
5
  background: bgColor,
6
6
  color: textColor,
7
7
  border: borderColor ? `1px solid ${borderColor}` : undefined
8
8
  };
9
- return (_jsx("button", { className: `btn btn-${variant}`, onClick: onClick, disabled: disabled, style: customStyle, children: label }));
9
+ return (_jsx("button", { className: `
10
+ btn btn-${variant}
11
+ ${animationStyle === "next" ? "btn-next" : ""}
12
+ ${animationStyle === "previous" ? "btn-previous" : ""}
13
+ `, onClick: onClick, disabled: disabled, style: customStyle, children: _jsx("span", { className: "btn-content", children: loading ? (_jsxs("span", { className: "btn-loader", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] })) : (_jsx("span", { className: "btn-label", children: label })) }) }));
10
14
  };
@@ -88,4 +88,131 @@
88
88
  /* .card-section:last-child {
89
89
  border-bottom: none;
90
90
  } */
91
- }
91
+ }
92
+ .cards {
93
+ width: 100%;
94
+ display: flex;
95
+ justify-content: center;
96
+ max-width: 820px;
97
+ }
98
+
99
+ .card {
100
+ margin-right: 25px;
101
+ transition: box-shadow 0.4s cubic-bezier(0.175, 0.885, 0, 1);
102
+ background-color: #fff;
103
+ width: 33.3%;
104
+ position: relative;
105
+ border-radius: 12px;
106
+ overflow: hidden;
107
+ box-shadow: 0px 13px 10px -7px rgba(0, 0, 0, 0.1);
108
+ }
109
+
110
+ /* Card itself does not scale */
111
+ .card:hover {
112
+ box-shadow: 0px 30px 18px -8px rgba(0, 0, 0, 0.1);
113
+ transform: none;
114
+ }
115
+
116
+ /* First image (default) */
117
+ .card__img {
118
+ background-size: cover;
119
+ background-position: center;
120
+ background-repeat: no-repeat;
121
+ width: 100%;
122
+ height: 235px;
123
+ border-top-left-radius: 12px;
124
+ border-top-right-radius: 12px;
125
+ transition: opacity 0.3s ease; /* smooth fade */
126
+ }
127
+
128
+ /* Hover overlay image */
129
+ .card__img--hover {
130
+ transition: all 0.4s ease; /* smooth fade + expand */
131
+ background-size: cover;
132
+ background-position: center;
133
+ background-repeat: no-repeat;
134
+ width: 100%;
135
+ height: 100%; /* cover full card */
136
+ position: absolute;
137
+ top: 0;
138
+ left: 0;
139
+ border-radius: 12px; /* covers whole card corners */
140
+ opacity: 0; /* hidden by default */
141
+ pointer-events: none;
142
+ z-index: 1;
143
+ }
144
+
145
+ /* Hover effects: overlay fades in and zooms */
146
+ .card:hover .card__img--hover {
147
+ opacity: 0.3; /* fade in overlay */
148
+ transform: scale(1.1); /* zoom slightly */
149
+ }
150
+
151
+ /* Info section */
152
+ .card__info {
153
+ z-index: 2;
154
+ background-color: #fff;
155
+ border-bottom-left-radius: 12px;
156
+ border-bottom-right-radius: 12px;
157
+ padding: 16px 24px 24px 24px;
158
+ transition: background-color 0.3s ease;
159
+ }
160
+
161
+ /* Info content styling */
162
+ .card__category {
163
+ font-family: 'Raleway', sans-serif;
164
+ text-transform: uppercase;
165
+ font-size: 13px;
166
+ letter-spacing: 2px;
167
+ font-weight: 500;
168
+ color: #868686;
169
+ }
170
+ .card__title {
171
+ margin-top: 5px;
172
+ margin-bottom: 10px;
173
+ font-family: 'Roboto Slab', serif;
174
+ }
175
+ .card__by {
176
+ font-size: 12px;
177
+ font-family: 'Raleway', sans-serif;
178
+ font-weight: 500;
179
+ }
180
+ .card__author {
181
+ font-weight: 600;
182
+ text-decoration: none;
183
+ color: #AD7D52;
184
+ }
185
+
186
+ /* Clock & like icons */
187
+ .card__like {
188
+ width: 18px;
189
+ }
190
+ .card__clock {
191
+ width: 15px;
192
+ vertical-align: middle;
193
+ fill: #AD7D52;
194
+ }
195
+ .card__time {
196
+ font-size: 12px;
197
+ color: #AD7D52;
198
+ vertical-align: middle;
199
+ margin-left: 5px;
200
+ }
201
+ .card__clock-info {
202
+ float: right;
203
+ }
204
+
205
+ /* Fade out first image on hover */
206
+ .card:hover .card__img {
207
+ opacity: 0;
208
+ }
209
+
210
+ /* Info hover overlay */
211
+ .card:hover .card__info {
212
+ background-color: transparent;
213
+ position: relative;
214
+ }
215
+
216
+ .card:hover .card__info-hover {
217
+ opacity: 1; /* show overlay info */
218
+ }
@@ -6,6 +6,7 @@ export interface CardProps {
6
6
  columnWidths?: string[];
7
7
  width?: string;
8
8
  hoverable?: boolean;
9
+ variant?: "default" | "blog";
9
10
  className?: string;
10
11
  style?: React.CSSProperties;
11
12
  }
@@ -1,13 +1,16 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import "./Card.css";
4
- export const Card = ({ children, columns = 1, columnWidths, width = "100%", hoverable = false, className = "", style, }) => {
4
+ export const Card = ({ children, columns = 1, columnWidths, width = "100%", hoverable = false, variant = "default", // default remains your current version
5
+ className = "", style, }) => {
5
6
  const gridTemplateColumns = columnWidths && columnWidths.length
6
7
  ? columnWidths.map((w) => `minmax(0, ${w})`).join(" ")
7
8
  : `repeat(${columns}, minmax(0, 1fr))`;
8
- return (_jsx("div", { className: `card ${hoverable ? "hoverable" : ""} ${className}`, style: { width, ...style }, children: _jsx("div", { className: "card-grid", style: { gridTemplateColumns }, children: React.Children.map(children, (child, i) => (_jsx("div", { className: `card-section ${React.isValidElement(child) &&
9
- child.props?.className?.includes("card-image")
10
- ? "card-image-section"
11
- : ""}`, children: child }, i))) }) }));
9
+ return (_jsxs("div", { className: `
10
+ card
11
+ card-${variant}
12
+ ${hoverable ? "hoverable" : ""}
13
+ ${className}
14
+ `, style: { width, ...style }, children: [variant === "default" && (_jsx("div", { className: "card-grid", style: { gridTemplateColumns }, children: React.Children.map(children, (child, i) => (_jsx("div", { className: "card-section", children: child }, i))) })), variant === "blog" && (_jsx("div", { className: "card-blog-wrapper", children: children }))] }));
12
15
  };
13
16
  export default Card;
@@ -0,0 +1,56 @@
1
+ .link {
2
+ position: relative;
3
+ display: inline-flex;
4
+ align-items: center;
5
+ gap: 6px;
6
+ font-weight: 500;
7
+ text-decoration: none;
8
+ cursor: pointer;
9
+ transition: color 0.3s ease;
10
+ }
11
+
12
+ /* Variants */
13
+ .link-default {
14
+ color: #5d5d5d;
15
+ }
16
+
17
+ .link-white {
18
+ color: #ffffff;
19
+ }
20
+
21
+ .link-red {
22
+ color: #ff0000;
23
+ }
24
+
25
+ .link-black {
26
+ color: #333333;
27
+ }
28
+
29
+ /* ===== See More / View More Animation ===== */
30
+ .link-more::after {
31
+ content: "";
32
+ position: absolute;
33
+ bottom: -2px;
34
+ left: 0;
35
+ height: 1.5px;
36
+ width: 100%;
37
+ background: currentColor;
38
+ transform-origin: left;
39
+ transform: scaleX(1);
40
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
41
+ }
42
+
43
+ .link-more:hover::after {
44
+ transform: scaleX(0);
45
+ }
46
+
47
+ /* Arrow */
48
+ .link-arrow {
49
+ display: flex;
50
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
51
+ }
52
+
53
+ /* Arrow nudges right */
54
+ .link-more:hover .link-arrow {
55
+ transform: translateX(4px);
56
+ }
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import "./Link.css";
3
+ type LinkAnimation = "default" | "see-more" | "view-more";
4
+ export interface LinkProps {
5
+ label: string;
6
+ href?: string;
7
+ onClick?: () => void;
8
+ variant?: "default" | "white" | "red" | "black";
9
+ animationStyle?: LinkAnimation;
10
+ textColor?: string;
11
+ }
12
+ export declare const Link: React.FC<LinkProps>;
13
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import "./Link.css";
3
+ export const Link = ({ label, href = "#", onClick, variant = "default", animationStyle = "default", textColor }) => {
4
+ const customStyle = {
5
+ color: textColor
6
+ };
7
+ return (_jsxs("a", { href: href, onClick: onClick, className: `
8
+ link
9
+ link-${variant}
10
+ ${animationStyle === "see-more" ? "link-more" : ""}
11
+ ${animationStyle === "view-more" ? "link-more" : ""}
12
+ `, style: customStyle, children: [_jsx("span", { className: "link-text", children: label }), (animationStyle === "see-more" ||
13
+ animationStyle === "view-more") && (_jsx("span", { className: "link-arrow", children: _jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '20', height: '20', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', children: [_jsx("path", { stroke: 'none', d: 'M0 0h24v24H0z', fill: 'none' }), _jsx("path", { d: 'M5 12l14 0' }), _jsx("path", { d: 'M13 18l6 -6' }), _jsx("path", { d: 'M13 6l6 6' })] }) }))] }));
14
+ };
@@ -2,7 +2,7 @@
2
2
  Navbar Base
3
3
  ------------------------- */
4
4
  .navbar {
5
- position: sticky;
5
+ position: fixed;
6
6
  background: #fff;
7
7
  border-bottom: 1px solid #eee;
8
8
  width: 100%;
@@ -205,7 +205,7 @@
205
205
  /* -------------------------
206
206
  Responsive
207
207
  ------------------------- */
208
- @media (max-width: 992px) {
208
+ @media (max-width: 1100px) {
209
209
  .navbar-container {
210
210
  margin: 0 20px;
211
211
  padding: 1rem 1.5rem;
@@ -242,27 +242,33 @@
242
242
 
243
243
  .navbar-links {
244
244
  position: fixed;
245
+ /* key change */
245
246
  top: 0;
246
- right: -100%;
247
- width: 400px;
247
+ right: 0;
248
248
  height: 100vh;
249
+ width: 360px;
249
250
  background: #fff;
250
251
  flex-direction: column;
251
- padding: 65px 0px 70px;
252
- transition: right 0.3s ease-in-out;
253
- box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
254
- z-index: 9999;
255
- overflow-y: auto;
252
+ padding: 80px 20px;
253
+ box-shadow: -5px 0 15px rgba(0, 0, 0, 0.1);
254
+
255
+ transform: translateX(100%);
256
+ transition: transform 0.3s ease;
257
+ z-index: 200;
256
258
  }
257
259
 
258
260
  .navbar-links.open {
259
- right: 0;
261
+ transform: translateX(0);
260
262
  }
261
263
 
262
264
  .nav-items {
263
265
  flex-direction: column;
264
266
  gap: 0;
265
- overflow: visible;
267
+ /* overflow: visible; */
268
+ }
269
+
270
+ .nav-items--hidden {
271
+ transform: translateY(-100%);
266
272
  }
267
273
 
268
274
  .navbar-links a {
@@ -273,6 +279,10 @@
273
279
  color: #333;
274
280
  }
275
281
 
282
+ .separator {
283
+ display: none !important;
284
+ }
285
+
276
286
  .navbar-links a:hover {
277
287
  background: #ff0000;
278
288
  color: #fff;
package/dist/index.d.ts CHANGED
@@ -37,3 +37,5 @@ export { Carousel } from "./components/Carousel/Carousel";
37
37
  export type { CarouselProps } from "./components/Carousel/Carousel";
38
38
  export { TextArea } from "./components/TextArea/TextArea";
39
39
  export type { TextAreaProps } from "./components/TextArea/TextArea";
40
+ export { Link } from "./components/Link/Link";
41
+ export type { LinkProps } from "./components/Link/Link";
package/dist/index.js CHANGED
@@ -18,3 +18,4 @@ export { Footer } from "./components/Footer/Footer";
18
18
  export { PageBanner } from "./components/PageBanner/PageBanner";
19
19
  export { Carousel } from "./components/Carousel/Carousel";
20
20
  export { TextArea } from "./components/TextArea/TextArea";
21
+ export { Link } from "./components/Link/Link";
package/package.json CHANGED
@@ -1,29 +1,29 @@
1
- {
2
- "name": "ml-ui-lib",
3
- "version": "1.0.30",
4
- "main": "dist/index.js",
5
- "module": "dist/index.esm.js",
6
- "types": "dist/index.d.ts",
7
- "author": "Kenneth James B. Simbulan",
8
- "files": [
9
- "dist"
10
- ],
11
- "scripts": {
12
- "clean": "rimraf dist",
13
- "build": "npm run clean && tsc && npm run copy-assets",
14
- "copy-assets": "copyfiles -u 1 \"src/**/*.css\" \"src/**/*.png\" dist/",
15
- "watch": "tsc --watch",
16
- "dev": "npm run build -- --watch"
17
- },
18
- "peerDependencies": {
19
- "react": ">=17",
20
- "react-dom": ">=17"
21
- },
22
- "devDependencies": {
23
- "@types/react": "^18.0.0",
24
- "@types/react-dom": "^18.0.0",
25
- "copyfiles": "^2.4.1",
26
- "rimraf": "^5.0.10",
27
- "typescript": "^5.9.3"
28
- }
29
- }
1
+ {
2
+ "name": "ml-ui-lib",
3
+ "version": "1.0.32",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.esm.js",
6
+ "types": "dist/index.d.ts",
7
+ "author": "Kenneth James B. Simbulan",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "clean": "rimraf dist",
13
+ "build": "npm run clean && tsc && npm run copy-assets",
14
+ "copy-assets": "copyfiles -u 1 \"src/**/*.css\" \"src/**/*.png\" dist/",
15
+ "watch": "tsc --watch",
16
+ "dev": "npm run build -- --watch"
17
+ },
18
+ "peerDependencies": {
19
+ "react": ">=17",
20
+ "react-dom": ">=17"
21
+ },
22
+ "devDependencies": {
23
+ "@types/react": "^18.0.0",
24
+ "@types/react-dom": "^18.0.0",
25
+ "copyfiles": "^2.4.1",
26
+ "rimraf": "^5.0.10",
27
+ "typescript": "^5.9.3"
28
+ }
29
+ }