react-bootstrap-plugins 1.0.5 → 2.1.0

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.
Files changed (83) hide show
  1. package/README.md +14 -7
  2. package/dist/AutoTextarea.cjs +2 -0
  3. package/dist/AutoTextarea.d.cts +29 -0
  4. package/dist/AutoTextarea.d.ts +29 -0
  5. package/dist/AutoTextarea.js +2 -0
  6. package/dist/DatePicker.cjs +2 -2
  7. package/dist/DatePicker.d.cts +57 -0
  8. package/dist/DatePicker.d.ts +54 -42
  9. package/dist/DatePicker.js +2 -2
  10. package/dist/Label.cjs +2 -2
  11. package/dist/Label.d.cts +15 -0
  12. package/dist/Label.d.ts +12 -13
  13. package/dist/Label.js +2 -2
  14. package/dist/SearchSelect.cjs +2 -2
  15. package/dist/SearchSelect.d.cts +40 -0
  16. package/dist/SearchSelect.d.ts +37 -28
  17. package/dist/SearchSelect.js +2 -2
  18. package/dist/TableLoading.cjs +2 -2
  19. package/dist/TableLoading.d.cts +13 -0
  20. package/dist/TableLoading.d.ts +10 -10
  21. package/dist/TableLoading.js +2 -2
  22. package/dist/chunk-2Q4NZKMX.cjs +2 -0
  23. package/dist/chunk-5IOLZUVD.cjs +2 -0
  24. package/dist/chunk-7LXLWNUR.js +2 -0
  25. package/dist/chunk-AWU5XGMI.cjs +2 -0
  26. package/dist/chunk-HYB5IGJK.js +2 -0
  27. package/dist/chunk-KKWFIJKN.js +2 -0
  28. package/dist/chunk-M3OUUXZG.cjs +2 -0
  29. package/dist/chunk-NPQQDBFB.cjs +2 -0
  30. package/dist/chunk-OEFG7PNW.cjs +2 -0
  31. package/dist/chunk-RR7TBRGI.js +2 -0
  32. package/dist/chunk-WLMCWTO6.js +2 -0
  33. package/dist/chunk-ZCAQ7S2A.js +2 -0
  34. package/dist/css/datepicker.css +1 -299
  35. package/dist/css/plugins.css +1 -0
  36. package/dist/index.cjs +2 -2
  37. package/dist/index.d.cts +6 -0
  38. package/dist/index.d.ts +6 -13
  39. package/dist/index.js +2 -2
  40. package/docs/AUTOTEXTAREA.md +106 -0
  41. package/docs/DATEPICKER.md +3 -3
  42. package/package.json +25 -8
  43. package/dist/DatePicker.cjs.map +0 -1
  44. package/dist/DatePicker.js.map +0 -1
  45. package/dist/Label.cjs.map +0 -1
  46. package/dist/Label.js.map +0 -1
  47. package/dist/SearchSelect.cjs.map +0 -1
  48. package/dist/SearchSelect.js.map +0 -1
  49. package/dist/TableLoading.cjs.map +0 -1
  50. package/dist/TableLoading.js.map +0 -1
  51. package/dist/chunk-2JC4VIKL.cjs +0 -2
  52. package/dist/chunk-2JC4VIKL.cjs.map +0 -1
  53. package/dist/chunk-46AJ2Q5H.js +0 -2
  54. package/dist/chunk-46AJ2Q5H.js.map +0 -1
  55. package/dist/chunk-J4TRPVD4.cjs +0 -2
  56. package/dist/chunk-J4TRPVD4.cjs.map +0 -1
  57. package/dist/chunk-KZEOI42M.cjs +0 -2
  58. package/dist/chunk-KZEOI42M.cjs.map +0 -1
  59. package/dist/chunk-MQRJBL7S.cjs +0 -2
  60. package/dist/chunk-MQRJBL7S.cjs.map +0 -1
  61. package/dist/chunk-MTRPXJ3C.js +0 -2
  62. package/dist/chunk-MTRPXJ3C.js.map +0 -1
  63. package/dist/chunk-QQNPKA7A.cjs +0 -2
  64. package/dist/chunk-QQNPKA7A.cjs.map +0 -1
  65. package/dist/chunk-W6UBCMKG.js +0 -2
  66. package/dist/chunk-W6UBCMKG.js.map +0 -1
  67. package/dist/chunk-WPTHY5AJ.js +0 -2
  68. package/dist/chunk-WPTHY5AJ.js.map +0 -1
  69. package/dist/chunk-XFHLZ7I3.js +0 -2
  70. package/dist/chunk-XFHLZ7I3.js.map +0 -1
  71. package/dist/index.cjs.map +0 -1
  72. package/dist/index.js.map +0 -1
  73. package/src/components/DatePicker.d.ts +0 -45
  74. package/src/components/DatePicker.jsx +0 -691
  75. package/src/components/Label.d.ts +0 -16
  76. package/src/components/Label.jsx +0 -22
  77. package/src/components/SearchSelect.d.ts +0 -31
  78. package/src/components/SearchSelect.jsx +0 -155
  79. package/src/components/TableLoading.d.ts +0 -13
  80. package/src/components/TableLoading.jsx +0 -43
  81. package/src/css/datepicker.css +0 -299
  82. package/src/index.js +0 -16
  83. package/src/lib/cn.js +0 -35
@@ -1,16 +0,0 @@
1
- import * as React from 'react'
2
-
3
- export interface LabelProps {
4
- /** Additional CSS classes */
5
- className?: string
6
- /** htmlFor attribute — associates label with input ID (default 'default') */
7
- hf?: string
8
- /** Whether to show the required asterisk (default true) */
9
- required?: boolean
10
- /** Label text content (default 'Title') */
11
- label?: string
12
- }
13
-
14
- export const Label: React.ForwardRefExoticComponent<
15
- LabelProps & React.RefAttributes<HTMLLabelElement>
16
- >
@@ -1,22 +0,0 @@
1
- import * as React from 'react'
2
-
3
- /**
4
- * A simple Bootstrap-styled form label with an optional required indicator.
5
- *
6
- * @param {string} [className] - Additional CSS classes
7
- * @param {string} [hf='default'] - htmlFor attribute (associates label with input ID)
8
- * @param {boolean} [required=true] - Whether to show the required asterisk
9
- * @param {string} [label='Title'] - Label text content
10
- */
11
- const Label = React.forwardRef(({ className, hf = 'default', required = true, label = 'Title' }, ref) => {
12
- return (
13
- <label htmlFor={hf} className={className} ref={ref}>
14
- {label}{required ? <b className="text-danger">*</b> : ''}
15
- </label>
16
- )
17
- })
18
-
19
- Label.displayName = 'Label'
20
-
21
- export { Label }
22
- export default Label
@@ -1,31 +0,0 @@
1
- import * as React from 'react'
2
-
3
- export interface SearchSelectProps<T = any> {
4
- /** Additional CSS classes on the wrapper */
5
- className?: string
6
- /** Selectable options — primitives (string/number/boolean) or objects */
7
- options?: T[] | Array<string | number | boolean>
8
- /** Key for display text when options are objects (default 'label') */
9
- labelKey?: string
10
- /** Key for the value when options are objects (default 'value') */
11
- valueKey?: string
12
- /** Placeholder text (default 'Select...') */
13
- placeholder?: string
14
- /** Currently selected value */
15
- value?: any
16
- /** Called with synthetic event; e.target.value is the selected value, e.target.name is the input name */
17
- onChange?: (e: { target: { value: any; name: string } }) => void
18
- /** Input element ID */
19
- id?: string
20
- /** Input name attribute — surfaces as e.target.name in onChange */
21
- name?: string
22
- /** Disable the input */
23
- disabled?: boolean
24
- }
25
-
26
- declare const SearchSelect: React.ForwardRefExoticComponent<
27
- SearchSelectProps & React.RefAttributes<HTMLDivElement>
28
- >
29
-
30
- export default SearchSelect
31
- export { SearchSelect }
@@ -1,155 +0,0 @@
1
- import React, { useState, useRef, useEffect } from 'react'
2
- import { cn } from '../lib/cn.js'
3
-
4
- /**
5
- * A filterable, searchable select dropdown styled with Bootstrap 5.
6
- * Supports both primitive arrays and object arrays with configurable label/value keys.
7
- *
8
- * @param {string} [className] - Additional CSS classes on the wrapper
9
- * @param {Array<string|number|boolean|object>} [options=[]] - Selectable options (primitives or objects)
10
- * @param {string} [labelKey='label'] - Key for display text when options are objects
11
- * @param {string} [valueKey='value'] - Key for the value when options are objects
12
- * @param {string} [placeholder='Select...'] - Placeholder text
13
- * @param {any} [value=null] - Currently selected value
14
- * @param {(e: { target: { value: any, name: string } }) => void} [onChange] - Called with synthetic event; e.target.value is selected value, e.target.name is input name
15
- * @param {string} [id='filterable-select'] - Input element ID
16
- * @param {string} [name] - Input name attribute — surfaces as e.target.name in onChange
17
- * @param {boolean} [disabled=false] - Disable the input
18
- */
19
- const SearchSelect = React.forwardRef(({
20
- className,
21
- options = [],
22
- labelKey = 'label',
23
- valueKey = 'value',
24
- placeholder = 'Select...',
25
- value = null,
26
- onChange = null,
27
- id = 'filterable-select',
28
- name,
29
- disabled = false,
30
- ...props
31
- }, ref) => {
32
- const [isOpen, setIsOpen] = useState(false)
33
- const [searchTerm, setSearchTerm] = useState('')
34
- const wrapperRef = useRef(null)
35
-
36
- // AUTO-DETECT: primitives vs objects
37
- const isPrimitiveArray = options.length > 0 &&
38
- (typeof options[0] === 'string' || typeof options[0] === 'number' || typeof options[0] === 'boolean')
39
-
40
- const getLabel = (option) => {
41
- if (isPrimitiveArray) return String(option)
42
- return option?.[labelKey] || ''
43
- }
44
-
45
- const getValue = (option) => {
46
- if (isPrimitiveArray) return option
47
- return option?.[valueKey] ?? null
48
- }
49
-
50
- const selectedOption = options.find(opt => getValue(opt) === value)
51
-
52
- // Sync input when value changes externally
53
- useEffect(() => {
54
- if (selectedOption !== undefined) {
55
- setSearchTerm(getLabel(selectedOption))
56
- } else {
57
- setSearchTerm('')
58
- }
59
- }, [value, options, labelKey, valueKey])
60
-
61
- // Filter options
62
- const filteredOptions = options.filter(option =>
63
- getLabel(option).toLowerCase().includes(searchTerm.toLowerCase())
64
- )
65
-
66
- // Click outside to close
67
- useEffect(() => {
68
- const handleClickOutside = (event) => {
69
- if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
70
- setIsOpen(false)
71
- }
72
- }
73
- document.addEventListener('mousedown', handleClickOutside)
74
- return () => document.removeEventListener('mousedown', handleClickOutside)
75
- }, [])
76
-
77
- const handleSelect = (option) => {
78
- const selectedValue = getValue(option)
79
- setSearchTerm(getLabel(option))
80
- setIsOpen(false)
81
- if (onChange) onChange({ target: { value: selectedValue, name: name || id } })
82
- }
83
-
84
- return (
85
- <div
86
- ref={(node) => {
87
- wrapperRef.current = node
88
- if (typeof ref === 'function') ref(node)
89
- else if (ref) ref.current = node
90
- }}
91
- // flex-fill lets the wrapper participate in Bootstrap input-group flex layout
92
- // rounded gives the wrapper a border-radius so the inner input can inherit it
93
- // correctly when the input-group adjusts border-radius on adjacent items
94
- className={cn('position-relative ', className)}
95
- style={{ minWidth: 0 }}
96
- {...props}
97
- >
98
- <input
99
- id={id}
100
- type="text"
101
- className="form-select"
102
- placeholder={placeholder}
103
- value={searchTerm}
104
- disabled={disabled}
105
- onChange={(e) => {
106
- setSearchTerm(e.target.value)
107
- setIsOpen(true)
108
- }}
109
- onFocus={() => setIsOpen(true)}
110
- style={{ cursor: 'text', borderRadius: 'inherit' }}
111
- />
112
-
113
- {isOpen && !disabled && (
114
- <ul
115
- className="dropdown-menu show w-100 overflow-x-hidden"
116
- style={{
117
- maxHeight: '200px',
118
- marginTop: '2px',
119
- zIndex: 1050,
120
- borderRadius: '0.375rem',
121
- boxShadow: '0 0.5rem 1rem rgba(0,0,0,0.15)',
122
- }}
123
- >
124
- {filteredOptions.length > 0 ? (
125
- filteredOptions.map((option, index) => {
126
- const key = getValue(option) ?? `option-${index}`
127
- return (
128
- <li key={key}>
129
- <button
130
- type="button"
131
- className="dropdown-item text-truncate"
132
- onClick={() => handleSelect(option)}
133
- >
134
- {getLabel(option)}
135
- </button>
136
- </li>
137
- )
138
- })
139
- ) : (
140
- <li>
141
- <span className="dropdown-item disabled text-muted" style={{ cursor: 'default' }}>
142
- No options found
143
- </span>
144
- </li>
145
- )}
146
- </ul>
147
- )}
148
- </div>
149
- )
150
- })
151
-
152
- SearchSelect.displayName = 'SearchSelect'
153
-
154
- export default SearchSelect
155
- export { SearchSelect }
@@ -1,13 +0,0 @@
1
- import * as React from 'react'
2
-
3
- export interface TableLoadingProps {
4
- /** Number of placeholder rows to render (default 5) */
5
- rows?: number
6
- /** Number of placeholder columns per row (default 4) */
7
- columns?: number
8
- }
9
-
10
- declare const TableLoading: React.FC<TableLoadingProps>
11
-
12
- export default TableLoading
13
- export { TableLoading }
@@ -1,43 +0,0 @@
1
- import * as React from 'react'
2
-
3
- /**
4
- * Bootstrap 5 placeholder loading rows for table `<tbody>` elements.
5
- * Renders a grid of shimmer placeholders matching the table column count.
6
- *
7
- * @param {number} [rows=5] - Number of placeholder rows to render
8
- * @param {number} [columns=4] - Number of placeholder columns per row
9
- *
10
- * @example
11
- * // Inside a table
12
- * <table className="table">
13
- * <thead><tr><th>Name</th><th>Class</th><th>Status</th></tr></thead>
14
- * <tbody>
15
- * {loading ? (
16
- * <TableLoading rows={8} columns={3} />
17
- * ) : (
18
- * data.map(row => <tr key={row.id}>...</tr>)
19
- * )}
20
- * </tbody>
21
- * </table>
22
- */
23
- const TableLoading = ({ rows = 5, columns = 4 }) => (
24
- <>
25
- {Array.from({ length: rows }, (_, r) => (
26
- <tr key={r}>
27
- {Array.from({ length: columns }, (_, c) => (
28
- <td key={c} className="placeholder-glow">
29
- <span
30
- className="placeholder rounded py-2 col-12"
31
- style={{ height: 14, display: 'block' }}
32
- />
33
- </td>
34
- ))}
35
- </tr>
36
- ))}
37
- </>
38
- )
39
-
40
- TableLoading.displayName = 'TableLoading'
41
-
42
- export { TableLoading }
43
- export default TableLoading
@@ -1,299 +0,0 @@
1
- /* ==========================================================================
2
- Custom DatePicker — Bootstrap 5 design tokens
3
- Zero dependencies. Calendar grid + time picker + year picker + datetime combo.
4
- Popover is portaled to document.body — positioning is set inline by JS.
5
- ========================================================================== */
6
-
7
- /* --- Popover container --- */
8
- .datepicker-popover {
9
- border-radius: var(--bs-border-radius, 0.375rem);
10
- box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
11
- user-select: none;
12
- -webkit-user-select: none;
13
- }
14
-
15
- .datepicker-popover--wide {
16
- min-width: 420px;
17
- }
18
-
19
- /* --- Calendar panel --- */
20
- .datepicker-calendar {
21
- min-width: 260px;
22
- }
23
-
24
- /* 7-column day-of-week header + day grid */
25
- .datepicker-days-header,
26
- .datepicker-days-grid {
27
- display: grid;
28
- grid-template-columns: repeat(7, 1fr);
29
- gap: 2px;
30
- }
31
-
32
- /* Day-of-week label */
33
- .datepicker-day-label {
34
- font-size: 0.7rem;
35
- font-weight: 600;
36
- color: var(--bs-secondary-color, #6c757d);
37
- text-transform: uppercase;
38
- text-align: center;
39
- padding: 2px 0;
40
- width: 34px;
41
- }
42
-
43
- /* Individual day cell */
44
- .datepicker-day {
45
- width: 34px;
46
- height: 34px;
47
- display: flex;
48
- align-items: center;
49
- justify-content: center;
50
- font-size: 0.8rem;
51
- font-weight: 400;
52
- color: var(--bs-body-color, #212529);
53
- background: transparent;
54
- border: none;
55
- border-radius: var(--bs-border-radius-sm, 0.25rem);
56
- cursor: pointer;
57
- transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
58
- padding: 0;
59
- margin: 0 auto;
60
- }
61
-
62
- .datepicker-day:hover:not(:disabled):not(.datepicker-day--selected) {
63
- background-color: var(--bs-primary-bg-subtle, #cfe2ff);
64
- }
65
-
66
- /* Today */
67
- .datepicker-day--today {
68
- font-weight: 700;
69
- border: 1px solid var(--bs-border-color, #dee2e6);
70
- }
71
-
72
- /* Selected (Bootstrap primary) */
73
- .datepicker-day--selected {
74
- background-color: var(--bs-primary, #0d6efd) !important;
75
- color: #fff !important;
76
- font-weight: 600;
77
- }
78
-
79
- /* Outside current month */
80
- .datepicker-day--outside {
81
- color: var(--bs-tertiary-color, #adb5bd);
82
- opacity: 0.45;
83
- pointer-events: none;
84
- }
85
-
86
- /* Disabled (outside min/max range) */
87
- .datepicker-day--disabled {
88
- color: var(--bs-tertiary-color, #adb5bd);
89
- opacity: 0.35;
90
- cursor: not-allowed;
91
- pointer-events: none;
92
- }
93
-
94
- /* --- Year picker --- */
95
- .datepicker-year-picker {
96
- min-width: 260px;
97
- }
98
-
99
- /* 4-column year grid */
100
- .datepicker-year-grid {
101
- display: grid;
102
- grid-template-columns: repeat(4, 1fr);
103
- gap: 6px;
104
- }
105
-
106
- .datepicker-year-cell {
107
- font-size: 0.85rem;
108
- padding: 6px 4px;
109
- text-align: center;
110
- }
111
-
112
- /* --- Time panel --- */
113
- .datepicker-time {
114
- min-width: 120px;
115
- }
116
-
117
- /* Three-column scrollable time picker */
118
- .datepicker-time-col {
119
- display: flex;
120
- flex-direction: column;
121
- align-items: center;
122
- flex: 0 0 auto;
123
- width: 52px;
124
- }
125
-
126
- .datepicker-time-col-label {
127
- font-size: 0.6rem;
128
- font-weight: 600;
129
- color: var(--bs-secondary-color, #6c757d);
130
- text-transform: uppercase;
131
- letter-spacing: 0.04em;
132
- margin-bottom: 2px;
133
- user-select: none;
134
- -webkit-user-select: none;
135
- }
136
-
137
- .datepicker-time-col-scroll {
138
- display: flex;
139
- flex-direction: column;
140
- align-items: center;
141
- gap: 1px;
142
- overflow-y: scroll;
143
- scrollbar-width: none; /* Firefox */
144
- -ms-overflow-style: none; /* IE/Edge */
145
- height: 220px;
146
- scroll-behavior: smooth;
147
- }
148
-
149
- .datepicker-time-col-scroll::-webkit-scrollbar {
150
- display: none; /* Chrome/Safari/Opera */
151
- }
152
-
153
- .datepicker-time-item {
154
- width: 44px;
155
- height: 30px;
156
- display: flex;
157
- align-items: center;
158
- justify-content: center;
159
- font-size: 0.82rem;
160
- font-weight: 500;
161
- color: var(--bs-body-color, #212529);
162
- background: transparent;
163
- border: none;
164
- border-radius: var(--bs-border-radius-sm, 0.25rem);
165
- cursor: pointer;
166
- transition: background-color 0.1s ease, color 0.1s ease;
167
- padding: 0;
168
- flex-shrink: 0;
169
- }
170
-
171
- .datepicker-time-item:hover {
172
- background-color: var(--bs-primary-bg-subtle, #cfe2ff);
173
- }
174
-
175
- .datepicker-time-item.active {
176
- background-color: var(--bs-primary, #0d6efd);
177
- color: #fff;
178
- font-weight: 600;
179
- }
180
-
181
- /* AM/PM items — slightly taller since only 2 */
182
- .datepicker-time-item--ampm {
183
- height: 36px;
184
- width: 46px;
185
- font-size: 0.78rem;
186
- }
187
-
188
- .datepicker-time-separator {
189
- font-size: 1.1rem;
190
- font-weight: 600;
191
- color: var(--bs-body-color, #212529);
192
- align-self: center;
193
- margin-top: 14px;
194
- flex: 0 0 auto;
195
- }
196
-
197
- /* Footer bar (Today/Now + Clear) */
198
- .datepicker-footer {
199
- border-bottom-left-radius: var(--bs-border-radius, 0.375rem);
200
- border-bottom-right-radius: var(--bs-border-radius, 0.375rem);
201
- }
202
-
203
- /* --- Dark mode --- */
204
- [data-bs-theme="dark"] .datepicker-popover {
205
- background-color: var(--bs-body-bg, #212529);
206
- border-color: var(--bs-border-color, #495057);
207
- }
208
-
209
- [data-bs-theme="dark"] .datepicker-day:hover:not(:disabled):not(.datepicker-day--selected) {
210
- background-color: var(--bs-primary-bg-subtle, #2c3e50);
211
- }
212
-
213
- [data-bs-theme="dark"] .datepicker-time-item:hover {
214
- background-color: var(--bs-primary-bg-subtle, #2c3e50);
215
- }
216
-
217
- [data-bs-theme="dark"] .datepicker-time-item.active {
218
- background-color: var(--bs-primary, #0d6efd);
219
- color: #fff;
220
- }
221
-
222
- [data-bs-theme="dark"] .datepicker-footer {
223
- border-top-color: var(--bs-border-color, #495057);
224
- }
225
-
226
- /* ==========================================================================
227
- Mobile responsive — adapts layout and sizing for small screens
228
- ========================================================================== */
229
-
230
- @media (max-width: 575.98px) {
231
- /* Popover: never wider than the viewport */
232
- .datepicker-popover {
233
- max-width: calc(100vw - 8px) !important;
234
- overflow-x: hidden;
235
- }
236
-
237
- /* Stack calendar + time vertically in datetime mode */
238
- .datepicker-popover--wide .d-flex.flex-row {
239
- flex-direction: column !important;
240
- }
241
-
242
- /* Hide vertical divider between calendar and time */
243
- .datepicker-popover--wide .vr {
244
- display: none;
245
- }
246
-
247
- /* Slightly smaller day cells to fit narrow screens */
248
- .datepicker-day {
249
- width: 28px;
250
- height: 28px;
251
- font-size: 0.72rem;
252
- }
253
-
254
- .datepicker-day-label {
255
- width: 28px;
256
- font-size: 0.62rem;
257
- }
258
-
259
- /* Reduce calendar min-width */
260
- .datepicker-calendar,
261
- .datepicker-year-picker {
262
- min-width: 210px;
263
- }
264
-
265
- /* Time columns — stack more compactly */
266
- .datepicker-time-col-scroll {
267
- height: 200px;
268
- }
269
-
270
- .datepicker-time-item {
271
- width: 38px;
272
- height: 26px;
273
- font-size: 0.75rem;
274
- }
275
-
276
- .datepicker-time-item--ampm {
277
- width: 40px;
278
- height: 32px;
279
- }
280
-
281
- .datepicker-time-separator {
282
- font-size: 1rem;
283
- margin-top: 12px;
284
- }
285
-
286
- /* Increase touch target for footer buttons */
287
- .datepicker-footer .btn {
288
- font-size: 0.8rem;
289
- padding: 6px 8px;
290
- min-height: 34px;
291
- }
292
-
293
- /* Year grid cells — slightly roomier for tap */
294
- .datepicker-year-cell {
295
- font-size: 0.8rem;
296
- padding: 8px 4px;
297
- min-height: 34px;
298
- }
299
- }
package/src/index.js DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * react-bootstrap-plugins — Production-grade Bootstrap 5 UI components for React
3
- *
4
- * @example
5
- * // Tree-shakeable: import only what you need
6
- * import { DatePicker, Label } from 'react-bootstrap-plugins'
7
- *
8
- * // Or individual entry points for maximum tree-shaking
9
- * import DatePicker from 'react-bootstrap-plugins/DatePicker'
10
- * import SearchSelect from 'react-bootstrap-plugins/SearchSelect'
11
- */
12
-
13
- export { DatePicker } from './components/DatePicker.jsx'
14
- export { SearchSelect } from './components/SearchSelect.jsx'
15
- export { Label } from './components/Label.jsx'
16
- export { TableLoading } from './components/TableLoading.jsx'
package/src/lib/cn.js DELETED
@@ -1,35 +0,0 @@
1
- /**
2
- * Utility for conditionally joining CSS class names together.
3
- * Filters out falsy values and joins with space.
4
- *
5
- * @param {...any} args - Class name strings, objects, or arrays
6
- * @returns {string} Joined class string
7
- *
8
- * @example
9
- * cn('btn', isActive && 'btn-primary', 'px-3')
10
- * // => 'btn btn-primary px-3'
11
- *
12
- * @example
13
- * cn('base-class', { 'active': isActive, 'disabled': isDisabled })
14
- * // => 'base-class active' (when isActive=true, isDisabled=false)
15
- */
16
- export function cn(...args) {
17
- const classes = []
18
-
19
- for (const arg of args) {
20
- if (!arg) continue
21
-
22
- if (typeof arg === 'string') {
23
- classes.push(arg)
24
- } else if (Array.isArray(arg)) {
25
- const nested = cn(...arg)
26
- if (nested) classes.push(nested)
27
- } else if (typeof arg === 'object') {
28
- for (const [key, value] of Object.entries(arg)) {
29
- if (value) classes.push(key)
30
- }
31
- }
32
- }
33
-
34
- return classes.join(' ')
35
- }