@zimyo/ui 1.1.1 → 1.1.2

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 ADDED
@@ -0,0 +1,15 @@
1
+ # 📦 @zimyo/ui
2
+
3
+ A scalable and customizable UI component library built on top of [MUI (Material UI)](https://mui.com/) — optimized for performance, accessibility, and developer experience.
4
+
5
+ > Built with [React](https://reactjs.org/), [TypeScript](https://www.typescriptlang.org/), and bundled using [Rollup](https://rollupjs.org/).
6
+ > Versioned and released via [Changesets](https://github.com/changesets/changesets).
7
+
8
+ ---
9
+
10
+ ## 📋 Prerequisites & Installation
11
+
12
+ To install `@zimyo/ui` **with all required peer dependencies**, run:
13
+
14
+ ```bash
15
+ npm install @zimyo/ui @mui/material@5 @emotion/react @emotion/styled
@@ -1,11 +1,7 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { useTheme, Accordion as Accordion$1, AccordionSummary, AccordionDetails } from '@mui/material';
4
- import { createSvgIcon } from '@mui/material/utils';
5
-
6
- var ExpandMoreIcon = createSvgIcon(/*#__PURE__*/jsx("path", {
7
- d: "M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z"
8
- }), 'ExpandMore');
4
+ import { ExpandMore } from '@mui/icons-material';
9
5
 
10
6
  const AccordionContext = React.createContext({});
11
7
  // Main Accordion Container Component
@@ -79,7 +75,7 @@ const AccordionItem = React.forwardRef(({ value: itemValue, children, sx = {}, .
79
75
  // AccordionTrigger Component
80
76
  const AccordionTrigger = React.forwardRef(({ children, sx = {}, expandIcon, ...props }, ref) => {
81
77
  const theme = useTheme();
82
- const defaultExpandIcon = expandIcon !== undefined ? expandIcon : jsx(ExpandMoreIcon, {});
78
+ const defaultExpandIcon = expandIcon !== undefined ? expandIcon : jsx(ExpandMore, {});
83
79
  return (jsx(AccordionSummary, { ref: ref, expandIcon: defaultExpandIcon, sx: {
84
80
  borderRadius: theme.radius?.sm || theme.shape.borderRadius,
85
81
  minHeight: 56,
@@ -5,11 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
7
  var material = require('@mui/material');
8
- var utils = require('@mui/material/utils');
9
-
10
- var ExpandMoreIcon = utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
11
- d: "M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z"
12
- }), 'ExpandMore');
8
+ var iconsMaterial = require('@mui/icons-material');
13
9
 
14
10
  const AccordionContext = React.createContext({});
15
11
  // Main Accordion Container Component
@@ -83,7 +79,7 @@ const AccordionItem = React.forwardRef(({ value: itemValue, children, sx = {}, .
83
79
  // AccordionTrigger Component
84
80
  const AccordionTrigger = React.forwardRef(({ children, sx = {}, expandIcon, ...props }, ref) => {
85
81
  const theme = material.useTheme();
86
- const defaultExpandIcon = expandIcon !== undefined ? expandIcon : jsxRuntime.jsx(ExpandMoreIcon, {});
82
+ const defaultExpandIcon = expandIcon !== undefined ? expandIcon : jsxRuntime.jsx(iconsMaterial.ExpandMore, {});
87
83
  return (jsxRuntime.jsx(material.AccordionSummary, { ref: ref, expandIcon: defaultExpandIcon, sx: {
88
84
  borderRadius: theme.radius?.sm || theme.shape.borderRadius,
89
85
  minHeight: 56,
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { SelectProps, SelectChangeEvent } from '@mui/material';
3
+
4
+ interface OptionType {
5
+ label: string;
6
+ value: string | number;
7
+ }
8
+ interface CustomSelectProps extends Omit<SelectProps, 'value' | 'onChange'> {
9
+ label?: string;
10
+ options: OptionType[];
11
+ error?: boolean;
12
+ helperText?: string;
13
+ required?: boolean;
14
+ placeholder?: string;
15
+ value?: any;
16
+ onChange?: (event: SelectChangeEvent<any>) => void;
17
+ isMulti?: boolean;
18
+ }
19
+ declare const CustomSelect: React.ForwardRefExoticComponent<Omit<CustomSelectProps, "ref"> & React.RefAttributes<any>>;
20
+
21
+ export { CustomSelect, CustomSelect as default };
22
+ export type { CustomSelectProps, OptionType };
@@ -0,0 +1,63 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { useTheme, FormControl, Select, OutlinedInput, IconButton, MenuItem, ListItemText, FormHelperText, Box, Chip } from '@mui/material';
4
+ import { ExpandMore, Clear } from '@mui/icons-material';
5
+
6
+ const CustomSelect = React.forwardRef(({ label = '', options = [], value, onChange, error = false, helperText = '', required = false, placeholder = 'Select...', isMulti = false, disabled = false, ...rest }, ref) => {
7
+ useTheme();
8
+ const handleRemoveChip = (chipValue) => (e) => {
9
+ e.stopPropagation();
10
+ const newValue = value.filter((v) => v !== chipValue);
11
+ onChange?.({
12
+ target: {
13
+ name: rest.name,
14
+ value: newValue,
15
+ },
16
+ });
17
+ };
18
+ const renderValue = (selected) => {
19
+ if (isMulti && Array.isArray(selected)) {
20
+ return (jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 0.5 }, children: selected.map((val) => {
21
+ const label = options.find((o) => o.value === val)?.label || val;
22
+ return jsx(Box, { onMouseDown: (e) => e.stopPropagation(), children: jsx(Chip, { onDelete: handleRemoveChip(val), label: label, sx: { borderRadius: '12px' } }) }, val);
23
+ }) }));
24
+ }
25
+ return options.find((o) => o.value === selected)?.label || placeholder;
26
+ };
27
+ const handleClearSelection = (e) => {
28
+ e.stopPropagation();
29
+ const emptyValue = isMulti ? [] : '';
30
+ onChange?.({
31
+ target: {
32
+ name: rest.name,
33
+ value: emptyValue,
34
+ },
35
+ });
36
+ };
37
+ return (jsxs(FormControl, { fullWidth: true, error: error, disabled: disabled, sx: {
38
+ '& .MuiOutlinedInput-root': {
39
+ borderRadius: '8px',
40
+ minHeight: '44px',
41
+ // backgroundColor: theme.palette.background.paper,
42
+ fontSize: '14px'
43
+ },
44
+ '& .MuiSelect-select': {
45
+ fontSize: '14px',
46
+ padding: '10px 14px',
47
+ },
48
+ '& .MuiSelect-placeholder': {
49
+ fontSize: '14px',
50
+ },
51
+ '& .MuiMenuItem-root': {
52
+ fontSize: '14px',
53
+ },
54
+ '& .MuiChip-label': {
55
+ fontSize: '14px',
56
+ },
57
+ }, children: [jsx(Select, { displayEmpty: true,
58
+ // labelId={labelId}
59
+ multiple: isMulti, value: value || (isMulti ? [] : ''), onChange: onChange, input: jsx(OutlinedInput, { label: label }), renderValue: renderValue, ref: ref, IconComponent: ExpandMore, endAdornment: value && !isMulti && ((isMulti && value.length > 0) || (!isMulti && value !== '')) ? (jsx(IconButton, { sx: { marginRight: '1rem' }, size: "small", onClick: handleClearSelection, children: jsx(Clear, { fontSize: "small" }) })) : null, variant: "outlined", ...rest, children: options && options.map((option) => (jsx(MenuItem, { value: option.value, children: isMulti ? (jsx(Fragment, { children: jsx(ListItemText, { primary: option.label }) })) : (option.label || placeholder) }, option.value))) }), helperText && jsx(FormHelperText, { children: helperText })] }));
60
+ });
61
+ CustomSelect.displayName = 'CustomSelect';
62
+
63
+ export { CustomSelect, CustomSelect as default };
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var React = require('react');
7
+ var material = require('@mui/material');
8
+ var iconsMaterial = require('@mui/icons-material');
9
+
10
+ const CustomSelect = React.forwardRef(({ label = '', options = [], value, onChange, error = false, helperText = '', required = false, placeholder = 'Select...', isMulti = false, disabled = false, ...rest }, ref) => {
11
+ material.useTheme();
12
+ const handleRemoveChip = (chipValue) => (e) => {
13
+ e.stopPropagation();
14
+ const newValue = value.filter((v) => v !== chipValue);
15
+ onChange?.({
16
+ target: {
17
+ name: rest.name,
18
+ value: newValue,
19
+ },
20
+ });
21
+ };
22
+ const renderValue = (selected) => {
23
+ if (isMulti && Array.isArray(selected)) {
24
+ return (jsxRuntime.jsx(material.Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 0.5 }, children: selected.map((val) => {
25
+ const label = options.find((o) => o.value === val)?.label || val;
26
+ return jsxRuntime.jsx(material.Box, { onMouseDown: (e) => e.stopPropagation(), children: jsxRuntime.jsx(material.Chip, { onDelete: handleRemoveChip(val), label: label, sx: { borderRadius: '12px' } }) }, val);
27
+ }) }));
28
+ }
29
+ return options.find((o) => o.value === selected)?.label || placeholder;
30
+ };
31
+ const handleClearSelection = (e) => {
32
+ e.stopPropagation();
33
+ const emptyValue = isMulti ? [] : '';
34
+ onChange?.({
35
+ target: {
36
+ name: rest.name,
37
+ value: emptyValue,
38
+ },
39
+ });
40
+ };
41
+ return (jsxRuntime.jsxs(material.FormControl, { fullWidth: true, error: error, disabled: disabled, sx: {
42
+ '& .MuiOutlinedInput-root': {
43
+ borderRadius: '8px',
44
+ minHeight: '44px',
45
+ // backgroundColor: theme.palette.background.paper,
46
+ fontSize: '14px'
47
+ },
48
+ '& .MuiSelect-select': {
49
+ fontSize: '14px',
50
+ padding: '10px 14px',
51
+ },
52
+ '& .MuiSelect-placeholder': {
53
+ fontSize: '14px',
54
+ },
55
+ '& .MuiMenuItem-root': {
56
+ fontSize: '14px',
57
+ },
58
+ '& .MuiChip-label': {
59
+ fontSize: '14px',
60
+ },
61
+ }, children: [jsxRuntime.jsx(material.Select, { displayEmpty: true,
62
+ // labelId={labelId}
63
+ multiple: isMulti, value: value || (isMulti ? [] : ''), onChange: onChange, input: jsxRuntime.jsx(material.OutlinedInput, { label: label }), renderValue: renderValue, ref: ref, IconComponent: iconsMaterial.ExpandMore, endAdornment: value && !isMulti && ((isMulti && value.length > 0) || (!isMulti && value !== '')) ? (jsxRuntime.jsx(material.IconButton, { sx: { marginRight: '1rem' }, size: "small", onClick: handleClearSelection, children: jsxRuntime.jsx(iconsMaterial.Clear, { fontSize: "small" }) })) : null, variant: "outlined", ...rest, children: options && options.map((option) => (jsxRuntime.jsx(material.MenuItem, { value: option.value, children: isMulti ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.ListItemText, { primary: option.label }) })) : (option.label || placeholder) }, option.value))) }), helperText && jsxRuntime.jsx(material.FormHelperText, { children: helperText })] }));
64
+ });
65
+ CustomSelect.displayName = 'CustomSelect';
66
+
67
+ exports.CustomSelect = CustomSelect;
68
+ exports.default = CustomSelect;
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { SwitchProps } from '@mui/material';
3
+
4
+ interface SwitchInputProps extends Omit<SwitchProps, 'onChange'> {
5
+ label?: string;
6
+ helperText?: string;
7
+ error?: boolean;
8
+ required?: boolean | number;
9
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>, checked: boolean) => void;
10
+ }
11
+ declare const SwitchInput: React.ForwardRefExoticComponent<Omit<SwitchInputProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
12
+
13
+ export { SwitchInput as default };
14
+ export type { SwitchInputProps };
@@ -0,0 +1,9 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { FormControl, FormControlLabel, Switch, FormHelperText } from '@mui/material';
4
+
5
+ const SwitchInput = React.forwardRef(({ label = '', helperText = '', error = false, onChange, checked, required = false, disabled = false, ...rest }, ref) => {
6
+ return (jsxs(FormControl, { error: error, disabled: disabled, component: "fieldset", children: [jsx(FormControlLabel, { control: jsx(Switch, { inputRef: ref, checked: checked, onChange: (e, checked) => onChange?.(e, checked), disabled: disabled, required: required == 1 || required === true ? true : false, ...rest }), label: label }), helperText && jsx(FormHelperText, { children: helperText })] }));
7
+ });
8
+
9
+ export { SwitchInput as default };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var material = require('@mui/material');
6
+
7
+ const SwitchInput = React.forwardRef(({ label = '', helperText = '', error = false, onChange, checked, required = false, disabled = false, ...rest }, ref) => {
8
+ return (jsxRuntime.jsxs(material.FormControl, { error: error, disabled: disabled, component: "fieldset", children: [jsxRuntime.jsx(material.FormControlLabel, { control: jsxRuntime.jsx(material.Switch, { inputRef: ref, checked: checked, onChange: (e, checked) => onChange?.(e, checked), disabled: disabled, required: required == 1 || required === true ? true : false, ...rest }), label: label }), helperText && jsxRuntime.jsx(material.FormHelperText, { children: helperText })] }));
9
+ });
10
+
11
+ module.exports = SwitchInput;
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { TabProps, TabsProps as TabsProps$1 } from '@mui/material';
3
+ import { SxProps, Theme } from '@mui/system';
4
+
5
+ interface TabItem {
6
+ label: string;
7
+ value: string | number;
8
+ icon?: React.ReactNode;
9
+ disabled?: boolean;
10
+ badge?: string | number;
11
+ }
12
+ interface CustomTabProps extends Omit<TabProps, 'sx'> {
13
+ sx?: SxProps<Theme>;
14
+ badge?: string | number;
15
+ }
16
+ interface TabsProps extends Omit<TabsProps$1, 'children' | 'sx' | 'indicatorColor' | 'textColor'> {
17
+ items: TabItem[];
18
+ value: string | number;
19
+ onChange: (event: React.SyntheticEvent, newValue: string | number) => void;
20
+ variant?: 'standard' | 'scrollable' | 'fullWidth';
21
+ orientation?: 'horizontal' | 'vertical';
22
+ styleVariant?: 'default' | 'filled' | 'outlined' | 'pills' | 'underlined';
23
+ size?: 'small' | 'medium' | 'large';
24
+ centered?: boolean;
25
+ allowScrollButtonsMobile?: boolean;
26
+ scrollButtons?: boolean | 'auto';
27
+ sx?: SxProps<Theme>;
28
+ tabSx?: SxProps<Theme>;
29
+ iconPosition?: 'start' | 'end' | 'top' | 'bottom';
30
+ indicatorColor?: TabsProps$1['indicatorColor'];
31
+ textColor?: TabsProps$1['textColor'];
32
+ }
33
+ declare const Tabs: React.ForwardRefExoticComponent<Omit<TabsProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
34
+
35
+ export { Tabs, Tabs as default };
36
+ export type { CustomTabProps, TabItem, TabsProps };
@@ -0,0 +1,202 @@
1
+ import React from 'react';
2
+ import { useTheme, Box, Tab, Tabs as Tabs$1, alpha } from '@mui/material';
3
+
4
+ // Custom Tab Component
5
+ const CustomTab = React.forwardRef(({ badge, sx, label, ...props }, ref) => {
6
+ const theme = useTheme();
7
+ const tabLabel = badge ? React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } }, label, React.createElement(Box, {
8
+ component: 'span',
9
+ sx: {
10
+ backgroundColor: theme.palette.error.main,
11
+ color: theme.palette.error.contrastText,
12
+ borderRadius: '10px',
13
+ padding: '2px 6px',
14
+ fontSize: '0.75rem',
15
+ fontWeight: 600,
16
+ minWidth: '18px',
17
+ height: '18px',
18
+ display: 'flex',
19
+ alignItems: 'center',
20
+ justifyContent: 'center',
21
+ lineHeight: 1,
22
+ }
23
+ }, badge)) : label;
24
+ return React.createElement(Tab, {
25
+ ref,
26
+ sx: {
27
+ position: 'relative',
28
+ ...sx,
29
+ },
30
+ label: tabLabel,
31
+ ...props
32
+ });
33
+ });
34
+ CustomTab.displayName = 'CustomTab';
35
+ // Main Tabs Component
36
+ const Tabs = React.forwardRef(({ items, value, onChange, variant = 'standard', orientation = 'horizontal', styleVariant = 'default', size = 'medium', centered = false, allowScrollButtonsMobile = false, scrollButtons = 'auto', sx = {}, tabSx = {}, iconPosition = 'start', indicatorColor = 'primary', textColor = 'primary', ...props }, ref) => {
37
+ const theme = useTheme();
38
+ // Get size-based styling
39
+ const getSizeStyles = () => {
40
+ switch (size) {
41
+ case 'small':
42
+ return {
43
+ minHeight: 36,
44
+ fontSize: '0.875rem',
45
+ padding: '6px 12px',
46
+ };
47
+ case 'large':
48
+ return {
49
+ minHeight: 56,
50
+ fontSize: '1rem',
51
+ padding: '12px 24px',
52
+ };
53
+ default:
54
+ return {
55
+ minHeight: 48,
56
+ fontSize: '0.9375rem',
57
+ padding: '8px 16px',
58
+ };
59
+ }
60
+ };
61
+ // Get style variant specific styling
62
+ const getStyleVariantStyles = () => {
63
+ const baseStyles = getSizeStyles();
64
+ switch (styleVariant) {
65
+ case 'filled':
66
+ return {
67
+ '& .MuiTab-root': {
68
+ ...baseStyles,
69
+ backgroundColor: alpha(theme.palette.action.hover, 0.08),
70
+ borderRadius: theme.shape.borderRadius,
71
+ margin: '0 4px',
72
+ border: 'none',
73
+ '&.Mui-selected': {
74
+ backgroundColor: theme.palette.primary.main,
75
+ color: theme.palette.primary.contrastText,
76
+ },
77
+ '&:hover': {
78
+ backgroundColor: alpha(theme.palette.action.hover, 0.12),
79
+ },
80
+ },
81
+ '& .MuiTabs-indicator': {
82
+ display: 'none',
83
+ },
84
+ };
85
+ case 'outlined':
86
+ return {
87
+ '& .MuiTab-root': {
88
+ ...baseStyles,
89
+ border: `1px solid ${alpha(theme.palette.divider, 0.5)}`,
90
+ borderRadius: theme.shape.borderRadius,
91
+ margin: '0 2px',
92
+ '&.Mui-selected': {
93
+ borderColor: theme.palette.primary.main,
94
+ backgroundColor: alpha(theme.palette.primary.main, 0.08),
95
+ color: theme.palette.primary.main,
96
+ },
97
+ '&:hover': {
98
+ borderColor: alpha(theme.palette.primary.main, 0.5),
99
+ },
100
+ },
101
+ '& .MuiTabs-indicator': {
102
+ display: 'none',
103
+ },
104
+ };
105
+ case 'pills':
106
+ return {
107
+ '& .MuiTab-root': {
108
+ ...baseStyles,
109
+ borderRadius: 25,
110
+ margin: '0 4px',
111
+ backgroundColor: 'transparent',
112
+ border: `1px solid transparent`,
113
+ '&.Mui-selected': {
114
+ backgroundColor: theme.palette.primary.main,
115
+ color: theme.palette.primary.contrastText,
116
+ },
117
+ '&:hover': {
118
+ backgroundColor: alpha(theme.palette.action.hover, 0.08),
119
+ },
120
+ },
121
+ '& .MuiTabs-indicator': {
122
+ display: 'none',
123
+ },
124
+ };
125
+ case 'underlined':
126
+ return {
127
+ '& .MuiTab-root': {
128
+ ...baseStyles,
129
+ borderBottom: `2px solid transparent`,
130
+ '&.Mui-selected': {
131
+ borderBottomColor: theme.palette.primary.main,
132
+ },
133
+ },
134
+ '& .MuiTabs-indicator': {
135
+ display: 'none',
136
+ },
137
+ };
138
+ default:
139
+ return {
140
+ '& .MuiTab-root': {
141
+ ...baseStyles,
142
+ },
143
+ };
144
+ }
145
+ };
146
+ return React.createElement(Box, { ref }, React.createElement(Tabs$1, {
147
+ value,
148
+ onChange,
149
+ variant,
150
+ orientation,
151
+ centered,
152
+ allowScrollButtonsMobile,
153
+ scrollButtons,
154
+ indicatorColor,
155
+ textColor,
156
+ sx: {
157
+ ...getStyleVariantStyles(),
158
+ '& .MuiTab-root': {
159
+ textTransform: 'none',
160
+ fontWeight: 500,
161
+ letterSpacing: '0.5px',
162
+ transition: 'all 0.2s ease-in-out',
163
+ ...getStyleVariantStyles()['& .MuiTab-root'],
164
+ ...tabSx,
165
+ },
166
+ ...sx,
167
+ },
168
+ ...props,
169
+ }, ...items.map((item) => {
170
+ // Create the label content based on icon position
171
+ let labelContent;
172
+ if (item.icon) {
173
+ switch (iconPosition) {
174
+ case 'end':
175
+ labelContent = React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, flexDirection: 'row-reverse' } }, item.icon, item.label);
176
+ break;
177
+ case 'top':
178
+ labelContent = React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 0.5, flexDirection: 'column' } }, item.icon, item.label);
179
+ break;
180
+ case 'bottom':
181
+ labelContent = React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 0.5, flexDirection: 'column-reverse' } }, item.icon, item.label);
182
+ break;
183
+ default: // 'start'
184
+ labelContent = React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } }, item.icon, item.label);
185
+ break;
186
+ }
187
+ }
188
+ else {
189
+ labelContent = item.label;
190
+ }
191
+ return React.createElement(CustomTab, {
192
+ key: item.value,
193
+ value: item.value,
194
+ disabled: item.disabled,
195
+ badge: item.badge,
196
+ label: labelContent,
197
+ });
198
+ })));
199
+ });
200
+ Tabs.displayName = 'Tabs';
201
+
202
+ export { Tabs, Tabs as default };