@abstraks-dev/ui-library 1.1.24 → 1.1.28
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/dist/__tests__/AccountBox.test.js +61 -0
- package/dist/__tests__/AccountCircle.test.js +69 -0
- package/dist/__tests__/Alert.test.js +144 -0
- package/dist/__tests__/ArrowIcon.test.js +61 -0
- package/dist/__tests__/ArrowRight.test.js +12 -7
- package/dist/__tests__/BookOpen.test.js +61 -0
- package/dist/__tests__/Camera.test.js +69 -0
- package/dist/__tests__/CaretDown.test.js +69 -0
- package/dist/__tests__/ChevronDown.test.js +13 -8
- package/dist/__tests__/Comment.test.js +69 -0
- package/dist/__tests__/Ellipses.test.js +61 -0
- package/dist/__tests__/Explore.test.js +61 -0
- package/dist/__tests__/FileInput.test.js +148 -0
- package/dist/__tests__/Filter.test.js +69 -0
- package/dist/__tests__/Form.test.js +471 -0
- package/dist/__tests__/Group.test.js +61 -0
- package/dist/__tests__/GroupReview.test.js +61 -0
- package/dist/__tests__/Hamburger.test.js +69 -0
- package/dist/__tests__/Header.test.js +198 -0
- package/dist/__tests__/Heart.test.js +69 -0
- package/dist/__tests__/Home.test.js +69 -0
- package/dist/__tests__/LoadingSpinner.test.js +78 -0
- package/dist/__tests__/LogOut.test.js +69 -0
- package/dist/__tests__/Magnify.test.js +69 -0
- package/dist/__tests__/News.test.js +61 -0
- package/dist/__tests__/Review.test.js +61 -0
- package/dist/__tests__/SaveIcon.test.js +61 -0
- package/dist/__tests__/Search.test.js +101 -0
- package/dist/__tests__/utils/accessibility.test.js +361 -0
- package/dist/__tests__/utils/inputValidation-core.test.js +80 -0
- package/dist/__tests__/utils/validation-core.test.js +123 -0
- package/dist/__tests__/utils/validation.test.js +362 -0
- package/dist/components/Alert.js +104 -0
- package/dist/components/FileInput.js +96 -0
- package/dist/components/Form.js +87 -39
- package/dist/components/Header.js +29 -1
- package/dist/components/Radio.js +1 -3
- package/dist/components/Search.js +236 -0
- package/dist/icons/AccountBox.js +33 -0
- package/dist/icons/AccountCircle.js +33 -0
- package/dist/icons/ArrowIcon.js +3 -2
- package/dist/icons/ArrowRight.js +23 -12
- package/dist/icons/BookOpen.js +33 -0
- package/dist/icons/Camera.js +33 -0
- package/dist/icons/CaretDown.js +33 -0
- package/dist/icons/ChevronDown.js +19 -9
- package/dist/icons/Comment.js +33 -0
- package/dist/icons/Explore.js +33 -0
- package/dist/icons/Filter.js +33 -0
- package/dist/icons/Group.js +33 -0
- package/dist/icons/GroupReview.js +33 -0
- package/dist/icons/Hamburger.js +14 -20
- package/dist/icons/Heart.js +33 -0
- package/dist/icons/Home.js +33 -0
- package/dist/icons/LoadingSpinner.js +3 -2
- package/dist/icons/LogOut.js +33 -0
- package/dist/icons/Magnify.js +33 -0
- package/dist/icons/News.js +33 -0
- package/dist/icons/Review.js +35 -0
- package/dist/icons/SaveIcon.js +3 -2
- package/dist/icons/index.js +112 -0
- package/dist/index.js +32 -0
- package/dist/styles/_variables.scss +2 -0
- package/dist/styles/alert.css +218 -0
- package/dist/styles/alert.css.map +1 -0
- package/dist/styles/alert.scss +128 -0
- package/dist/styles/anchor.css.map +1 -1
- package/dist/styles/avatar.css.map +1 -1
- package/dist/styles/button.css.map +1 -1
- package/dist/styles/card.css.map +1 -1
- package/dist/styles/checkbox.css.map +1 -1
- package/dist/styles/crud.css.map +1 -1
- package/dist/styles/dragAndDrop.css.map +1 -1
- package/dist/styles/error.css.map +1 -1
- package/dist/styles/file-input.css +165 -0
- package/dist/styles/file-input.css.map +1 -0
- package/dist/styles/file-input.scss +69 -0
- package/dist/styles/footer.css.map +1 -1
- package/dist/styles/form.css.map +1 -1
- package/dist/styles/header.css +9 -0
- package/dist/styles/header.css.map +1 -1
- package/dist/styles/header.scss +16 -7
- package/dist/styles/heading.css.map +1 -1
- package/dist/styles/hero.css.map +1 -1
- package/dist/styles/htmlElements.css.map +1 -1
- package/dist/styles/label.css.map +1 -1
- package/dist/styles/loader.css.map +1 -1
- package/dist/styles/main.css +320 -0
- package/dist/styles/main.css.map +1 -1
- package/dist/styles/menu-hover.css.map +1 -1
- package/dist/styles/paragraph.css.map +1 -1
- package/dist/styles/prompt.css.map +1 -1
- package/dist/styles/radio.css.map +1 -1
- package/dist/styles/search.css +269 -0
- package/dist/styles/search.css.map +1 -0
- package/dist/styles/search.scss +215 -0
- package/dist/styles/select.css.map +1 -1
- package/dist/styles/side-menu.css.map +1 -1
- package/dist/styles/tabs.css.map +1 -1
- package/dist/styles/text-area.css.map +1 -1
- package/dist/styles/text-input.css.map +1 -1
- package/dist/utils/utils/validation.js +2 -2
- package/dist/utils/validation.js +2 -2
- package/package.json +2 -2
- package/dist/icons/__tests__/CheckCircle.test.js +0 -9
- package/dist/icons/__tests__/ChevronDown.test.js +0 -9
- package/dist/icons/__tests__/Close.test.js +0 -9
- package/dist/icons/__tests__/EditSquare.test.js +0 -9
- package/dist/icons/__tests__/PlusCircle.test.js +0 -9
- package/dist/icons/__tests__/TrashX.test.js +0 -9
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.FileInput = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _propTypes = require("prop-types");
|
|
9
|
+
var _ssrSafeId = require("../utils/ssrSafeId");
|
|
10
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
11
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
12
|
+
/**
|
|
13
|
+
* FileInput - A stateless, accessible file input component
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Multiple file types support via accept prop
|
|
17
|
+
* - Custom label content (text, images, or components)
|
|
18
|
+
* - Accessible with proper ARIA labels
|
|
19
|
+
* - Multiple file selection support
|
|
20
|
+
* - Drag and drop styling ready
|
|
21
|
+
* - Hidden native input with custom styling
|
|
22
|
+
*
|
|
23
|
+
* @component
|
|
24
|
+
* @example
|
|
25
|
+
* <FileInput
|
|
26
|
+
* accept="image/*"
|
|
27
|
+
* onChange={(event) => handleFileChange(event)}
|
|
28
|
+
* label="📷 Upload Image"
|
|
29
|
+
* multiple={false}
|
|
30
|
+
* />
|
|
31
|
+
*/
|
|
32
|
+
const FileInput = exports.FileInput = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
33
|
+
// Core props
|
|
34
|
+
id,
|
|
35
|
+
className = '',
|
|
36
|
+
// Functionality props
|
|
37
|
+
accept = '*/*',
|
|
38
|
+
multiple = false,
|
|
39
|
+
onChange,
|
|
40
|
+
disabled = false,
|
|
41
|
+
// Content props
|
|
42
|
+
label = 'Choose File',
|
|
43
|
+
// Accessibility props
|
|
44
|
+
ariaLabel,
|
|
45
|
+
ariaDescribedBy,
|
|
46
|
+
// Additional props
|
|
47
|
+
...rest
|
|
48
|
+
}, ref) => {
|
|
49
|
+
const stableId = (0, _ssrSafeId.useStableId)(id);
|
|
50
|
+
const inputRef = (0, _react.useRef)(null);
|
|
51
|
+
|
|
52
|
+
// Handle click on label to trigger file input
|
|
53
|
+
const handleLabelClick = () => {
|
|
54
|
+
if (!disabled && inputRef.current) {
|
|
55
|
+
inputRef.current.click();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const combinedClassName = ['ui-file-input', disabled && 'ui-file-input--disabled', className].filter(Boolean).join(' ');
|
|
59
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
60
|
+
className: combinedClassName
|
|
61
|
+
}, /*#__PURE__*/_react.default.createElement("label", {
|
|
62
|
+
htmlFor: stableId,
|
|
63
|
+
className: "ui-file-input__label",
|
|
64
|
+
onClick: handleLabelClick,
|
|
65
|
+
"aria-label": ariaLabel,
|
|
66
|
+
"aria-describedby": ariaDescribedBy
|
|
67
|
+
}, label), /*#__PURE__*/_react.default.createElement("input", _extends({
|
|
68
|
+
ref: ref || inputRef,
|
|
69
|
+
id: stableId,
|
|
70
|
+
type: "file",
|
|
71
|
+
accept: accept,
|
|
72
|
+
multiple: multiple,
|
|
73
|
+
onChange: onChange,
|
|
74
|
+
disabled: disabled,
|
|
75
|
+
className: "ui-file-input__input",
|
|
76
|
+
"aria-label": ariaLabel || 'File input',
|
|
77
|
+
"aria-describedby": ariaDescribedBy
|
|
78
|
+
}, rest)));
|
|
79
|
+
});
|
|
80
|
+
FileInput.displayName = 'FileInput';
|
|
81
|
+
FileInput.propTypes = {
|
|
82
|
+
// Core props
|
|
83
|
+
id: _propTypes.string,
|
|
84
|
+
className: _propTypes.string,
|
|
85
|
+
// Functionality props
|
|
86
|
+
accept: _propTypes.string,
|
|
87
|
+
multiple: _propTypes.bool,
|
|
88
|
+
onChange: _propTypes.func,
|
|
89
|
+
disabled: _propTypes.bool,
|
|
90
|
+
// Content props
|
|
91
|
+
label: _propTypes.node,
|
|
92
|
+
// Accessibility props
|
|
93
|
+
ariaLabel: _propTypes.string,
|
|
94
|
+
ariaDescribedBy: _propTypes.string
|
|
95
|
+
};
|
|
96
|
+
var _default = exports.default = FileInput;
|
package/dist/components/Form.js
CHANGED
|
@@ -141,6 +141,28 @@ const Form = exports.Form = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
141
141
|
}
|
|
142
142
|
}, [validationMode, validateField, announceErrors]);
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Extract all field names from form children
|
|
146
|
+
* @returns {Array} Array of field names
|
|
147
|
+
*/
|
|
148
|
+
const getAllFieldNames = (0, _react.useCallback)(() => {
|
|
149
|
+
const fieldNames = [];
|
|
150
|
+
const extractFieldNames = childrenToExtract => {
|
|
151
|
+
_react.Children.forEach(childrenToExtract, child => {
|
|
152
|
+
if (! /*#__PURE__*/(0, _react.isValidElement)(child)) return;
|
|
153
|
+
const fieldName = child.props?.name || child.props?.setName;
|
|
154
|
+
if (fieldName && !fieldNames.includes(fieldName)) {
|
|
155
|
+
fieldNames.push(fieldName);
|
|
156
|
+
}
|
|
157
|
+
if (child.props?.children) {
|
|
158
|
+
extractFieldNames(child.props.children);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
extractFieldNames(children);
|
|
163
|
+
return fieldNames;
|
|
164
|
+
}, [children]);
|
|
165
|
+
|
|
144
166
|
/**
|
|
145
167
|
* Validates all form fields
|
|
146
168
|
* @returns {Object} Object containing all field errors
|
|
@@ -148,14 +170,16 @@ const Form = exports.Form = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
148
170
|
const validateAllFields = (0, _react.useCallback)(() => {
|
|
149
171
|
if (!onValidate) return {};
|
|
150
172
|
const newErrors = {};
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
const allFieldNames = getAllFieldNames();
|
|
174
|
+
allFieldNames.forEach(fieldName => {
|
|
175
|
+
const value = formData[fieldName];
|
|
176
|
+
const error = validateField(fieldName, value);
|
|
153
177
|
if (error) {
|
|
154
178
|
newErrors[fieldName] = error;
|
|
155
179
|
}
|
|
156
180
|
});
|
|
157
181
|
return newErrors;
|
|
158
|
-
}, [formData, validateField, onValidate]);
|
|
182
|
+
}, [getAllFieldNames, formData, validateField, onValidate]);
|
|
159
183
|
|
|
160
184
|
/**
|
|
161
185
|
* Handles form submission
|
|
@@ -219,46 +243,70 @@ const Form = exports.Form = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
219
243
|
// Generate comprehensive class names
|
|
220
244
|
const classNames = [componentName, additionalClassName, disabled && `${componentName}--disabled`, isSubmitting && `${componentName}--submitting`, hasErrors && `${componentName}--has-errors`].filter(Boolean).join(' ');
|
|
221
245
|
|
|
222
|
-
//
|
|
223
|
-
const
|
|
224
|
-
if (/*#__PURE__*/_react.
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
'
|
|
255
|
-
|
|
256
|
-
|
|
246
|
+
// Recursively enhance children with form context
|
|
247
|
+
const enhanceChildren = childrenToEnhance => _react.Children.map(childrenToEnhance, child => {
|
|
248
|
+
if (! /*#__PURE__*/(0, _react.isValidElement)(child)) return child;
|
|
249
|
+
const fieldName = child.props?.name || child.props?.setName;
|
|
250
|
+
let enhancedChild = child;
|
|
251
|
+
if (fieldName) {
|
|
252
|
+
const childType = child.type?.displayName || child.type?.name;
|
|
253
|
+
const isCheckbox = childType === 'Checkbox' || child.props?.type === 'checkbox';
|
|
254
|
+
const isRadio = childType === 'Radio' || child.props?.type === 'radio';
|
|
255
|
+
const commonProps = {
|
|
256
|
+
error: allErrors[fieldName],
|
|
257
|
+
errorText: allErrors[fieldName],
|
|
258
|
+
onChangeFunc: event => {
|
|
259
|
+
const target = event.target;
|
|
260
|
+
const value = target?.type === 'checkbox' ? target.checked : target?.value !== undefined ? target.value : event;
|
|
261
|
+
updateFormData(fieldName, value);
|
|
262
|
+
child.props?.onChangeFunc?.(event);
|
|
263
|
+
},
|
|
264
|
+
onChange: event => {
|
|
265
|
+
const target = event.target;
|
|
266
|
+
const value = target?.type === 'checkbox' ? target.checked : target?.value !== undefined ? target.value : event;
|
|
267
|
+
updateFormData(fieldName, value);
|
|
268
|
+
child.props?.onChange?.(event);
|
|
269
|
+
},
|
|
270
|
+
onBlur: event => {
|
|
271
|
+
const target = event.target;
|
|
272
|
+
const value = target?.type === 'checkbox' ? target.checked : target?.value !== undefined ? target.value : formData[fieldName];
|
|
273
|
+
handleFieldBlur(fieldName, value);
|
|
274
|
+
child.props?.onBlur?.(event);
|
|
275
|
+
},
|
|
276
|
+
blur: event => {
|
|
277
|
+
const target = event.target;
|
|
278
|
+
const value = target?.type === 'checkbox' ? target.checked : target?.value !== undefined ? target.value : formData[fieldName];
|
|
279
|
+
handleFieldBlur(fieldName, value);
|
|
280
|
+
child.props?.blur?.(event);
|
|
281
|
+
},
|
|
282
|
+
disabled: disabled || child.props?.disabled,
|
|
283
|
+
'aria-invalid': !!allErrors[fieldName],
|
|
284
|
+
'aria-describedby': allErrors[fieldName] ? `${fieldName}-error` : child.props?.['aria-describedby']
|
|
285
|
+
};
|
|
286
|
+
if (isRadio) {
|
|
287
|
+
const childValue = child.props.value ?? child.props.inputValue;
|
|
288
|
+
commonProps.value = childValue;
|
|
289
|
+
commonProps.inputValue = childValue;
|
|
290
|
+
commonProps.checked = formData[fieldName] !== undefined ? formData[fieldName] === childValue : child.props.checked;
|
|
291
|
+
} else if (isCheckbox) {
|
|
292
|
+
commonProps.checked = formData[fieldName] !== undefined ? formData[fieldName] : child.props.checked ?? false;
|
|
293
|
+
} else {
|
|
294
|
+
commonProps.value = formData[fieldName] ?? child.props.value ?? '';
|
|
295
|
+
commonProps.inputValue = formData[fieldName] ?? child.props.inputValue ?? '';
|
|
296
|
+
}
|
|
297
|
+
enhancedChild = /*#__PURE__*/(0, _react.cloneElement)(child, commonProps);
|
|
298
|
+
}
|
|
299
|
+
if (child.props?.children) {
|
|
300
|
+
const nestedChildren = enhanceChildren(child.props.children);
|
|
301
|
+
if (nestedChildren !== child.props.children) {
|
|
302
|
+
enhancedChild = /*#__PURE__*/(0, _react.cloneElement)(enhancedChild, {
|
|
303
|
+
children: nestedChildren
|
|
257
304
|
});
|
|
258
305
|
}
|
|
259
306
|
}
|
|
260
|
-
return
|
|
307
|
+
return enhancedChild;
|
|
261
308
|
});
|
|
309
|
+
const enhancedChildren = enhanceChildren(children);
|
|
262
310
|
return /*#__PURE__*/_react.default.createElement("form", _extends({
|
|
263
311
|
ref: ref,
|
|
264
312
|
className: classNames,
|
|
@@ -65,6 +65,9 @@ var _accessibility = require("../utils/accessibility");
|
|
|
65
65
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
66
66
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } // components
|
|
67
67
|
// utils
|
|
68
|
+
// Constants
|
|
69
|
+
const SCROLL_THRESHOLD = 100; // Pixels to scroll before hiding header
|
|
70
|
+
|
|
68
71
|
/**
|
|
69
72
|
* Header Component
|
|
70
73
|
*
|
|
@@ -121,6 +124,30 @@ const Header = exports.Header = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
121
124
|
const finalClassName = className || additionalClassName;
|
|
122
125
|
const size = (0, _useWindowSize.useWindowSize)();
|
|
123
126
|
const isMobile = size.width < 768;
|
|
127
|
+
const [isHidden, setIsHidden] = (0, _react.useState)(false);
|
|
128
|
+
const lastScrollY = (0, _react.useRef)(0);
|
|
129
|
+
|
|
130
|
+
// Memoized scroll handler to prevent recreating on every render
|
|
131
|
+
const onScroll = (0, _react.useCallback)(() => {
|
|
132
|
+
const currentScrollY = window.scrollY;
|
|
133
|
+
if (currentScrollY > lastScrollY.current && currentScrollY > SCROLL_THRESHOLD) {
|
|
134
|
+
setIsHidden(true);
|
|
135
|
+
} else if (currentScrollY < lastScrollY.current || currentScrollY <= SCROLL_THRESHOLD) {
|
|
136
|
+
setIsHidden(false);
|
|
137
|
+
}
|
|
138
|
+
lastScrollY.current = currentScrollY;
|
|
139
|
+
}, []);
|
|
140
|
+
(0, _react.useEffect)(() => {
|
|
141
|
+
if (!isMobile) {
|
|
142
|
+
setIsHidden(false);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Initialize lastScrollY with current scroll position
|
|
147
|
+
lastScrollY.current = window.scrollY;
|
|
148
|
+
window.addEventListener('scroll', onScroll);
|
|
149
|
+
return () => window.removeEventListener('scroll', onScroll);
|
|
150
|
+
}, [isMobile, onScroll]);
|
|
124
151
|
|
|
125
152
|
// Handle keyboard navigation
|
|
126
153
|
const handleKeyDown = event => {
|
|
@@ -170,10 +197,11 @@ const Header = exports.Header = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
170
197
|
const handleEllipsesToggle = () => {
|
|
171
198
|
if (onEllipsesToggle) onEllipsesToggle(!isEllipsesOpen);
|
|
172
199
|
};
|
|
200
|
+
const headerClassName = `${componentName} ${finalClassName} ${isMobile && isHidden ? `${componentName}--hidden` : ''}`;
|
|
173
201
|
return /*#__PURE__*/_react.default.createElement("header", _extends({
|
|
174
202
|
ref: ref,
|
|
175
203
|
id: finalId,
|
|
176
|
-
className:
|
|
204
|
+
className: headerClassName,
|
|
177
205
|
"data-testid": componentName,
|
|
178
206
|
role: "banner",
|
|
179
207
|
"aria-label": ariaLabel,
|
package/dist/components/Radio.js
CHANGED
|
@@ -135,9 +135,7 @@ const Radio = exports.Radio = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
135
135
|
"aria-required": required || undefined
|
|
136
136
|
}, restProps)), /*#__PURE__*/_react.default.createElement("span", {
|
|
137
137
|
className: "custom-radio"
|
|
138
|
-
}),
|
|
139
|
-
className: `${componentName}__label-text`
|
|
140
|
-
}, finalLabel)), error && errorText && /*#__PURE__*/_react.default.createElement(_Error.Error, {
|
|
138
|
+
})), error && errorText && /*#__PURE__*/_react.default.createElement(_Error.Error, {
|
|
141
139
|
id: errorId,
|
|
142
140
|
className: `${componentName}__error`,
|
|
143
141
|
role: "alert",
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.Search = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _propTypes = require("prop-types");
|
|
9
|
+
var _TextInput = require("./TextInput");
|
|
10
|
+
var _Button = require("./Button");
|
|
11
|
+
var _icons = require("../icons");
|
|
12
|
+
var _ssrSafeId = require("../utils/ssrSafeId");
|
|
13
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
14
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } // components
|
|
15
|
+
/**
|
|
16
|
+
* Search Component
|
|
17
|
+
*
|
|
18
|
+
* A flexible search component that can filter various types of data with real-time updates.
|
|
19
|
+
* Supports filtering by multiple fields and customizable result rendering.
|
|
20
|
+
*
|
|
21
|
+
* This is a stateless component - state management should be handled externally.
|
|
22
|
+
*
|
|
23
|
+
* @component
|
|
24
|
+
* @example
|
|
25
|
+
* <Search
|
|
26
|
+
* placeholder="Search users..."
|
|
27
|
+
* searchValue={searchValue}
|
|
28
|
+
* onSearchChange={handleSearchChange}
|
|
29
|
+
* data={users}
|
|
30
|
+
* searchFields={['name', 'email']}
|
|
31
|
+
* renderResult={({ item, highlightMatch }) => (
|
|
32
|
+
* <div className="search-result-item">
|
|
33
|
+
* <h4>{highlightMatch(item.name)}</h4>
|
|
34
|
+
* <p>{item.email}</p>
|
|
35
|
+
* </div>
|
|
36
|
+
* )}
|
|
37
|
+
* />
|
|
38
|
+
*/
|
|
39
|
+
const Search = exports.Search = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
40
|
+
// Core props
|
|
41
|
+
id,
|
|
42
|
+
className = '',
|
|
43
|
+
placeholder = 'Search...',
|
|
44
|
+
searchValue = '',
|
|
45
|
+
onSearchChange,
|
|
46
|
+
// Data props
|
|
47
|
+
data = [],
|
|
48
|
+
searchFields = [],
|
|
49
|
+
filterFunction,
|
|
50
|
+
// Rendering props
|
|
51
|
+
renderResult,
|
|
52
|
+
renderEmptyState,
|
|
53
|
+
renderNoResults,
|
|
54
|
+
// Appearance props
|
|
55
|
+
variant = 'default',
|
|
56
|
+
size = 'medium',
|
|
57
|
+
disabled = false,
|
|
58
|
+
hideResultsWhenEmpty = false,
|
|
59
|
+
maxResults,
|
|
60
|
+
// Loading state
|
|
61
|
+
isLoading = false,
|
|
62
|
+
loadingText = 'Searching...',
|
|
63
|
+
// Result container props
|
|
64
|
+
resultContainerClassName = '',
|
|
65
|
+
resultItemClassName = '',
|
|
66
|
+
// Advanced props
|
|
67
|
+
caseSensitive = false,
|
|
68
|
+
highlightMatches = true,
|
|
69
|
+
// Icon and button props
|
|
70
|
+
showIcon = true,
|
|
71
|
+
iconSize = 20,
|
|
72
|
+
iconColor = '#6c757d',
|
|
73
|
+
showButton = false,
|
|
74
|
+
buttonText = 'Search',
|
|
75
|
+
buttonVariant = 'primary',
|
|
76
|
+
onButtonClick,
|
|
77
|
+
...rest
|
|
78
|
+
}, ref) => {
|
|
79
|
+
const stableId = (0, _ssrSafeId.useStableId)(id);
|
|
80
|
+
|
|
81
|
+
// Filter data based on search value
|
|
82
|
+
const getFilteredData = () => {
|
|
83
|
+
if (!searchValue.trim()) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
if (filterFunction) {
|
|
87
|
+
return filterFunction(data, searchValue);
|
|
88
|
+
}
|
|
89
|
+
if (!searchFields.length) {
|
|
90
|
+
return data;
|
|
91
|
+
}
|
|
92
|
+
const searchTerm = caseSensitive ? searchValue : searchValue.toLowerCase();
|
|
93
|
+
const filtered = data.filter(item => {
|
|
94
|
+
return searchFields.some(field => {
|
|
95
|
+
const fieldValue = getNestedValue(item, field);
|
|
96
|
+
if (fieldValue == null) return false;
|
|
97
|
+
const stringValue = String(fieldValue);
|
|
98
|
+
const compareValue = caseSensitive ? stringValue : stringValue.toLowerCase();
|
|
99
|
+
return compareValue.includes(searchTerm);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
return maxResults ? filtered.slice(0, maxResults) : filtered;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Helper function to get nested object values
|
|
106
|
+
const getNestedValue = (obj, path) => {
|
|
107
|
+
return path.split('.').reduce((current, key) => current?.[key], obj);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Highlight matching text
|
|
111
|
+
const highlightMatch = (text, field = null) => {
|
|
112
|
+
if (!highlightMatches || !searchValue.trim() || !text) {
|
|
113
|
+
return text;
|
|
114
|
+
}
|
|
115
|
+
const textStr = String(text);
|
|
116
|
+
const searchTerm = caseSensitive ? searchValue : searchValue.toLowerCase();
|
|
117
|
+
const compareText = caseSensitive ? textStr : textStr.toLowerCase();
|
|
118
|
+
if (!compareText.includes(searchTerm)) {
|
|
119
|
+
return textStr;
|
|
120
|
+
}
|
|
121
|
+
const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, caseSensitive ? 'g' : 'gi');
|
|
122
|
+
const parts = textStr.split(regex);
|
|
123
|
+
return parts.map((part, index) => {
|
|
124
|
+
const isMatch = caseSensitive ? part === searchTerm : part.toLowerCase() === searchTerm.toLowerCase();
|
|
125
|
+
return isMatch ? /*#__PURE__*/_react.default.createElement("mark", {
|
|
126
|
+
key: index,
|
|
127
|
+
className: "search-highlight"
|
|
128
|
+
}, part) : part;
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const filteredData = getFilteredData();
|
|
132
|
+
const hasResults = filteredData.length > 0;
|
|
133
|
+
const showResults = searchValue.trim().length > 0;
|
|
134
|
+
|
|
135
|
+
// Default render functions
|
|
136
|
+
const defaultRenderResult = ({
|
|
137
|
+
item,
|
|
138
|
+
index
|
|
139
|
+
}) => /*#__PURE__*/_react.default.createElement("div", {
|
|
140
|
+
key: index,
|
|
141
|
+
className: `search-result-item ${resultItemClassName}`.trim()
|
|
142
|
+
}, typeof item === 'string' ? item : JSON.stringify(item));
|
|
143
|
+
const defaultRenderEmptyState = () => /*#__PURE__*/_react.default.createElement("div", {
|
|
144
|
+
className: "search-empty-state"
|
|
145
|
+
}, /*#__PURE__*/_react.default.createElement("p", null, "Start typing to search..."));
|
|
146
|
+
const defaultRenderNoResults = () => /*#__PURE__*/_react.default.createElement("div", {
|
|
147
|
+
className: "search-no-results"
|
|
148
|
+
}, /*#__PURE__*/_react.default.createElement("p", null, "No results found for \"", searchValue, "\""));
|
|
149
|
+
|
|
150
|
+
// Component classes
|
|
151
|
+
const searchClasses = ['search-component', `search-component--${variant}`, `search-component--${size}`, disabled && 'search-component--disabled', className].filter(Boolean).join(' ');
|
|
152
|
+
const resultsClasses = ['search-results', `search-results--${variant}`, resultContainerClassName].filter(Boolean).join(' ');
|
|
153
|
+
return /*#__PURE__*/_react.default.createElement("div", _extends({
|
|
154
|
+
className: searchClasses
|
|
155
|
+
}, rest), /*#__PURE__*/_react.default.createElement("div", {
|
|
156
|
+
className: "search-input-container"
|
|
157
|
+
}, showIcon && /*#__PURE__*/_react.default.createElement("div", {
|
|
158
|
+
className: "search-icon"
|
|
159
|
+
}, /*#__PURE__*/_react.default.createElement(_icons.Magnify, {
|
|
160
|
+
dimensions: iconSize,
|
|
161
|
+
fill: iconColor,
|
|
162
|
+
additionalClassName: "search-magnify-icon"
|
|
163
|
+
})), /*#__PURE__*/_react.default.createElement(_TextInput.TextInput, {
|
|
164
|
+
ref: ref,
|
|
165
|
+
id: stableId,
|
|
166
|
+
type: "text",
|
|
167
|
+
placeholder: placeholder,
|
|
168
|
+
value: searchValue,
|
|
169
|
+
onChange: onSearchChange,
|
|
170
|
+
disabled: disabled,
|
|
171
|
+
size: size,
|
|
172
|
+
className: `search-input ${showIcon ? 'search-input--with-icon' : ''}`
|
|
173
|
+
}), showButton && /*#__PURE__*/_react.default.createElement(_Button.Button, {
|
|
174
|
+
variant: buttonVariant,
|
|
175
|
+
size: size,
|
|
176
|
+
onClick: onButtonClick,
|
|
177
|
+
disabled: disabled,
|
|
178
|
+
className: "search-button"
|
|
179
|
+
}, buttonText)), showResults && /*#__PURE__*/_react.default.createElement("div", {
|
|
180
|
+
className: resultsClasses
|
|
181
|
+
}, isLoading ? /*#__PURE__*/_react.default.createElement("div", {
|
|
182
|
+
className: "search-loading"
|
|
183
|
+
}, /*#__PURE__*/_react.default.createElement("p", null, loadingText)) : hasResults ? /*#__PURE__*/_react.default.createElement("div", {
|
|
184
|
+
className: "search-results-list"
|
|
185
|
+
}, filteredData.map((item, index) => {
|
|
186
|
+
const ResultComponent = renderResult || defaultRenderResult;
|
|
187
|
+
return /*#__PURE__*/_react.default.createElement(ResultComponent, {
|
|
188
|
+
key: item.id || item._id || index,
|
|
189
|
+
item: item,
|
|
190
|
+
index: index,
|
|
191
|
+
highlightMatch: highlightMatch,
|
|
192
|
+
searchValue: searchValue
|
|
193
|
+
});
|
|
194
|
+
})) : searchValue.trim() ? renderNoResults ? renderNoResults() : defaultRenderNoResults() : renderEmptyState ? renderEmptyState() : defaultRenderEmptyState()));
|
|
195
|
+
});
|
|
196
|
+
Search.displayName = 'Search';
|
|
197
|
+
Search.propTypes = {
|
|
198
|
+
// Core props
|
|
199
|
+
id: _propTypes.string,
|
|
200
|
+
className: _propTypes.string,
|
|
201
|
+
placeholder: _propTypes.string,
|
|
202
|
+
searchValue: _propTypes.string,
|
|
203
|
+
onSearchChange: _propTypes.func,
|
|
204
|
+
// Data props
|
|
205
|
+
data: _propTypes.array,
|
|
206
|
+
searchFields: _propTypes.array,
|
|
207
|
+
filterFunction: _propTypes.func,
|
|
208
|
+
// Rendering props
|
|
209
|
+
renderResult: _propTypes.func,
|
|
210
|
+
renderEmptyState: _propTypes.func,
|
|
211
|
+
renderNoResults: _propTypes.func,
|
|
212
|
+
// Appearance props
|
|
213
|
+
variant: (0, _propTypes.oneOf)(['default', 'bordered', 'minimal']),
|
|
214
|
+
size: (0, _propTypes.oneOf)(['small', 'medium', 'large']),
|
|
215
|
+
disabled: _propTypes.bool,
|
|
216
|
+
hideResultsWhenEmpty: _propTypes.bool,
|
|
217
|
+
maxResults: _propTypes.number,
|
|
218
|
+
// Loading state
|
|
219
|
+
isLoading: _propTypes.bool,
|
|
220
|
+
loadingText: _propTypes.string,
|
|
221
|
+
// Result container props
|
|
222
|
+
resultContainerClassName: _propTypes.string,
|
|
223
|
+
resultItemClassName: _propTypes.string,
|
|
224
|
+
// Advanced props
|
|
225
|
+
caseSensitive: _propTypes.bool,
|
|
226
|
+
highlightMatches: _propTypes.bool,
|
|
227
|
+
// Icon and button props
|
|
228
|
+
showIcon: _propTypes.bool,
|
|
229
|
+
iconSize: _propTypes.number,
|
|
230
|
+
iconColor: _propTypes.string,
|
|
231
|
+
showButton: _propTypes.bool,
|
|
232
|
+
buttonText: _propTypes.string,
|
|
233
|
+
buttonVariant: (0, _propTypes.oneOf)(['primary', 'secondary', 'success', 'error', 'warning']),
|
|
234
|
+
onButtonClick: _propTypes.func
|
|
235
|
+
};
|
|
236
|
+
var _default = exports.default = Search;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.AccountBox = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _propTypes = require("prop-types");
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const AccountBox = ({
|
|
11
|
+
componentName = 'account-box',
|
|
12
|
+
additionalClassName = '',
|
|
13
|
+
dimensions = 24,
|
|
14
|
+
viewBox = '0 -960 960 960',
|
|
15
|
+
fill = '#adb5bd'
|
|
16
|
+
}) => /*#__PURE__*/_react.default.createElement("svg", {
|
|
17
|
+
className: `icon ${componentName} ${additionalClassName}`,
|
|
18
|
+
width: dimensions,
|
|
19
|
+
height: dimensions,
|
|
20
|
+
viewBox: viewBox,
|
|
21
|
+
fill: fill
|
|
22
|
+
}, /*#__PURE__*/_react.default.createElement("path", {
|
|
23
|
+
d: "M200-246q54-53 125.5-83.5T480-360q83 0 154.5 30.5T760-246v-514H200v514Zm280-194q58 0 99-41t41-99q0-58-41-99t-99-41q-58 0-99 41t-41 99q0 58 41 99t99 41ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm69-80h422q-44-39-99.5-59.5T480-280q-56 0-112.5 20.5T269-200Zm211-320q-25 0-42.5-17.5T420-580q0-25 17.5-42.5T480-640q25 0 42.5 17.5T540-580q0 25-17.5 42.5T480-520Zm0 17Z"
|
|
24
|
+
}));
|
|
25
|
+
exports.AccountBox = AccountBox;
|
|
26
|
+
AccountBox.propTypes = {
|
|
27
|
+
componentName: _propTypes.string,
|
|
28
|
+
additionalClassName: _propTypes.string,
|
|
29
|
+
dimensions: _propTypes.number,
|
|
30
|
+
viewBox: _propTypes.string,
|
|
31
|
+
fill: _propTypes.string
|
|
32
|
+
};
|
|
33
|
+
var _default = exports.default = AccountBox;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.AccountCircle = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _propTypes = require("prop-types");
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const AccountCircle = ({
|
|
11
|
+
componentName = 'account-circle',
|
|
12
|
+
additionalClassName = '',
|
|
13
|
+
dimensions = 24,
|
|
14
|
+
viewBox = '0 -960 960 960',
|
|
15
|
+
fill = '#adb5bd'
|
|
16
|
+
}) => /*#__PURE__*/_react.default.createElement("svg", {
|
|
17
|
+
className: `icon ${componentName} ${additionalClassName}`,
|
|
18
|
+
width: dimensions,
|
|
19
|
+
height: dimensions,
|
|
20
|
+
viewBox: viewBox,
|
|
21
|
+
fill: fill
|
|
22
|
+
}, /*#__PURE__*/_react.default.createElement("path", {
|
|
23
|
+
d: "M234-276q51-39 114-61.5T480-360q69 0 132 22.5T726-276q35-41 54.5-93T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 59 19.5 111t54.5 93Zm246-164q-59 0-99.5-40.5T340-580q0-59 40.5-99.5T480-720q59 0 99.5 40.5T620-580q0 59-40.5 99.5T480-440Zm0 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q53 0 100-15.5t86-44.5q-39-29-86-44.5T480-280q-53 0-100 15.5T294-220q39 29 86 44.5T480-160Zm0-360q26 0 43-17t17-43q0-26-17-43t-43-17q-26 0-43 17t-17 43q0 26 17 43t43 17Zm0-60Zm0 360Z"
|
|
24
|
+
}));
|
|
25
|
+
exports.AccountCircle = AccountCircle;
|
|
26
|
+
AccountCircle.propTypes = {
|
|
27
|
+
componentName: _propTypes.string,
|
|
28
|
+
additionalClassName: _propTypes.string,
|
|
29
|
+
dimensions: _propTypes.number,
|
|
30
|
+
viewBox: _propTypes.string,
|
|
31
|
+
fill: _propTypes.string
|
|
32
|
+
};
|
|
33
|
+
var _default = exports.default = AccountCircle;
|
package/dist/icons/ArrowIcon.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.ArrowIcon = void 0;
|
|
6
|
+
exports.default = exports.ArrowIcon = void 0;
|
|
7
7
|
var _react = _interopRequireDefault(require("react"));
|
|
8
8
|
var _propTypes = require("prop-types");
|
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -29,4 +29,5 @@ ArrowIcon.propTypes = {
|
|
|
29
29
|
dimensions: _propTypes.number,
|
|
30
30
|
viewBox: _propTypes.string,
|
|
31
31
|
fill: _propTypes.string
|
|
32
|
-
};
|
|
32
|
+
};
|
|
33
|
+
var _default = exports.default = ArrowIcon;
|