ab-nextjs-components 0.1.2 → 0.1.3
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/CHANGELOG.md +40 -0
- package/README.md +60 -14
- package/ab-avatar/index.tsx +90 -0
- package/ab-avatar/styles.module.css +62 -0
- package/ab-balloon/index.tsx +55 -0
- package/ab-balloon/styles.module.css +12 -0
- package/ab-brand/index.tsx +88 -0
- package/ab-brand/styles.module.css +54 -0
- package/ab-button/index.tsx +164 -0
- package/ab-button/styles.module.css +63 -0
- package/ab-collapsible/index.tsx +188 -0
- package/ab-collapsible/styles.module.css +98 -0
- package/ab-color/index.tsx +84 -0
- package/ab-color/styles.module.css +51 -0
- package/ab-demo-box/index.tsx +38 -0
- package/ab-demo-box/styles.module.css +13 -0
- package/ab-demo-code/index.tsx +62 -0
- package/ab-demo-code/styles.module.css +41 -0
- package/ab-icon/index.tsx +63 -0
- package/ab-icon/styles.module.css +27 -0
- package/ab-icon-button/index.tsx +107 -0
- package/ab-icon-button/styles.module.css +64 -0
- package/ab-image/index.tsx +83 -0
- package/ab-image/styles.module.css +27 -0
- package/ab-info/index.tsx +89 -0
- package/ab-info/styles.module.css +87 -0
- package/ab-input/index.tsx +277 -0
- package/ab-input/styles.module.css +101 -0
- package/ab-key-feature/index.tsx +60 -0
- package/ab-key-feature/styles.module.css +47 -0
- package/ab-like-button/index.tsx +116 -0
- package/ab-like-button/styles.module.css +60 -0
- package/ab-logo/index.tsx +94 -0
- package/ab-logo/styles.module.css +30 -0
- package/ab-main-headline/index.tsx +57 -0
- package/ab-main-headline/styles.module.css +24 -0
- package/ab-menu/index.tsx +119 -0
- package/ab-menu/styles.module.css +99 -0
- package/ab-name/index.tsx +49 -0
- package/ab-name/styles.module.css +14 -0
- package/ab-navbar/index.tsx +68 -0
- package/ab-navbar/styles.module.css +35 -0
- package/ab-page-paginator/index.tsx +130 -0
- package/ab-page-paginator/styles.module.css +47 -0
- package/ab-page-switcher/index.tsx +121 -0
- package/ab-page-switcher/styles.module.css +37 -0
- package/ab-preview/index.tsx +78 -0
- package/ab-preview/styles.module.css +26 -0
- package/ab-price/index.tsx +109 -0
- package/ab-price/styles.module.css +36 -0
- package/ab-price-tag/index.tsx +70 -0
- package/ab-price-tag/styles.module.css +81 -0
- package/ab-product/index.tsx +128 -0
- package/ab-product/styles.module.css +44 -0
- package/ab-product-item/index.tsx +78 -0
- package/ab-product-item/styles.module.css +21 -0
- package/ab-progress-chips/index.tsx +105 -0
- package/ab-progress-chips/styles.module.css +43 -0
- package/ab-search-result/index.tsx +79 -0
- package/ab-search-result/styles.module.css +48 -0
- package/ab-searchbar/index.tsx +150 -0
- package/ab-searchbar/styles.module.css +77 -0
- package/ab-sidebar/index.tsx +72 -0
- package/ab-sidebar/styles.module.css +41 -0
- package/ab-switch-back/index.tsx +72 -0
- package/ab-switch-back/styles.module.css +45 -0
- package/ab-tab/index.tsx +101 -0
- package/ab-tab/styles.module.css +65 -0
- package/ab-tabs/index.tsx +45 -0
- package/ab-tabs/styles.module.css +17 -0
- package/ab-test-hello/index.tsx +37 -0
- package/ab-test-hello/styles.module.css +25 -0
- package/ab-text/index.tsx +36 -0
- package/ab-text/styles.module.css +3 -0
- package/index.ts +117 -0
- package/package.json +152 -7
- package/server/ab-avatar/index.tsx +85 -0
- package/server/ab-avatar/styles.module.css +62 -0
- package/server/ab-badge/index.tsx +66 -0
- package/server/ab-badge/styles.module.css +39 -0
- package/server/ab-brand/index.tsx +87 -0
- package/server/ab-brand/styles.module.css +54 -0
- package/server/ab-button/index.tsx +144 -0
- package/server/ab-button/styles.module.css +63 -0
- package/server/ab-icon/index.tsx +61 -0
- package/server/ab-icon/styles.module.css +27 -0
- package/server/ab-key-feature/index.tsx +59 -0
- package/server/ab-key-feature/styles.module.css +47 -0
- package/server/ab-logo/index.tsx +93 -0
- package/server/ab-logo/styles.module.css +30 -0
- package/server/ab-name/index.tsx +48 -0
- package/server/ab-name/styles.module.css +14 -0
- package/server/ab-nav-link/index.tsx +60 -0
- package/server/ab-nav-link/styles.module.css +32 -0
- package/server/ab-navbar/index.tsx +64 -0
- package/server/ab-navbar/styles.module.css +35 -0
- package/server/ab-polygon/index.tsx +45 -0
- package/server/ab-polygon/styles.module.css +11 -0
- package/server/ab-sidebar/index.tsx +68 -0
- package/server/ab-sidebar/styles.module.css +41 -0
- package/server/ab-switch-back/index.tsx +71 -0
- package/server/ab-switch-back/styles.module.css +45 -0
- package/server/ab-test-hello/index.tsx +35 -0
- package/server/ab-test-hello/styles.module.css +22 -0
- package/server/ab-text/index.tsx +33 -0
- package/server/ab-text/styles.module.css +3 -0
- package/server/index.ts +27 -0
- package/types/index.d.ts +54 -0
- package/.github/ab-logo-dark.svg +0 -12
- package/.github/ab-logo-light.svg +0 -9
- package/.github/nextjs-logoname-dark.svg +0 -28
- package/.github/nextjs-logoname-light.svg +0 -25
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @license MIT
|
|
3
|
+
* ~~~~~~~~~~~~
|
|
4
|
+
* ab-nextjs-components
|
|
5
|
+
* ~~~~~~~~~~~~
|
|
6
|
+
* Copyright (c) 2026 Abraham Ukachi. The abElements Project.
|
|
7
|
+
*
|
|
8
|
+
* @project: ab-nextjs-components
|
|
9
|
+
* @name: AbTestHello - Client (port of lyd-test-hello)
|
|
10
|
+
* @file: ab-test-hello/index.tsx
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use client';
|
|
14
|
+
|
|
15
|
+
import type { ReactElement } from 'react';
|
|
16
|
+
import clsx from 'clsx';
|
|
17
|
+
import styles from './styles.module.css';
|
|
18
|
+
|
|
19
|
+
export interface AbTestHelloProps {
|
|
20
|
+
name: string;
|
|
21
|
+
src?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const AbTestHello = ({ name, src, className }: AbTestHelloProps): ReactElement => {
|
|
26
|
+
return (
|
|
27
|
+
<div id="abTestHello" className={clsx('AbTestHello', styles.abTestHello, className)}>
|
|
28
|
+
<h2 className={styles.abTestHelloTitle}>
|
|
29
|
+
Hello from <span className={styles.abTestHelloName}>{name}</span>
|
|
30
|
+
</h2>
|
|
31
|
+
{src ? <span className={styles.abTestHelloSrc}>{src}</span> : null}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default AbTestHello;
|
|
37
|
+
export { AbTestHello };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.abTestHello {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: flex-start;
|
|
5
|
+
text-align: left;
|
|
6
|
+
padding: 1.5rem;
|
|
7
|
+
}
|
|
8
|
+
.abTestHelloTitle {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0.75rem 0 0.25rem;
|
|
11
|
+
font-size: 1rem;
|
|
12
|
+
}
|
|
13
|
+
.abTestHelloName {
|
|
14
|
+
font-family: ui-serif, Georgia, serif;
|
|
15
|
+
font-weight: 700;
|
|
16
|
+
color: var(--ab-primary, #6750a4);
|
|
17
|
+
}
|
|
18
|
+
.abTestHelloSrc {
|
|
19
|
+
font-family: ui-monospace, monospace;
|
|
20
|
+
font-size: 0.875rem;
|
|
21
|
+
opacity: 0.5;
|
|
22
|
+
}
|
|
23
|
+
.abTestHelloSrc:hover {
|
|
24
|
+
opacity: 0.9;
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @license MIT
|
|
3
|
+
* ~~~~~~~~~~~~
|
|
4
|
+
* ab-nextjs-components
|
|
5
|
+
* ~~~~~~~~~~~~
|
|
6
|
+
* Copyright (c) 2026 Abraham Ukachi. The abElements Project.
|
|
7
|
+
*
|
|
8
|
+
* @project: ab-nextjs-components
|
|
9
|
+
* @name: AbText - Client (port of lyd-text; i18n stripped — pass value)
|
|
10
|
+
* @file: ab-text/index.tsx
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use client';
|
|
14
|
+
|
|
15
|
+
import type { ReactElement } from 'react';
|
|
16
|
+
import clsx from 'clsx';
|
|
17
|
+
import styles from './styles.module.css';
|
|
18
|
+
|
|
19
|
+
export interface AbTextProps {
|
|
20
|
+
className?: string;
|
|
21
|
+
id?: string;
|
|
22
|
+
value?: string;
|
|
23
|
+
/** Kept for API compat; unused without i18n peer. Prefer `value`. */
|
|
24
|
+
origin?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const AbText = ({ className, id, value }: AbTextProps): ReactElement => {
|
|
28
|
+
return (
|
|
29
|
+
<span id={id} className={clsx('AbText', styles.abText, className)}>
|
|
30
|
+
{value ?? id ?? ''}
|
|
31
|
+
</span>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default AbText;
|
|
36
|
+
export { AbText };
|
package/index.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @license MIT
|
|
3
|
+
* ~~~~~~~~~~~~
|
|
4
|
+
* ab-nextjs-components
|
|
5
|
+
* ~~~~~~~~~~~~
|
|
6
|
+
* Copyright (c) 2026 Abraham Ukachi. The abElements Project.
|
|
7
|
+
*
|
|
8
|
+
* @project: ab-nextjs-components
|
|
9
|
+
* @name: Components - Package Catalog
|
|
10
|
+
* @file: index.ts
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { ComponentCatalogEntry } from './types'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Catalog — Phase 2–4 + Skip-override (Phase 5 components) marked Done.
|
|
17
|
+
* Barrel re-exports use explicit /index.tsx paths (avoid DIR_IMPORT).
|
|
18
|
+
*/
|
|
19
|
+
const supportedComponents: Array<ComponentCatalogEntry> = [
|
|
20
|
+
// CLIENT
|
|
21
|
+
{ name: 'AbIcon', file: 'ab-icon/index.tsx', kind: 'client', status: 'Done' },
|
|
22
|
+
{ name: 'AbLogo', file: 'ab-logo/index.tsx', kind: 'client', status: 'Done' },
|
|
23
|
+
{ name: 'AbButton', file: 'ab-button/index.tsx', kind: 'client', status: 'Done' },
|
|
24
|
+
{ name: 'AbIconButton', file: 'ab-icon-button/index.tsx', kind: 'client', status: 'Done' },
|
|
25
|
+
{ name: 'AbInput', file: 'ab-input/index.tsx', kind: 'client', status: 'Done' },
|
|
26
|
+
{ name: 'AbBalloon', file: 'ab-balloon/index.tsx', kind: 'client', status: 'Done' },
|
|
27
|
+
{ name: 'AbAvatar', file: 'ab-avatar/index.tsx', kind: 'client', status: 'Done' },
|
|
28
|
+
{ name: 'AbTab', file: 'ab-tab/index.tsx', kind: 'client', status: 'Done' },
|
|
29
|
+
{ name: 'AbTabs', file: 'ab-tabs/index.tsx', kind: 'client', status: 'Done' },
|
|
30
|
+
{ name: 'AbMenu', file: 'ab-menu/index.tsx', kind: 'client', status: 'Done' },
|
|
31
|
+
{ name: 'AbCollapsible', file: 'ab-collapsible/index.tsx', kind: 'client', status: 'Done' },
|
|
32
|
+
{ name: 'AbColor', file: 'ab-color/index.tsx', kind: 'client', status: 'Done' },
|
|
33
|
+
{ name: 'AbInfo', file: 'ab-info/index.tsx', kind: 'client', status: 'Done' },
|
|
34
|
+
{ name: 'AbLikeButton', file: 'ab-like-button/index.tsx', kind: 'client', status: 'Done' },
|
|
35
|
+
{ name: 'AbSearchbar', file: 'ab-searchbar/index.tsx', kind: 'client', status: 'Done' },
|
|
36
|
+
{ name: 'AbSearchResult', file: 'ab-search-result/index.tsx', kind: 'client', status: 'Done' },
|
|
37
|
+
{ name: 'AbPagePaginator', file: 'ab-page-paginator/index.tsx', kind: 'client', status: 'Done' },
|
|
38
|
+
{ name: 'AbPageSwitcher', file: 'ab-page-switcher/index.tsx', kind: 'client', status: 'Done' },
|
|
39
|
+
{ name: 'AbProgressChips', file: 'ab-progress-chips/index.tsx', kind: 'client', status: 'Done' },
|
|
40
|
+
{ name: 'AbPrice', file: 'ab-price/index.tsx', kind: 'client', status: 'Done' },
|
|
41
|
+
{ name: 'AbPriceTag', file: 'ab-price-tag/index.tsx', kind: 'client', status: 'Done' },
|
|
42
|
+
{ name: 'AbImage', file: 'ab-image/index.tsx', kind: 'client', status: 'Done' },
|
|
43
|
+
{ name: 'AbBrand', file: 'ab-brand/index.tsx', kind: 'client', status: 'Done' },
|
|
44
|
+
{ name: 'AbName', file: 'ab-name/index.tsx', kind: 'client', status: 'Done' },
|
|
45
|
+
{ name: 'AbNavbar', file: 'ab-navbar/index.tsx', kind: 'client', status: 'Done' },
|
|
46
|
+
{ name: 'AbSidebar', file: 'ab-sidebar/index.tsx', kind: 'client', status: 'Done' },
|
|
47
|
+
{ name: 'AbText', file: 'ab-text/index.tsx', kind: 'client', status: 'Done' },
|
|
48
|
+
{ name: 'AbTestHello', file: 'ab-test-hello/index.tsx', kind: 'client', status: 'Done' },
|
|
49
|
+
{ name: 'AbKeyFeature', file: 'ab-key-feature/index.tsx', kind: 'client', status: 'Done' },
|
|
50
|
+
{ name: 'AbMainHeadline', file: 'ab-main-headline/index.tsx', kind: 'client', status: 'Done' },
|
|
51
|
+
{ name: 'AbPreview', file: 'ab-preview/index.tsx', kind: 'client', status: 'Done' },
|
|
52
|
+
{ name: 'AbProduct', file: 'ab-product/index.tsx', kind: 'client', status: 'Done' },
|
|
53
|
+
{ name: 'AbProductItem', file: 'ab-product-item/index.tsx', kind: 'client', status: 'Done' },
|
|
54
|
+
{ name: 'AbSwitchBack', file: 'ab-switch-back/index.tsx', kind: 'client', status: 'Done' },
|
|
55
|
+
{ name: 'AbDemoBox', file: 'ab-demo-box/index.tsx', kind: 'client', status: 'Done' },
|
|
56
|
+
{ name: 'AbDemoCode', file: 'ab-demo-code/index.tsx', kind: 'client', status: 'Done' },
|
|
57
|
+
|
|
58
|
+
// SERVER
|
|
59
|
+
{ name: 'AbIcon', file: 'server/ab-icon/index.tsx', kind: 'server', status: 'Done' },
|
|
60
|
+
{ name: 'AbLogo', file: 'server/ab-logo/index.tsx', kind: 'server', status: 'Done' },
|
|
61
|
+
{ name: 'AbButton', file: 'server/ab-button/index.tsx', kind: 'server', status: 'Done' },
|
|
62
|
+
{ name: 'AbAvatar', file: 'server/ab-avatar/index.tsx', kind: 'server', status: 'Done' },
|
|
63
|
+
{ name: 'AbBadge', file: 'server/ab-badge/index.tsx', kind: 'server', status: 'Done' },
|
|
64
|
+
{ name: 'AbPolygon', file: 'server/ab-polygon/index.tsx', kind: 'server', status: 'Done' },
|
|
65
|
+
{ name: 'AbBrand', file: 'server/ab-brand/index.tsx', kind: 'server', status: 'Done' },
|
|
66
|
+
{ name: 'AbName', file: 'server/ab-name/index.tsx', kind: 'server', status: 'Done' },
|
|
67
|
+
{ name: 'AbNavbar', file: 'server/ab-navbar/index.tsx', kind: 'server', status: 'Done' },
|
|
68
|
+
{ name: 'AbSidebar', file: 'server/ab-sidebar/index.tsx', kind: 'server', status: 'Done' },
|
|
69
|
+
{ name: 'AbNavLink', file: 'server/ab-nav-link/index.tsx', kind: 'server', status: 'Done' },
|
|
70
|
+
{ name: 'AbText', file: 'server/ab-text/index.tsx', kind: 'server', status: 'Done' },
|
|
71
|
+
{ name: 'AbTestHello', file: 'server/ab-test-hello/index.tsx', kind: 'server', status: 'Done' },
|
|
72
|
+
{ name: 'AbKeyFeature', file: 'server/ab-key-feature/index.tsx', kind: 'server', status: 'Done' },
|
|
73
|
+
{ name: 'AbSwitchBack', file: 'server/ab-switch-back/index.tsx', kind: 'server', status: 'Done' },
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
const abComponents = { supportedComponents }
|
|
77
|
+
|
|
78
|
+
export { supportedComponents }
|
|
79
|
+
export default abComponents
|
|
80
|
+
|
|
81
|
+
export { default as AbIcon } from './ab-icon/index.tsx'
|
|
82
|
+
export { default as AbLogo } from './ab-logo/index.tsx'
|
|
83
|
+
export { default as AbButton } from './ab-button/index.tsx'
|
|
84
|
+
export { default as AbIconButton } from './ab-icon-button/index.tsx'
|
|
85
|
+
export { default as AbInput } from './ab-input/index.tsx'
|
|
86
|
+
export { default as AbBalloon } from './ab-balloon/index.tsx'
|
|
87
|
+
export { default as AbAvatar } from './ab-avatar/index.tsx'
|
|
88
|
+
export { default as AbTab } from './ab-tab/index.tsx'
|
|
89
|
+
export { default as AbTabs } from './ab-tabs/index.tsx'
|
|
90
|
+
export { default as AbMenu } from './ab-menu/index.tsx'
|
|
91
|
+
export { default as AbCollapsible } from './ab-collapsible/index.tsx'
|
|
92
|
+
export { default as AbColor } from './ab-color/index.tsx'
|
|
93
|
+
export { default as AbInfo } from './ab-info/index.tsx'
|
|
94
|
+
export { default as AbLikeButton } from './ab-like-button/index.tsx'
|
|
95
|
+
export { default as AbSearchbar } from './ab-searchbar/index.tsx'
|
|
96
|
+
export { default as AbSearchResult } from './ab-search-result/index.tsx'
|
|
97
|
+
export { default as AbPagePaginator } from './ab-page-paginator/index.tsx'
|
|
98
|
+
export { default as AbPageSwitcher } from './ab-page-switcher/index.tsx'
|
|
99
|
+
export { default as AbProgressChips } from './ab-progress-chips/index.tsx'
|
|
100
|
+
export { default as AbPrice } from './ab-price/index.tsx'
|
|
101
|
+
export { default as AbPriceTag } from './ab-price-tag/index.tsx'
|
|
102
|
+
export { default as AbImage } from './ab-image/index.tsx'
|
|
103
|
+
export { default as AbBrand } from './ab-brand/index.tsx'
|
|
104
|
+
export { default as AbName } from './ab-name/index.tsx'
|
|
105
|
+
export { default as AbNavbar } from './ab-navbar/index.tsx'
|
|
106
|
+
export { default as AbSidebar } from './ab-sidebar/index.tsx'
|
|
107
|
+
export { default as AbText } from './ab-text/index.tsx'
|
|
108
|
+
export { default as AbTestHello } from './ab-test-hello/index.tsx'
|
|
109
|
+
export { default as AbKeyFeature } from './ab-key-feature/index.tsx'
|
|
110
|
+
export { default as AbMainHeadline } from './ab-main-headline/index.tsx'
|
|
111
|
+
export { default as AbPreview } from './ab-preview/index.tsx'
|
|
112
|
+
export { default as AbProduct } from './ab-product/index.tsx'
|
|
113
|
+
export { default as AbProductItem } from './ab-product-item/index.tsx'
|
|
114
|
+
export { default as AbSwitchBack } from './ab-switch-back/index.tsx'
|
|
115
|
+
export { default as AbDemoBox } from './ab-demo-box/index.tsx'
|
|
116
|
+
export { default as AbDemoCode } from './ab-demo-code/index.tsx'
|
|
117
|
+
export { default as AbPolygon } from './server/ab-polygon/index.tsx'
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ab-nextjs-components",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "\ud83d\ude80 A lightweight collection of server & client React components created by Abraham Ukachi, and optimized for Next.js applications \ud83d\ude0e.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.ts",
|
|
6
7
|
"types": "types/index.d.ts",
|
|
7
8
|
"homepage": "https://github.com/abraham-ukachi/ab-nextjs-components#readme",
|
|
8
9
|
"repository": {
|
|
@@ -12,6 +13,10 @@
|
|
|
12
13
|
"bugs": {
|
|
13
14
|
"url": "https://github.com/abraham-ukachi/ab-nextjs-components/issues"
|
|
14
15
|
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"lint": "eslint . --fix",
|
|
18
|
+
"test": "vitest run"
|
|
19
|
+
},
|
|
15
20
|
"keywords": [
|
|
16
21
|
"react",
|
|
17
22
|
"nextjs",
|
|
@@ -20,7 +25,8 @@
|
|
|
20
25
|
"components",
|
|
21
26
|
"abraham",
|
|
22
27
|
"ukachi",
|
|
23
|
-
"ab-nextjs-components"
|
|
28
|
+
"ab-nextjs-components",
|
|
29
|
+
"ab-elements"
|
|
24
30
|
],
|
|
25
31
|
"author": {
|
|
26
32
|
"name": "Abraham Ukachi",
|
|
@@ -28,7 +34,146 @@
|
|
|
28
34
|
"email": "abraham.ukachi@laplateforme.io"
|
|
29
35
|
},
|
|
30
36
|
"license": "MIT",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"clsx": "^2",
|
|
39
|
+
"next": "16.3.4",
|
|
40
|
+
"react": "^19",
|
|
41
|
+
"react-dom": "^19",
|
|
42
|
+
"ab-nextjs-theme": "*",
|
|
43
|
+
"ab-nextjs-icons": "*",
|
|
44
|
+
"ab-nextjs-hooks": "*",
|
|
45
|
+
"ab-nextjs-animations": "*"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^20",
|
|
49
|
+
"@types/react": "^19",
|
|
50
|
+
"eslint": "^9.39.0",
|
|
51
|
+
"eslint-config-next": "16.3.4",
|
|
52
|
+
"next": "16.3.4",
|
|
53
|
+
"react": "^19",
|
|
54
|
+
"react-dom": "^19",
|
|
55
|
+
"typescript": "^5",
|
|
56
|
+
"vitest": "^3",
|
|
57
|
+
"clsx": "^2.1.1",
|
|
58
|
+
"ab-nextjs-hooks": "file:../ab-nextjs-hooks"
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"index.ts",
|
|
62
|
+
"types",
|
|
63
|
+
"server",
|
|
64
|
+
"ab-logo",
|
|
65
|
+
"ab-icon",
|
|
66
|
+
"ab-button",
|
|
67
|
+
"ab-icon-button",
|
|
68
|
+
"ab-input",
|
|
69
|
+
"README.md",
|
|
70
|
+
"LICENSE",
|
|
71
|
+
"CHANGELOG.md",
|
|
72
|
+
"ab-balloon",
|
|
73
|
+
"ab-avatar",
|
|
74
|
+
"ab-tab",
|
|
75
|
+
"ab-tabs",
|
|
76
|
+
"ab-menu",
|
|
77
|
+
"ab-collapsible",
|
|
78
|
+
"ab-color",
|
|
79
|
+
"ab-info",
|
|
80
|
+
"ab-like-button",
|
|
81
|
+
"ab-searchbar",
|
|
82
|
+
"ab-search-result",
|
|
83
|
+
"ab-page-paginator",
|
|
84
|
+
"ab-page-switcher",
|
|
85
|
+
"ab-progress-chips",
|
|
86
|
+
"ab-price",
|
|
87
|
+
"ab-price-tag",
|
|
88
|
+
"ab-image",
|
|
89
|
+
"ab-brand",
|
|
90
|
+
"ab-name",
|
|
91
|
+
"ab-navbar",
|
|
92
|
+
"ab-sidebar",
|
|
93
|
+
"ab-text",
|
|
94
|
+
"ab-test-hello",
|
|
95
|
+
"ab-key-feature",
|
|
96
|
+
"ab-main-headline",
|
|
97
|
+
"ab-preview",
|
|
98
|
+
"ab-product",
|
|
99
|
+
"ab-product-item",
|
|
100
|
+
"ab-switch-back",
|
|
101
|
+
"ab-demo-box",
|
|
102
|
+
"ab-demo-code"
|
|
103
|
+
],
|
|
104
|
+
"exports": {
|
|
105
|
+
".": {
|
|
106
|
+
"types": "./types/index.d.ts",
|
|
107
|
+
"default": "./index.ts"
|
|
108
|
+
},
|
|
109
|
+
"./package.json": "./package.json",
|
|
110
|
+
"./ab-icon": "./ab-icon/index.tsx",
|
|
111
|
+
"./ab-logo": "./ab-logo/index.tsx",
|
|
112
|
+
"./ab-button": "./ab-button/index.tsx",
|
|
113
|
+
"./ab-icon-button": "./ab-icon-button/index.tsx",
|
|
114
|
+
"./ab-input": "./ab-input/index.tsx",
|
|
115
|
+
"./server/ab-icon": "./server/ab-icon/index.tsx",
|
|
116
|
+
"./server/ab-logo": "./server/ab-logo/index.tsx",
|
|
117
|
+
"./server/ab-button": "./server/ab-button/index.tsx",
|
|
118
|
+
"./ab-balloon": "./ab-balloon/index.tsx",
|
|
119
|
+
"./ab-avatar": "./ab-avatar/index.tsx",
|
|
120
|
+
"./ab-tab": "./ab-tab/index.tsx",
|
|
121
|
+
"./ab-tabs": "./ab-tabs/index.tsx",
|
|
122
|
+
"./ab-menu": "./ab-menu/index.tsx",
|
|
123
|
+
"./ab-collapsible": "./ab-collapsible/index.tsx",
|
|
124
|
+
"./ab-color": "./ab-color/index.tsx",
|
|
125
|
+
"./ab-info": "./ab-info/index.tsx",
|
|
126
|
+
"./ab-like-button": "./ab-like-button/index.tsx",
|
|
127
|
+
"./server/ab-avatar": "./server/ab-avatar/index.tsx",
|
|
128
|
+
"./server/ab-badge": "./server/ab-badge/index.tsx",
|
|
129
|
+
"./ab-searchbar": "./ab-searchbar/index.tsx",
|
|
130
|
+
"./ab-search-result": "./ab-search-result/index.tsx",
|
|
131
|
+
"./ab-page-paginator": "./ab-page-paginator/index.tsx",
|
|
132
|
+
"./ab-page-switcher": "./ab-page-switcher/index.tsx",
|
|
133
|
+
"./ab-progress-chips": "./ab-progress-chips/index.tsx",
|
|
134
|
+
"./ab-price": "./ab-price/index.tsx",
|
|
135
|
+
"./ab-price-tag": "./ab-price-tag/index.tsx",
|
|
136
|
+
"./ab-image": "./ab-image/index.tsx",
|
|
137
|
+
"./server/ab-polygon": "./server/ab-polygon/index.tsx",
|
|
138
|
+
"./server": {
|
|
139
|
+
"default": "./server/index.ts"
|
|
140
|
+
},
|
|
141
|
+
"./ab-brand": "./ab-brand/index.tsx",
|
|
142
|
+
"./ab-name": "./ab-name/index.tsx",
|
|
143
|
+
"./ab-navbar": "./ab-navbar/index.tsx",
|
|
144
|
+
"./ab-sidebar": "./ab-sidebar/index.tsx",
|
|
145
|
+
"./ab-text": "./ab-text/index.tsx",
|
|
146
|
+
"./ab-test-hello": "./ab-test-hello/index.tsx",
|
|
147
|
+
"./ab-key-feature": "./ab-key-feature/index.tsx",
|
|
148
|
+
"./ab-main-headline": "./ab-main-headline/index.tsx",
|
|
149
|
+
"./ab-preview": "./ab-preview/index.tsx",
|
|
150
|
+
"./ab-product": "./ab-product/index.tsx",
|
|
151
|
+
"./ab-product-item": "./ab-product-item/index.tsx",
|
|
152
|
+
"./ab-switch-back": "./ab-switch-back/index.tsx",
|
|
153
|
+
"./ab-demo-box": "./ab-demo-box/index.tsx",
|
|
154
|
+
"./ab-demo-code": "./ab-demo-code/index.tsx",
|
|
155
|
+
"./server/ab-brand": "./server/ab-brand/index.tsx",
|
|
156
|
+
"./server/ab-name": "./server/ab-name/index.tsx",
|
|
157
|
+
"./server/ab-navbar": "./server/ab-navbar/index.tsx",
|
|
158
|
+
"./server/ab-sidebar": "./server/ab-sidebar/index.tsx",
|
|
159
|
+
"./server/ab-nav-link": "./server/ab-nav-link/index.tsx",
|
|
160
|
+
"./server/ab-text": "./server/ab-text/index.tsx",
|
|
161
|
+
"./server/ab-test-hello": "./server/ab-test-hello/index.tsx",
|
|
162
|
+
"./server/ab-key-feature": "./server/ab-key-feature/index.tsx",
|
|
163
|
+
"./server/ab-switch-back": "./server/ab-switch-back/index.tsx"
|
|
164
|
+
},
|
|
165
|
+
"peerDependenciesMeta": {
|
|
166
|
+
"ab-nextjs-theme": {
|
|
167
|
+
"optional": true
|
|
168
|
+
},
|
|
169
|
+
"ab-nextjs-icons": {
|
|
170
|
+
"optional": true
|
|
171
|
+
},
|
|
172
|
+
"ab-nextjs-hooks": {
|
|
173
|
+
"optional": true
|
|
174
|
+
},
|
|
175
|
+
"ab-nextjs-animations": {
|
|
176
|
+
"optional": true
|
|
177
|
+
}
|
|
33
178
|
}
|
|
34
|
-
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @license MIT
|
|
3
|
+
* ~~~~~~~~~~~~
|
|
4
|
+
* ab-nextjs-components
|
|
5
|
+
* ~~~~~~~~~~~~
|
|
6
|
+
* Copyright (c) 2026 Abraham Ukachi. The abElements Project.
|
|
7
|
+
*
|
|
8
|
+
* @project: ab-nextjs-components
|
|
9
|
+
* @name: AbAvatar - Server (port of server/lyd-avatar)
|
|
10
|
+
* @file: server/ab-avatar/index.tsx
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { ReactElement } from 'react';
|
|
14
|
+
import Image from 'next/image';
|
|
15
|
+
import Link from 'next/link';
|
|
16
|
+
import clsx from 'clsx';
|
|
17
|
+
import styles from './styles.module.css';
|
|
18
|
+
|
|
19
|
+
export interface AbAvatarProps {
|
|
20
|
+
isConnected: boolean;
|
|
21
|
+
isOnline: boolean;
|
|
22
|
+
icon?: 'person' | 'group';
|
|
23
|
+
version?: number;
|
|
24
|
+
image?: string;
|
|
25
|
+
label?: string;
|
|
26
|
+
className?: string;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
href?: string;
|
|
30
|
+
offlineHref?: string;
|
|
31
|
+
isActive?: boolean;
|
|
32
|
+
noIndicator?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const AbAvatar = ({
|
|
36
|
+
isConnected,
|
|
37
|
+
isOnline,
|
|
38
|
+
icon = 'person',
|
|
39
|
+
version = 1,
|
|
40
|
+
image,
|
|
41
|
+
label = 'Avatar',
|
|
42
|
+
className,
|
|
43
|
+
width = 48,
|
|
44
|
+
height = 48,
|
|
45
|
+
href = '/',
|
|
46
|
+
offlineHref = '/',
|
|
47
|
+
isActive = false,
|
|
48
|
+
noIndicator = false,
|
|
49
|
+
}: AbAvatarProps): ReactElement => {
|
|
50
|
+
const src = image ?? `/assets/images/avatars/avatar_${version}.png`;
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className={clsx('AbAvatar', styles.abAvatar, className)}>
|
|
54
|
+
{isConnected ? (
|
|
55
|
+
<Link href={href} className={clsx(styles.abAvatarLink, isActive && styles.isActive)}>
|
|
56
|
+
<span className={styles.abAvatarImageWrap}>
|
|
57
|
+
<Image
|
|
58
|
+
src={src}
|
|
59
|
+
className={styles.abAvatarImage}
|
|
60
|
+
width={width}
|
|
61
|
+
height={height}
|
|
62
|
+
alt={label}
|
|
63
|
+
/>
|
|
64
|
+
{!noIndicator ? (
|
|
65
|
+
<span
|
|
66
|
+
className={clsx(styles.abAvatarIndicator, !isOnline && styles.isOffline)}
|
|
67
|
+
aria-hidden
|
|
68
|
+
/>
|
|
69
|
+
) : null}
|
|
70
|
+
</span>
|
|
71
|
+
</Link>
|
|
72
|
+
) : (
|
|
73
|
+
<Link href={offlineHref} className={styles.abAvatarOffline}>
|
|
74
|
+
<span className={clsx('material-symbols-rounded', styles.abAvatarIcon)} aria-hidden>
|
|
75
|
+
{icon}
|
|
76
|
+
</span>
|
|
77
|
+
{label ? <span className={styles.abAvatarLabel}>{label}</span> : null}
|
|
78
|
+
</Link>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default AbAvatar;
|
|
85
|
+
export { AbAvatar };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* AbAvatar — plain CSS (no Tailwind apply) */
|
|
2
|
+
.abAvatar {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
width: auto;
|
|
6
|
+
height: auto;
|
|
7
|
+
pointer-events: auto;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.abAvatarLink {
|
|
11
|
+
position: relative;
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
text-decoration: none;
|
|
14
|
+
opacity: 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.isActive {
|
|
18
|
+
opacity: 0.9;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.abAvatarImageWrap {
|
|
22
|
+
position: relative;
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.abAvatarImage {
|
|
27
|
+
border-radius: 9999px;
|
|
28
|
+
object-fit: cover;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.abAvatarIndicator {
|
|
32
|
+
position: absolute;
|
|
33
|
+
right: 0;
|
|
34
|
+
bottom: 0;
|
|
35
|
+
width: 1rem;
|
|
36
|
+
height: 1rem;
|
|
37
|
+
border-radius: 9999px;
|
|
38
|
+
border: 2px solid var(--ab-surface, #fff);
|
|
39
|
+
background: #22c55e;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.abAvatarIndicator.isOffline {
|
|
43
|
+
background: #ef4444;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.abAvatarOffline {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 0.25rem;
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
color: inherit;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.abAvatarIcon {
|
|
56
|
+
font-size: 1.75rem;
|
|
57
|
+
line-height: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.abAvatarLabel {
|
|
61
|
+
font-size: 0.75rem;
|
|
62
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @license MIT
|
|
3
|
+
* ~~~~~~~~~~~~
|
|
4
|
+
* ab-nextjs-components
|
|
5
|
+
* ~~~~~~~~~~~~
|
|
6
|
+
* Copyright (c) 2026 Abraham Ukachi. The abElements Project.
|
|
7
|
+
*
|
|
8
|
+
* @project: ab-nextjs-components
|
|
9
|
+
* @name: AbBadge - Server (port of server/lyd-badge)
|
|
10
|
+
* @file: server/ab-badge/index.tsx
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { CSSProperties, ReactElement } from 'react';
|
|
14
|
+
import clsx from 'clsx';
|
|
15
|
+
import styles from './styles.module.css';
|
|
16
|
+
|
|
17
|
+
export interface AbBadgeProps {
|
|
18
|
+
className?: string;
|
|
19
|
+
hidden?: boolean;
|
|
20
|
+
style?: CSSProperties;
|
|
21
|
+
color?: 'default' | 'red';
|
|
22
|
+
count: number;
|
|
23
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
24
|
+
size?: 'small' | 'medium' | 'large';
|
|
25
|
+
maxCount?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function formatCount(count: number, maxCount: number): string {
|
|
29
|
+
return count > maxCount ? `${maxCount}+` : String(count);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Server AbBadge — count pill. No 'use client'. */
|
|
33
|
+
const AbBadge = ({
|
|
34
|
+
className,
|
|
35
|
+
hidden = false,
|
|
36
|
+
style,
|
|
37
|
+
color = 'default',
|
|
38
|
+
count,
|
|
39
|
+
position = 'top-right',
|
|
40
|
+
size = 'small',
|
|
41
|
+
maxCount = 99,
|
|
42
|
+
}: AbBadgeProps): ReactElement | null => {
|
|
43
|
+
if (hidden) return null;
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<span
|
|
47
|
+
className={clsx(
|
|
48
|
+
'AbBadge',
|
|
49
|
+
styles.abBadge,
|
|
50
|
+
styles[`color_${color}`],
|
|
51
|
+
styles[`pos_${position.replace('-', '_')}`],
|
|
52
|
+
styles[`size_${size}`],
|
|
53
|
+
className,
|
|
54
|
+
)}
|
|
55
|
+
style={style}
|
|
56
|
+
data-color={color}
|
|
57
|
+
data-position={position}
|
|
58
|
+
data-size={size}
|
|
59
|
+
>
|
|
60
|
+
<span className={styles.abBadgeValue}>{formatCount(count, maxCount)}</span>
|
|
61
|
+
</span>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default AbBadge;
|
|
66
|
+
export { AbBadge };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* AbBadge — server, plain CSS */
|
|
2
|
+
.abBadge {
|
|
3
|
+
position: absolute;
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
width: fit-content;
|
|
6
|
+
height: fit-content;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
border-radius: 9999px;
|
|
9
|
+
padding: 0.125rem 0.375rem;
|
|
10
|
+
font-weight: 700;
|
|
11
|
+
line-height: 1.25;
|
|
12
|
+
pointer-events: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.abBadgeValue {
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
text-overflow: ellipsis;
|
|
18
|
+
white-space: nowrap;
|
|
19
|
+
letter-spacing: 0.04em;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.color_default {
|
|
23
|
+
background: var(--ab-badge-bg, #e8def8);
|
|
24
|
+
color: var(--ab-badge-fg, #4a4458);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.color_red {
|
|
28
|
+
background: #dc2626;
|
|
29
|
+
color: #fff;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.pos_top_left { top: 0.25rem; left: 0.375rem; }
|
|
33
|
+
.pos_top_right { top: 0.25rem; right: 0.375rem; }
|
|
34
|
+
.pos_bottom_left { bottom: 0.25rem; left: 0.375rem; }
|
|
35
|
+
.pos_bottom_right { bottom: 0.25rem; right: 0.375rem; }
|
|
36
|
+
|
|
37
|
+
.size_small { font-size: 0.75rem; }
|
|
38
|
+
.size_medium { font-size: 0.875rem; }
|
|
39
|
+
.size_large { font-size: 1rem; }
|