mtrl 0.2.1 → 0.2.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/.typedocignore +11 -0
- package/DOCS.md +153 -0
- package/index.ts +18 -3
- package/package.json +7 -2
- package/src/components/badge/_styles.scss +174 -0
- package/src/components/badge/api.ts +292 -0
- package/src/components/badge/badge.ts +52 -0
- package/src/components/badge/config.ts +68 -0
- package/src/components/badge/constants.ts +30 -0
- package/src/components/badge/features.ts +185 -0
- package/src/components/badge/index.ts +4 -0
- package/src/components/badge/types.ts +105 -0
- package/src/components/button/types.ts +174 -29
- package/src/components/card/constants.ts +14 -0
- package/src/components/carousel/_styles.scss +645 -0
- package/src/components/carousel/api.ts +147 -0
- package/src/components/carousel/carousel.ts +178 -0
- package/src/components/carousel/config.ts +91 -0
- package/src/components/carousel/constants.ts +95 -0
- package/src/components/carousel/features/drag.ts +388 -0
- package/src/components/carousel/features/index.ts +8 -0
- package/src/components/carousel/features/slides.ts +682 -0
- package/src/components/carousel/index.ts +38 -0
- package/src/components/carousel/types.ts +327 -0
- package/src/components/chip/_styles.scss +83 -140
- package/src/components/chip/api.ts +231 -102
- package/src/components/chip/chip.ts +356 -44
- package/src/components/chip/constants.ts +3 -3
- package/src/components/chip/index.ts +3 -3
- package/src/components/dialog/_styles.scss +213 -0
- package/src/components/dialog/api.ts +283 -0
- package/src/components/dialog/config.ts +113 -0
- package/src/components/dialog/constants.ts +32 -0
- package/src/components/dialog/dialog.ts +56 -0
- package/src/components/dialog/features.ts +713 -0
- package/src/components/dialog/index.ts +15 -0
- package/src/components/dialog/types.ts +221 -0
- package/src/components/progress/_styles.scss +13 -1
- package/src/components/progress/api.ts +2 -2
- package/src/components/progress/progress.ts +2 -2
- package/src/components/progress/types.ts +3 -0
- package/src/components/radios/_styles.scss +232 -0
- package/src/components/radios/api.ts +100 -0
- package/src/components/radios/config.ts +60 -0
- package/src/components/radios/constants.ts +28 -0
- package/src/components/radios/index.ts +4 -0
- package/src/components/radios/radio.ts +269 -0
- package/src/components/radios/radios.ts +42 -0
- package/src/components/radios/types.ts +232 -0
- package/src/components/sheet/_styles.scss +236 -0
- package/src/components/sheet/api.ts +96 -0
- package/src/components/sheet/config.ts +66 -0
- package/src/components/sheet/constants.ts +20 -0
- package/src/components/sheet/features/content.ts +51 -0
- package/src/components/sheet/features/gestures.ts +177 -0
- package/src/components/sheet/features/index.ts +6 -0
- package/src/components/sheet/features/position.ts +42 -0
- package/src/components/sheet/features/state.ts +116 -0
- package/src/components/sheet/features/title.ts +86 -0
- package/src/components/sheet/index.ts +4 -0
- package/src/components/sheet/sheet.ts +57 -0
- package/src/components/sheet/types.ts +266 -0
- package/src/components/slider/_styles.scss +518 -0
- package/src/components/slider/api.ts +336 -0
- package/src/components/slider/config.ts +145 -0
- package/src/components/slider/constants.ts +28 -0
- package/src/components/slider/features/appearance.ts +140 -0
- package/src/components/slider/features/disabled.ts +43 -0
- package/src/components/slider/features/events.ts +164 -0
- package/src/components/slider/features/index.ts +5 -0
- package/src/components/slider/features/interactions.ts +256 -0
- package/src/components/slider/features/keyboard.ts +114 -0
- package/src/components/slider/features/slider.ts +336 -0
- package/src/components/slider/features/structure.ts +264 -0
- package/src/components/slider/features/ui.ts +518 -0
- package/src/components/slider/index.ts +9 -0
- package/src/components/slider/slider.ts +58 -0
- package/src/components/slider/types.ts +166 -0
- package/src/components/tabs/_styles.scss +224 -0
- package/src/components/tabs/api.ts +443 -0
- package/src/components/tabs/config.ts +80 -0
- package/src/components/tabs/constants.ts +12 -0
- package/src/components/tabs/index.ts +4 -0
- package/src/components/tabs/tabs.ts +52 -0
- package/src/components/tabs/types.ts +247 -0
- package/src/components/textfield/_styles.scss +97 -4
- package/src/components/tooltip/_styles.scss +241 -0
- package/src/components/tooltip/api.ts +411 -0
- package/src/components/tooltip/config.ts +78 -0
- package/src/components/tooltip/constants.ts +27 -0
- package/src/components/tooltip/index.ts +4 -0
- package/src/components/tooltip/tooltip.ts +60 -0
- package/src/components/tooltip/types.ts +178 -0
- package/src/index.ts +9 -1
- package/src/styles/abstract/_variables.scss +24 -0
- package/tsconfig.json +22 -0
- package/typedoc.json +28 -0
- package/typedoc.simple.json +14 -0
package/.typedocignore
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Ignore files with TypeScript errors
|
|
2
|
+
src/components/snackbar/api.ts
|
|
3
|
+
src/components/snackbar/config.ts
|
|
4
|
+
src/components/snackbar/features.ts
|
|
5
|
+
src/components/snackbar/index.ts
|
|
6
|
+
src/components/snackbar/position.ts
|
|
7
|
+
src/components/snackbar/queue.ts
|
|
8
|
+
src/components/snackbar/snackbar.ts
|
|
9
|
+
src/components/chip/chip-set.ts
|
|
10
|
+
src/components/chip/chip.ts
|
|
11
|
+
src/components/menu/features/items-manager.ts
|
package/DOCS.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# TypeDoc Installation and Usage Guide for MTRL
|
|
2
|
+
|
|
3
|
+
This guide will help you set up and use TypeDoc with your MTRL library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To install TypeDoc and its dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Using Bun
|
|
11
|
+
bun add -D typedoc
|
|
12
|
+
|
|
13
|
+
# Using npm
|
|
14
|
+
npm install --save-dev typedoc
|
|
15
|
+
|
|
16
|
+
# Using yarn
|
|
17
|
+
yarn add --dev typedoc
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
TypeDoc is configured via the `typedoc.json` file at the root of your project. This configuration specifies input files, output directory, theming options, and more.
|
|
23
|
+
|
|
24
|
+
## Generating Documentation
|
|
25
|
+
|
|
26
|
+
To generate documentation:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Using the npm script
|
|
30
|
+
bun run docs
|
|
31
|
+
|
|
32
|
+
# Or directly
|
|
33
|
+
bun typedoc
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Serving Documentation Locally
|
|
37
|
+
|
|
38
|
+
To view the generated documentation in your browser:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Using the npm script
|
|
42
|
+
bun run docs:serve
|
|
43
|
+
|
|
44
|
+
# Or directly
|
|
45
|
+
bun run --bun serve docs
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then open your browser to http://localhost:8080
|
|
49
|
+
|
|
50
|
+
## Documentation Structure
|
|
51
|
+
|
|
52
|
+
TypeDoc generates a structured representation of your codebase:
|
|
53
|
+
|
|
54
|
+
- **Modules**: File-based organization of your code
|
|
55
|
+
- **Classes/Interfaces**: Object definitions and their members
|
|
56
|
+
- **Functions**: Standalone functions
|
|
57
|
+
- **Type aliases**: Custom type definitions
|
|
58
|
+
- **Variables**: Exported variables
|
|
59
|
+
|
|
60
|
+
## JSDoc Tips for Better Documentation
|
|
61
|
+
|
|
62
|
+
TypeDoc uses JSDoc comments to generate documentation. Here are some tips for writing effective comments:
|
|
63
|
+
|
|
64
|
+
### Basic Comment Structure
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
/**
|
|
68
|
+
* Description of the function
|
|
69
|
+
* @param paramName Description of the parameter
|
|
70
|
+
* @returns Description of the return value
|
|
71
|
+
*/
|
|
72
|
+
function myFunction(paramName: string): number {
|
|
73
|
+
// Implementation
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Common JSDoc Tags
|
|
78
|
+
|
|
79
|
+
- `@param {type} name - Description` - Describes a function parameter
|
|
80
|
+
- `@returns {type} Description` - Describes the return value
|
|
81
|
+
- `@example` - Provides an example of usage
|
|
82
|
+
- `@see` - References related documentation
|
|
83
|
+
- `@deprecated` - Marks an element as deprecated
|
|
84
|
+
- `@since version` - Indicates when the element was added
|
|
85
|
+
- `@category name` - Organizes documentation into categories
|
|
86
|
+
|
|
87
|
+
### Categories
|
|
88
|
+
|
|
89
|
+
Use the `@category` tag to organize your MTRL components and utilities:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
/**
|
|
93
|
+
* @category Components
|
|
94
|
+
*/
|
|
95
|
+
export interface ButtonConfig {
|
|
96
|
+
// ...
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @category Core
|
|
101
|
+
*/
|
|
102
|
+
export const pipe = (...fns) => (initialValue) => {
|
|
103
|
+
// ...
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Customizing the Theme
|
|
108
|
+
|
|
109
|
+
If you want to customize the default theme, you can create a custom theme:
|
|
110
|
+
|
|
111
|
+
1. Create a `typedoc-theme` directory
|
|
112
|
+
2. Copy the default theme files from the TypeDoc package
|
|
113
|
+
3. Modify the files as needed
|
|
114
|
+
4. Update the `typedoc.json` file to use your custom theme:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"theme": "./typedoc-theme"
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Continuous Integration
|
|
123
|
+
|
|
124
|
+
To automatically generate documentation on each commit or release:
|
|
125
|
+
|
|
126
|
+
1. Add a script to your CI workflow (GitHub Actions, etc.)
|
|
127
|
+
2. Generate the docs and deploy them to GitHub Pages or another hosting service
|
|
128
|
+
|
|
129
|
+
Example GitHub Actions workflow:
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
name: Generate Docs
|
|
133
|
+
|
|
134
|
+
on:
|
|
135
|
+
push:
|
|
136
|
+
branches: [main]
|
|
137
|
+
|
|
138
|
+
jobs:
|
|
139
|
+
build:
|
|
140
|
+
runs-on: ubuntu-latest
|
|
141
|
+
steps:
|
|
142
|
+
- uses: actions/checkout@v3
|
|
143
|
+
- uses: oven-sh/setup-bun@v1
|
|
144
|
+
- name: Install dependencies
|
|
145
|
+
run: bun install
|
|
146
|
+
- name: Generate docs
|
|
147
|
+
run: bun run docs
|
|
148
|
+
- name: Deploy to GitHub Pages
|
|
149
|
+
uses: JamesIves/github-pages-deploy-action@4.1.4
|
|
150
|
+
with:
|
|
151
|
+
branch: gh-pages
|
|
152
|
+
folder: docs
|
|
153
|
+
```
|
package/index.ts
CHANGED
|
@@ -2,32 +2,47 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createLayout,
|
|
4
4
|
createElement,
|
|
5
|
+
createBadge,
|
|
5
6
|
createButton,
|
|
6
7
|
createCard,
|
|
8
|
+
createCarousel,
|
|
7
9
|
createCheckbox,
|
|
8
10
|
createChip,
|
|
11
|
+
createDialog,
|
|
9
12
|
createList,
|
|
10
13
|
createMenu,
|
|
11
14
|
createNavigation,
|
|
12
15
|
createProgress,
|
|
13
|
-
|
|
16
|
+
createRadios,
|
|
17
|
+
createSheet,
|
|
18
|
+
createSlider,
|
|
14
19
|
createSnackbar,
|
|
20
|
+
createTabs,
|
|
21
|
+
createTextfield,
|
|
22
|
+
createTooltip,
|
|
15
23
|
createSwitch
|
|
16
|
-
|
|
17
24
|
} from './src/index.js'
|
|
18
25
|
|
|
19
26
|
export {
|
|
20
27
|
createLayout,
|
|
21
28
|
createElement,
|
|
29
|
+
createBadge,
|
|
22
30
|
createButton,
|
|
23
31
|
createCard,
|
|
32
|
+
createCarousel,
|
|
24
33
|
createCheckbox,
|
|
25
34
|
createChip,
|
|
35
|
+
createDialog,
|
|
26
36
|
createList,
|
|
27
37
|
createMenu,
|
|
28
38
|
createNavigation,
|
|
29
39
|
createProgress,
|
|
30
|
-
|
|
40
|
+
createRadios,
|
|
41
|
+
createSheet,
|
|
42
|
+
createSlider,
|
|
31
43
|
createSnackbar,
|
|
44
|
+
createTabs,
|
|
45
|
+
createTextfield,
|
|
46
|
+
createTooltip,
|
|
32
47
|
createSwitch
|
|
33
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mtrl",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "A functional JavaScript component library with composable architecture based on Material Design 3",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"component",
|
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
"test": "bun test",
|
|
16
16
|
"test:watch": "bun test --watch",
|
|
17
17
|
"test:coverage": "bun test --coverage",
|
|
18
|
-
"test:ui": "bun test --watch --ui"
|
|
18
|
+
"test:ui": "bun test --watch --ui",
|
|
19
|
+
"docs": "typedoc --skipErrorChecking",
|
|
20
|
+
"docs:js": "typedoc --options typedoc.simple.json",
|
|
21
|
+
"docs:alt": "bun generate-docs.js",
|
|
22
|
+
"docs:serve": "bun run --bun serve docs",
|
|
23
|
+
"docs:fix-errors": "tsc --noEmit --allowJs --skipLibCheck"
|
|
19
24
|
},
|
|
20
25
|
"repository": {
|
|
21
26
|
"type": "git",
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// src/components/badge/_styles.scss
|
|
2
|
+
@use '../../styles/abstract/base' as base;
|
|
3
|
+
@use '../../styles/abstract/variables' as v;
|
|
4
|
+
@use '../../styles/abstract/functions' as f;
|
|
5
|
+
@use '../../styles/abstract/mixins' as m;
|
|
6
|
+
@use '../../styles/abstract/theme' as t;
|
|
7
|
+
|
|
8
|
+
$component: '#{base.$prefix}-badge';
|
|
9
|
+
|
|
10
|
+
.#{$component} {
|
|
11
|
+
// Base styles
|
|
12
|
+
position: relative;
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
min-width: 20px;
|
|
18
|
+
height: 20px;
|
|
19
|
+
padding: 0 6px;
|
|
20
|
+
border-radius: 10px;
|
|
21
|
+
background-color: t.color('error');
|
|
22
|
+
color: t.color('on-error');
|
|
23
|
+
font-size: 11px;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
line-height: 1;
|
|
26
|
+
letter-spacing: 0.5px;
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
text-align: center;
|
|
29
|
+
|
|
30
|
+
// Badge parent wrapper
|
|
31
|
+
&-wrapper {
|
|
32
|
+
position: relative;
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default positioning (top-right)
|
|
37
|
+
&--positioned {
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: -8px;
|
|
40
|
+
right: -8px;
|
|
41
|
+
transform: translate(50%, -50%);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Dot variant
|
|
45
|
+
&--dot {
|
|
46
|
+
min-width: 8px;
|
|
47
|
+
height: 8px;
|
|
48
|
+
padding: 0;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Small size
|
|
53
|
+
&--small {
|
|
54
|
+
min-width: 16px;
|
|
55
|
+
height: 16px;
|
|
56
|
+
font-size: 10px;
|
|
57
|
+
padding: 0 4px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Large size
|
|
61
|
+
&--large {
|
|
62
|
+
min-width: 24px;
|
|
63
|
+
height: 24px;
|
|
64
|
+
font-size: 12px;
|
|
65
|
+
padding: 0 8px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Position variants
|
|
69
|
+
&--top-left {
|
|
70
|
+
top: 0;
|
|
71
|
+
left: 0;
|
|
72
|
+
transform: translate(-50%, -50%);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&--top-right {
|
|
76
|
+
top: 0;
|
|
77
|
+
right: 0;
|
|
78
|
+
transform: translate(50%, -50%);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&--bottom-left {
|
|
82
|
+
bottom: 0;
|
|
83
|
+
left: 0;
|
|
84
|
+
transform: translate(-50%, 50%);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&--bottom-right {
|
|
88
|
+
bottom: 0;
|
|
89
|
+
right: 0;
|
|
90
|
+
transform: translate(50%, 50%);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Color variants
|
|
94
|
+
&--primary {
|
|
95
|
+
background-color: t.color('primary');
|
|
96
|
+
color: t.color('on-primary');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&--secondary {
|
|
100
|
+
background-color: t.color('secondary');
|
|
101
|
+
color: t.color('on-secondary');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&--tertiary {
|
|
105
|
+
background-color: t.color('tertiary');
|
|
106
|
+
color: t.color('on-tertiary');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&--error {
|
|
110
|
+
background-color: t.color('error');
|
|
111
|
+
color: t.color('on-error');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&--success {
|
|
115
|
+
background-color: t.color('success', t.color('primary'));
|
|
116
|
+
color: t.color('on-success', t.color('on-primary'));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&--warning {
|
|
120
|
+
background-color: t.color('warning', t.color('tertiary'));
|
|
121
|
+
color: t.color('on-warning', t.color('on-tertiary'));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
&--info {
|
|
125
|
+
background-color: t.color('info', t.color('secondary'));
|
|
126
|
+
color: t.color('on-info', t.color('on-secondary'));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Outline variant
|
|
130
|
+
&--outlined {
|
|
131
|
+
background-color: transparent;
|
|
132
|
+
border: 1px solid currentColor;
|
|
133
|
+
|
|
134
|
+
&.#{$component}--primary {
|
|
135
|
+
color: t.color('primary');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&.#{$component}--secondary {
|
|
139
|
+
color: t.color('secondary');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
&.#{$component}--tertiary {
|
|
143
|
+
color: t.color('tertiary');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
&.#{$component}--error {
|
|
147
|
+
color: t.color('error');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
&.#{$component}--success {
|
|
151
|
+
color: t.color('success', t.color('primary'));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&.#{$component}--warning {
|
|
155
|
+
color: t.color('warning', t.color('tertiary'));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&.#{$component}--info {
|
|
159
|
+
color: t.color('info', t.color('secondary'));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Max value handling
|
|
164
|
+
&--max {
|
|
165
|
+
&::after {
|
|
166
|
+
content: '+';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Invisible
|
|
171
|
+
&--invisible {
|
|
172
|
+
display: none;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// src/components/badge/api.ts
|
|
2
|
+
import { BadgeComponent } from './types';
|
|
3
|
+
import { BADGE_VARIANTS, BADGE_SIZES, BADGE_COLORS, BADGE_POSITIONS } from './constants';
|
|
4
|
+
|
|
5
|
+
interface ApiOptions {
|
|
6
|
+
visibility: {
|
|
7
|
+
show: () => void;
|
|
8
|
+
hide: () => void;
|
|
9
|
+
toggle: (visible?: boolean) => void;
|
|
10
|
+
isVisible: () => boolean;
|
|
11
|
+
};
|
|
12
|
+
lifecycle: {
|
|
13
|
+
destroy: () => void;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ComponentWithElements {
|
|
18
|
+
element: HTMLElement;
|
|
19
|
+
wrapper?: HTMLElement;
|
|
20
|
+
config: {
|
|
21
|
+
max?: number;
|
|
22
|
+
content?: string | number;
|
|
23
|
+
};
|
|
24
|
+
getClass: (name: string) => string;
|
|
25
|
+
addClass: (...classes: string[]) => any;
|
|
26
|
+
removeClass: (...classes: string[]) => any;
|
|
27
|
+
on: (event: string, handler: Function) => any;
|
|
28
|
+
off: (event: string, handler: Function) => any;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Enhances a badge component with API methods
|
|
33
|
+
* @param {ApiOptions} options - API configuration options
|
|
34
|
+
* @returns {Function} Higher-order function that adds API methods to component
|
|
35
|
+
* @internal This is an internal utility for the Badge component
|
|
36
|
+
*/
|
|
37
|
+
export const withAPI = ({ visibility, lifecycle }: ApiOptions) =>
|
|
38
|
+
(component: ComponentWithElements): BadgeComponent => ({
|
|
39
|
+
...component as any,
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sets the badge content
|
|
43
|
+
* @param {string|number} content - Content to display in the badge
|
|
44
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
45
|
+
*/
|
|
46
|
+
setContent(content: string | number) {
|
|
47
|
+
const stringContent = String(content);
|
|
48
|
+
component.config.content = content;
|
|
49
|
+
|
|
50
|
+
// If max is defined and content is a number greater than max, show max+
|
|
51
|
+
if (component.config.max !== undefined &&
|
|
52
|
+
typeof content === 'number' &&
|
|
53
|
+
content > component.config.max) {
|
|
54
|
+
component.element.textContent = String(component.config.max);
|
|
55
|
+
component.element.classList.add(`${component.getClass('badge')}--max`);
|
|
56
|
+
} else {
|
|
57
|
+
component.element.textContent = stringContent;
|
|
58
|
+
component.element.classList.remove(`${component.getClass('badge')}--max`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Toggle the dot variant based on whether content is empty
|
|
62
|
+
if (stringContent === '' || stringContent === '0') {
|
|
63
|
+
this.hide();
|
|
64
|
+
} else {
|
|
65
|
+
this.show();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return this;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets the badge content
|
|
73
|
+
* @returns {string} Current badge content
|
|
74
|
+
*/
|
|
75
|
+
getContent() {
|
|
76
|
+
return component.element.textContent || '';
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Shows the badge
|
|
81
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
82
|
+
*/
|
|
83
|
+
show() {
|
|
84
|
+
visibility.show();
|
|
85
|
+
return this;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Hides the badge
|
|
90
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
91
|
+
*/
|
|
92
|
+
hide() {
|
|
93
|
+
visibility.hide();
|
|
94
|
+
return this;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Toggles badge visibility
|
|
99
|
+
* @param {boolean} [visible] - Optional flag to force visibility state
|
|
100
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
101
|
+
*/
|
|
102
|
+
toggle(visible?: boolean) {
|
|
103
|
+
visibility.toggle(visible);
|
|
104
|
+
return this;
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Checks if the badge is visible
|
|
109
|
+
* @returns {boolean} True if badge is visible
|
|
110
|
+
*/
|
|
111
|
+
isVisible() {
|
|
112
|
+
return visibility.isVisible();
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Sets maximum value (after which badge shows max+)
|
|
117
|
+
* @param {number} max - Maximum value to display
|
|
118
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
119
|
+
*/
|
|
120
|
+
setMax(max: number) {
|
|
121
|
+
component.config.max = max;
|
|
122
|
+
|
|
123
|
+
// Apply max formatting if current content exceeds max
|
|
124
|
+
if (typeof component.config.content === 'number' &&
|
|
125
|
+
component.config.content > max) {
|
|
126
|
+
component.element.textContent = String(max);
|
|
127
|
+
component.element.classList.add(`${component.getClass('badge')}--max`);
|
|
128
|
+
} else {
|
|
129
|
+
component.element.classList.remove(`${component.getClass('badge')}--max`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return this;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sets badge color
|
|
137
|
+
* @param {string} color - Color variant to apply
|
|
138
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
139
|
+
*/
|
|
140
|
+
setColor(color: keyof typeof BADGE_COLORS | BADGE_COLORS) {
|
|
141
|
+
// Remove existing color classes
|
|
142
|
+
Object.values(BADGE_COLORS).forEach(colorName => {
|
|
143
|
+
component.element.classList.remove(`${component.getClass('badge')}--${colorName}`);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Add new color class
|
|
147
|
+
component.element.classList.add(`${component.getClass('badge')}--${color}`);
|
|
148
|
+
return this;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Sets badge variant
|
|
153
|
+
* @param {string} variant - Variant to apply
|
|
154
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
155
|
+
*/
|
|
156
|
+
setVariant(variant: keyof typeof BADGE_VARIANTS | BADGE_VARIANTS) {
|
|
157
|
+
// Remove existing variant classes
|
|
158
|
+
Object.values(BADGE_VARIANTS).forEach(variantName => {
|
|
159
|
+
component.element.classList.remove(`${component.getClass('badge')}--${variantName}`);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Add new variant class if not standard
|
|
163
|
+
if (variant !== BADGE_VARIANTS.STANDARD) {
|
|
164
|
+
component.element.classList.add(`${component.getClass('badge')}--${variant}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Clear content if dot variant
|
|
168
|
+
if (variant === BADGE_VARIANTS.DOT) {
|
|
169
|
+
component.element.textContent = '';
|
|
170
|
+
} else if (component.config.content !== undefined) {
|
|
171
|
+
this.setContent(component.config.content);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return this;
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Sets badge size
|
|
179
|
+
* @param {string} size - Size variant to apply
|
|
180
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
181
|
+
*/
|
|
182
|
+
setSize(size: keyof typeof BADGE_SIZES | BADGE_SIZES) {
|
|
183
|
+
// Remove existing size classes
|
|
184
|
+
Object.values(BADGE_SIZES).forEach(sizeName => {
|
|
185
|
+
component.element.classList.remove(`${component.getClass('badge')}--${sizeName}`);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Add new size class if not medium (default)
|
|
189
|
+
if (size !== BADGE_SIZES.MEDIUM) {
|
|
190
|
+
component.element.classList.add(`${component.getClass('badge')}--${size}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return this;
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Sets badge position
|
|
198
|
+
* @param {string} position - Position variant to apply
|
|
199
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
200
|
+
*/
|
|
201
|
+
setPosition(position: keyof typeof BADGE_POSITIONS | BADGE_POSITIONS) {
|
|
202
|
+
// Remove existing position classes
|
|
203
|
+
Object.values(BADGE_POSITIONS).forEach(posName => {
|
|
204
|
+
component.element.classList.remove(`${component.getClass('badge')}--${posName}`);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Add new position class
|
|
208
|
+
component.element.classList.add(`${component.getClass('badge')}--${position}`);
|
|
209
|
+
|
|
210
|
+
return this;
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Attaches badge to a target element
|
|
215
|
+
* @param {HTMLElement} target - Element to attach badge to
|
|
216
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
217
|
+
*/
|
|
218
|
+
attachTo(target: HTMLElement) {
|
|
219
|
+
// If we already have a wrapper, remove the badge from it
|
|
220
|
+
if (component.wrapper && component.wrapper.contains(component.element)) {
|
|
221
|
+
component.wrapper.removeChild(component.element);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Create a new wrapper to hold the target and badge
|
|
225
|
+
const wrapper = document.createElement('div');
|
|
226
|
+
wrapper.classList.add(component.getClass('badge-wrapper'));
|
|
227
|
+
|
|
228
|
+
// Replace the target with the wrapper
|
|
229
|
+
const parent = target.parentNode;
|
|
230
|
+
if (parent) {
|
|
231
|
+
parent.replaceChild(wrapper, target);
|
|
232
|
+
wrapper.appendChild(target);
|
|
233
|
+
wrapper.appendChild(component.element);
|
|
234
|
+
|
|
235
|
+
// Make sure the badge is positioned
|
|
236
|
+
component.element.classList.add(`${component.getClass('badge')}--positioned`);
|
|
237
|
+
|
|
238
|
+
// Save the wrapper reference
|
|
239
|
+
component.wrapper = wrapper;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return this;
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Makes badge standalone (removes from wrapper)
|
|
247
|
+
* @returns {BadgeComponent} Badge component instance for chaining
|
|
248
|
+
*/
|
|
249
|
+
detach() {
|
|
250
|
+
if (component.wrapper && component.wrapper.contains(component.element)) {
|
|
251
|
+
// Remove the badge from the wrapper
|
|
252
|
+
component.wrapper.removeChild(component.element);
|
|
253
|
+
|
|
254
|
+
// Remove the positioned class
|
|
255
|
+
component.element.classList.remove(`${component.getClass('badge')}--positioned`);
|
|
256
|
+
|
|
257
|
+
// Add the badge to the document body or another container
|
|
258
|
+
document.body.appendChild(component.element);
|
|
259
|
+
|
|
260
|
+
// Clear the wrapper reference
|
|
261
|
+
component.wrapper = undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return this;
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Destroys the badge component and cleans up resources
|
|
269
|
+
*/
|
|
270
|
+
destroy() {
|
|
271
|
+
lifecycle.destroy();
|
|
272
|
+
|
|
273
|
+
// If badge is in a wrapper, restore the original DOM structure
|
|
274
|
+
if (component.wrapper) {
|
|
275
|
+
const target = component.wrapper.firstChild as HTMLElement;
|
|
276
|
+
const parent = component.wrapper.parentNode;
|
|
277
|
+
|
|
278
|
+
if (parent && target) {
|
|
279
|
+
parent.replaceChild(target, component.wrapper);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
// Forward basic component methods for API consistency
|
|
285
|
+
getClass: component.getClass,
|
|
286
|
+
addClass: component.addClass,
|
|
287
|
+
removeClass: component.removeClass,
|
|
288
|
+
on: component.on,
|
|
289
|
+
off: component.off,
|
|
290
|
+
element: component.element,
|
|
291
|
+
wrapper: component.wrapper
|
|
292
|
+
});
|