@behivetech/get-class-name 0.0.0-stage → 0.0.7

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/README.md CHANGED
@@ -1,3 +1,287 @@
1
- # Temporary Holding Version
1
+ # getClassName
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A utility for generating BEM-style class names with support for CSS modules, modifiers, and child elements.
4
+
5
+ A powerful utility for generating BEM (Block Element Modifier) style class names with built-in support for CSS modules, conditional modifiers, and child element naming.
6
+
7
+ ## Features
8
+
9
+ - **BEM Convention**: Automatically generates proper BEM-style class names
10
+ - **CSS Modules Support**: Works seamlessly with CSS/SCSS modules and styled components
11
+ - **Conditional Modifiers**: Apply modifiers based on boolean conditions
12
+ - **Child Element Helper**: Generate consistent child element class names
13
+ - **TypeScript Support**: Fully typed with comprehensive interfaces
14
+
15
+ ## Basic Usage
16
+
17
+ ```tsx
18
+ import { getClassName } from '@behivetech/get-class-name';
19
+
20
+ // Basic component setup
21
+ const [rootClass, getChildClass] = getClassName({
22
+ rootClass: 'button',
23
+ });
24
+
25
+ console.log(rootClass); // 'button'
26
+ console.log(getChildClass('text')); // 'button__text'
27
+ console.log(getChildClass('icon')); // 'button__icon'
28
+ ```
29
+
30
+ ## With Modifiers
31
+
32
+ ```tsx
33
+ const [buttonClass, getChildClass] = getClassName({
34
+ rootClass: 'button',
35
+ modifiers: {
36
+ primary: true,
37
+ large: true,
38
+ disabled: false,
39
+ },
40
+ });
41
+
42
+ console.log(buttonClass);
43
+ // 'button button--primary button--large'
44
+ ```
45
+
46
+ ## With Custom className
47
+
48
+ ```tsx
49
+ const [buttonClass] = getClassName({
50
+ rootClass: 'button',
51
+ className: 'my-custom-class another-class',
52
+ modifiers: {
53
+ primary: true,
54
+ },
55
+ });
56
+
57
+ console.log(buttonClass);
58
+ // 'my-custom-class another-class button button--primary'
59
+ ```
60
+
61
+ ## With CSS Modules
62
+
63
+ ```tsx
64
+ import styles from './Button.module.css';
65
+
66
+ const [buttonClass, getChildClass] = getClassName({
67
+ rootClass: 'button',
68
+ styles,
69
+ modifiers: {
70
+ primary: isActive,
71
+ disabled: !isEnabled,
72
+ },
73
+ });
74
+
75
+ // If styles object contains:
76
+ // {
77
+ // 'button': 'Button_button__3xKl2',
78
+ // 'button--primary': 'Button_primary__8mN4k',
79
+ // 'button__text': 'Button_text__5pL9x'
80
+ // }
81
+
82
+ console.log(buttonClass);
83
+ // 'Button_button__3xKl2 Button_primary__8mN4k'
84
+ console.log(getChildClass('text'));
85
+ // 'Button_text__5pL9x'
86
+ ```
87
+
88
+ ## React Component Example
89
+
90
+ ```tsx
91
+ import React from 'react';
92
+ import { getClassName } from '@behivetech/get-class-name';
93
+ import styles from './Button.module.css';
94
+
95
+ interface ButtonProps {
96
+ children: React.ReactNode;
97
+ className?: string;
98
+ variant?: 'primary' | 'secondary';
99
+ size?: 'small' | 'medium' | 'large';
100
+ disabled?: boolean;
101
+ onClick?: () => void;
102
+ }
103
+
104
+ export const Button: React.FC<ButtonProps> = ({
105
+ children,
106
+ className,
107
+ variant = 'primary',
108
+ size = 'medium',
109
+ disabled = false,
110
+ onClick,
111
+ }) => {
112
+ const [rootClass, getChildClass] = getClassName({
113
+ rootClass: 'button',
114
+ className,
115
+ styles,
116
+ modifiers: {
117
+ [variant]: true,
118
+ [size]: true,
119
+ disabled,
120
+ },
121
+ });
122
+
123
+ return (
124
+ <button className={rootClass} disabled={disabled} onClick={onClick}>
125
+ <span className={getChildClass('text')}>{children}</span>
126
+ </button>
127
+ );
128
+ };
129
+ ```
130
+
131
+ ## CSS Example
132
+
133
+ ```css
134
+ /* Button.module.css */
135
+ .button {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ padding: 8px 16px;
139
+ border: none;
140
+ border-radius: 4px;
141
+ cursor: pointer;
142
+ transition: all 0.2s ease;
143
+ }
144
+
145
+ .button--primary {
146
+ background-color: #007bff;
147
+ color: white;
148
+ }
149
+
150
+ .button--secondary {
151
+ background-color: #6c757d;
152
+ color: white;
153
+ }
154
+
155
+ .button--small {
156
+ padding: 4px 8px;
157
+ font-size: 12px;
158
+ }
159
+
160
+ .button--large {
161
+ padding: 12px 24px;
162
+ font-size: 18px;
163
+ }
164
+
165
+ .button--disabled {
166
+ opacity: 0.5;
167
+ cursor: not-allowed;
168
+ }
169
+
170
+ .button__text {
171
+ font-weight: 500;
172
+ }
173
+ ```
174
+
175
+ ## API Reference
176
+
177
+ ### getClassName(props)
178
+
179
+ #### Parameters
180
+
181
+ | Parameter | Type | Required | Description |
182
+ | ----------- | ------------------------- | -------- | ---------------------------------------------------------------------------- |
183
+ | `rootClass` | `string` | yes | The base class name for the component |
184
+ | `className` | `string` | no | Additional custom class names |
185
+ | `modifiers` | `Record<string, boolean>` | no | Object where keys are modifier names and values determine if they're applied |
186
+ | `styles` | `Record<string, string>` | no | CSS modules styles object for class name mapping |
187
+
188
+ #### Returns
189
+
190
+ Returns a tuple `[rootClass, getChildClass]`:
191
+
192
+ - **`rootClass`** (`string`): The computed root class name with all modifiers and custom classes
193
+ - **`getChildClass`** (`function`): Function that takes a child element name and returns the BEM child class
194
+
195
+ ### getChildClass(childClassName)
196
+
197
+ #### Parameters
198
+
199
+ | Parameter | Type | Required | Description |
200
+ | ---------------- | -------- | -------- | ------------------------- |
201
+ | `childClassName` | `string` | yes | Name of the child element |
202
+
203
+ #### Returns
204
+
205
+ - **`string`**: The computed BEM child class name (e.g., `block__element`)
206
+
207
+ ## Best Practices
208
+
209
+ ### Consistent Naming Convention
210
+
211
+ ```tsx
212
+ // Good: Use clear, descriptive names
213
+ const [cardClass, getChildClass] = getClassName({
214
+ rootClass: 'product-card',
215
+ modifiers: { featured: true, soldOut: false },
216
+ });
217
+ ```
218
+
219
+ ### Organize Modifiers Logically
220
+
221
+ ```tsx
222
+ const modifiers = {
223
+ // State modifiers
224
+ active: isActive,
225
+ disabled: isDisabled,
226
+ loading: isLoading,
227
+
228
+ // Appearance modifiers
229
+ primary: variant === 'primary',
230
+ large: size === 'large',
231
+ outlined: appearance === 'outlined',
232
+ };
233
+ ```
234
+
235
+ ### Use with CSS Custom Properties
236
+
237
+ ```css
238
+ .button {
239
+ --button-color: #007bff;
240
+ --button-padding: 8px 16px;
241
+
242
+ background-color: var(--button-color);
243
+ padding: var(--button-padding);
244
+ }
245
+
246
+ .button--large {
247
+ --button-padding: 12px 24px;
248
+ }
249
+ ```
250
+
251
+ ## Common Patterns
252
+
253
+ ### Conditional Styling
254
+
255
+ ```tsx
256
+ const [alertClass] = getClassName({
257
+ rootClass: 'alert',
258
+ modifiers: {
259
+ success: type === 'success',
260
+ error: type === 'error',
261
+ warning: type === 'warning',
262
+ dismissible: onClose !== undefined,
263
+ },
264
+ });
265
+ ```
266
+
267
+ ### Complex Component Structure
268
+
269
+ ```tsx
270
+ const [modalClass, getChildClass] = getClassName({
271
+ rootClass: 'modal',
272
+ modifiers: { open: isOpen, fullscreen: isFullscreen },
273
+ });
274
+
275
+ return (
276
+ <div className={modalClass}>
277
+ <div className={getChildClass('backdrop')} />
278
+ <div className={getChildClass('content')}>
279
+ <header className={getChildClass('header')}>
280
+ <h2 className={getChildClass('title')}>{title}</h2>
281
+ <button className={getChildClass('close-button')} />
282
+ </header>
283
+ <div className={getChildClass('body')}>{children}</div>
284
+ </div>
285
+ </div>
286
+ );
287
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ getClassName: () => getClassName
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // get-class-name.ts
38
+ var import_classnames = __toESM(require("classnames"), 1);
39
+ var getClassName = ({
40
+ className,
41
+ modifiers = {},
42
+ rootClass,
43
+ styles = {}
44
+ }) => {
45
+ function getModifiers() {
46
+ const updatedModifiers = {};
47
+ const modifierKeys = Object.keys(modifiers);
48
+ if (modifierKeys.length) {
49
+ modifierKeys.forEach((modKey) => {
50
+ const classKey = `${rootClass}--${modKey}`;
51
+ const newClassName = styles[classKey] || classKey;
52
+ updatedModifiers[newClassName] = modifiers[modKey] ?? false;
53
+ });
54
+ }
55
+ return updatedModifiers;
56
+ }
57
+ function getChildClass(childClassName) {
58
+ const classKey = `${rootClass}__${childClassName}`;
59
+ return styles[classKey] || classKey;
60
+ }
61
+ function getRootStyles() {
62
+ return (0, import_classnames.default)(
63
+ className,
64
+ {
65
+ ...getModifiers()
66
+ },
67
+ styles[rootClass] || rootClass
68
+ );
69
+ }
70
+ return [getRootStyles(), getChildClass];
71
+ };
72
+ // Annotate the CommonJS export names for ESM import in node:
73
+ 0 && (module.exports = {
74
+ getClassName
75
+ });
76
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts","../get-class-name.ts"],"sourcesContent":["export { getClassName } from './get-class-name.js';\n","import classnames from 'classnames';\n\ninterface IGetClassNameProps {\n /** className prop generally passed in from the parent component */\n className?: string;\n /**\n object where the key is any additional classNames used to modify the elements of the compoent.\n If the value of the key is true, it will add the name of the key to the className\n */\n modifiers?: { [key: string]: boolean };\n /** className for the component */\n rootClass: string;\n styles?: { [key: string]: string };\n}\n\nexport const getClassName = ({\n className,\n modifiers = {},\n rootClass,\n styles = {},\n}: IGetClassNameProps): [string, (childClassName: string) => string] => {\n function getModifiers() {\n const updatedModifiers: { [key: string]: boolean } = {};\n const modifierKeys = Object.keys(modifiers);\n if (modifierKeys.length) {\n modifierKeys.forEach((modKey) => {\n const classKey = `${rootClass}--${modKey}`;\n const newClassName: string = styles[classKey] || classKey;\n\n updatedModifiers[newClassName] = modifiers[modKey] ?? false;\n });\n }\n\n return updatedModifiers;\n }\n\n function getChildClass(childClassName: string) {\n const classKey = `${rootClass}__${childClassName}`;\n return styles[classKey] || classKey;\n }\n\n function getRootStyles() {\n return classnames(\n className,\n {\n ...getModifiers(),\n },\n styles[rootClass] || rootClass\n );\n }\n\n return [getRootStyles(), getChildClass];\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,wBAAuB;AAehB,IAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA,SAAS,CAAC;AACZ,MAAwE;AACtE,WAAS,eAAe;AACtB,UAAM,mBAA+C,CAAC;AACtD,UAAM,eAAe,OAAO,KAAK,SAAS;AAC1C,QAAI,aAAa,QAAQ;AACvB,mBAAa,QAAQ,CAAC,WAAW;AAC/B,cAAM,WAAW,GAAG,SAAS,KAAK,MAAM;AACxC,cAAM,eAAuB,OAAO,QAAQ,KAAK;AAEjD,yBAAiB,YAAY,IAAI,UAAU,MAAM,KAAK;AAAA,MACxD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,cAAc,gBAAwB;AAC7C,UAAM,WAAW,GAAG,SAAS,KAAK,cAAc;AAChD,WAAO,OAAO,QAAQ,KAAK;AAAA,EAC7B;AAEA,WAAS,gBAAgB;AACvB,eAAO,kBAAAA;AAAA,MACL;AAAA,MACA;AAAA,QACE,GAAG,aAAa;AAAA,MAClB;AAAA,MACA,OAAO,SAAS,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,CAAC,cAAc,GAAG,aAAa;AACxC;","names":["classnames"]}
@@ -0,0 +1,19 @@
1
+ interface IGetClassNameProps {
2
+ /** className prop generally passed in from the parent component */
3
+ className?: string;
4
+ /**
5
+ object where the key is any additional classNames used to modify the elements of the compoent.
6
+ If the value of the key is true, it will add the name of the key to the className
7
+ */
8
+ modifiers?: {
9
+ [key: string]: boolean;
10
+ };
11
+ /** className for the component */
12
+ rootClass: string;
13
+ styles?: {
14
+ [key: string]: string;
15
+ };
16
+ }
17
+ declare const getClassName: ({ className, modifiers, rootClass, styles, }: IGetClassNameProps) => [string, (childClassName: string) => string];
18
+
19
+ export { getClassName };
@@ -0,0 +1,19 @@
1
+ interface IGetClassNameProps {
2
+ /** className prop generally passed in from the parent component */
3
+ className?: string;
4
+ /**
5
+ object where the key is any additional classNames used to modify the elements of the compoent.
6
+ If the value of the key is true, it will add the name of the key to the className
7
+ */
8
+ modifiers?: {
9
+ [key: string]: boolean;
10
+ };
11
+ /** className for the component */
12
+ rootClass: string;
13
+ styles?: {
14
+ [key: string]: string;
15
+ };
16
+ }
17
+ declare const getClassName: ({ className, modifiers, rootClass, styles, }: IGetClassNameProps) => [string, (childClassName: string) => string];
18
+
19
+ export { getClassName };
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ // get-class-name.ts
2
+ import classnames from "classnames";
3
+ var getClassName = ({
4
+ className,
5
+ modifiers = {},
6
+ rootClass,
7
+ styles = {}
8
+ }) => {
9
+ function getModifiers() {
10
+ const updatedModifiers = {};
11
+ const modifierKeys = Object.keys(modifiers);
12
+ if (modifierKeys.length) {
13
+ modifierKeys.forEach((modKey) => {
14
+ const classKey = `${rootClass}--${modKey}`;
15
+ const newClassName = styles[classKey] || classKey;
16
+ updatedModifiers[newClassName] = modifiers[modKey] ?? false;
17
+ });
18
+ }
19
+ return updatedModifiers;
20
+ }
21
+ function getChildClass(childClassName) {
22
+ const classKey = `${rootClass}__${childClassName}`;
23
+ return styles[classKey] || classKey;
24
+ }
25
+ function getRootStyles() {
26
+ return classnames(
27
+ className,
28
+ {
29
+ ...getModifiers()
30
+ },
31
+ styles[rootClass] || rootClass
32
+ );
33
+ }
34
+ return [getRootStyles(), getChildClass];
35
+ };
36
+ export {
37
+ getClassName
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../get-class-name.ts"],"sourcesContent":["import classnames from 'classnames';\n\ninterface IGetClassNameProps {\n /** className prop generally passed in from the parent component */\n className?: string;\n /**\n object where the key is any additional classNames used to modify the elements of the compoent.\n If the value of the key is true, it will add the name of the key to the className\n */\n modifiers?: { [key: string]: boolean };\n /** className for the component */\n rootClass: string;\n styles?: { [key: string]: string };\n}\n\nexport const getClassName = ({\n className,\n modifiers = {},\n rootClass,\n styles = {},\n}: IGetClassNameProps): [string, (childClassName: string) => string] => {\n function getModifiers() {\n const updatedModifiers: { [key: string]: boolean } = {};\n const modifierKeys = Object.keys(modifiers);\n if (modifierKeys.length) {\n modifierKeys.forEach((modKey) => {\n const classKey = `${rootClass}--${modKey}`;\n const newClassName: string = styles[classKey] || classKey;\n\n updatedModifiers[newClassName] = modifiers[modKey] ?? false;\n });\n }\n\n return updatedModifiers;\n }\n\n function getChildClass(childClassName: string) {\n const classKey = `${rootClass}__${childClassName}`;\n return styles[classKey] || classKey;\n }\n\n function getRootStyles() {\n return classnames(\n className,\n {\n ...getModifiers(),\n },\n styles[rootClass] || rootClass\n );\n }\n\n return [getRootStyles(), getChildClass];\n};\n"],"mappings":";AAAA,OAAO,gBAAgB;AAehB,IAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA,SAAS,CAAC;AACZ,MAAwE;AACtE,WAAS,eAAe;AACtB,UAAM,mBAA+C,CAAC;AACtD,UAAM,eAAe,OAAO,KAAK,SAAS;AAC1C,QAAI,aAAa,QAAQ;AACvB,mBAAa,QAAQ,CAAC,WAAW;AAC/B,cAAM,WAAW,GAAG,SAAS,KAAK,MAAM;AACxC,cAAM,eAAuB,OAAO,QAAQ,KAAK;AAEjD,yBAAiB,YAAY,IAAI,UAAU,MAAM,KAAK;AAAA,MACxD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,cAAc,gBAAwB;AAC7C,UAAM,WAAW,GAAG,SAAS,KAAK,cAAc;AAChD,WAAO,OAAO,QAAQ,KAAK;AAAA,EAC7B;AAEA,WAAS,gBAAgB;AACvB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,GAAG,aAAa;AAAA,MAClB;AAAA,MACA,OAAO,SAAS,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,CAAC,cAAc,GAAG,aAAa;AACxC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,43 @@
1
1
  {
2
2
  "name": "@behivetech/get-class-name",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.7",
4
+ "type": "module",
5
+ "private": false,
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.cjs"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "classnames": "^2.5.1"
18
+ },
19
+ "devDependencies": {
20
+ "eslint": "^9.39.5",
21
+ "tsup": "^8.5.1",
22
+ "typescript": "^6.0.3",
23
+ "@behivetech/eslint-config": "0.1.0",
24
+ "@behivetech/typescript-config": "0.0.2"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/behivetech/bht-galaxy.git",
29
+ "directory": "packages/utils/get-class-name"
30
+ },
31
+ "publishConfig": {
32
+ "registry": "https://registry.npmjs.org",
33
+ "access": "public",
34
+ "provenance": true
35
+ },
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "dev": "tsup --watch",
39
+ "lint": "eslint . --max-warnings 0",
40
+ "check-types": "tsc --noEmit",
41
+ "test": "vitest run"
42
+ }
6
43
  }