tw-react-components 0.0.146 → 0.0.148

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/index.cjs.js CHANGED
@@ -6,6 +6,7 @@ var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var dayjs = require('dayjs');
8
8
  var advancedFormat = require('dayjs/plugin/advancedFormat');
9
+ var CollapsiblePrimitive = require('@radix-ui/react-collapsible');
9
10
  var lucideReact = require('lucide-react');
10
11
  var localeData = require('dayjs/plugin/localeData');
11
12
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
@@ -41,6 +42,7 @@ function _interopNamespaceDefault(e) {
41
42
  return Object.freeze(n);
42
43
  }
43
44
 
45
+ var CollapsiblePrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(CollapsiblePrimitive);
44
46
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TooltipPrimitive);
45
47
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DropdownMenuPrimitive);
46
48
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DialogPrimitive);
@@ -624,6 +626,14 @@ const Card = react.forwardRef((_a, ref) => {
624
626
  return (jsxRuntime.jsx(Block, Object.assign({ className: cn('rounded-lg border p-3 dark:border-slate-700 dark:bg-slate-900', className) }, blockProps, { ref: ref, children: children })));
625
627
  });
626
628
 
629
+ const $Collapsible = CollapsiblePrimitive__namespace.Root;
630
+ const CollapsibleTrigger = CollapsiblePrimitive__namespace.CollapsibleTrigger;
631
+ const CollapsibleContent = CollapsiblePrimitive__namespace.CollapsibleContent;
632
+ const Collapsible = Object.assign($Collapsible, {
633
+ Trigger: CollapsibleTrigger,
634
+ Content: CollapsibleContent,
635
+ });
636
+
627
637
  const directionClasses = {
628
638
  row: {
629
639
  normal: 'flex-row',
@@ -1265,7 +1275,7 @@ const SelectInput = react.forwardRef((_a, ref) => {
1265
1275
  const [open, setOpen] = react.useState(false);
1266
1276
  const [searchValue, setSearchValue] = react.useState('');
1267
1277
  const pureItems = react.useMemo(() => items.flatMap((item) => (item.group ? item.items : [item])), [items]);
1268
- const selectedItems = react.useMemo(() => value
1278
+ const selectedItems = react.useMemo(() => isNotNullOrUndefined(value)
1269
1279
  ? !multiple
1270
1280
  ? pureItems.find((item) => selectPredicate(item.value, value))
1271
1281
  ? [pureItems.find((item) => selectPredicate(item.value, value))]
@@ -1305,7 +1315,7 @@ const SelectInput = react.forwardRef((_a, ref) => {
1305
1315
  }
1306
1316
  }
1307
1317
  else if (multiple) {
1308
- if (selectedMap[id]) {
1318
+ if (isNotNullOrUndefined(selectedMap[id])) {
1309
1319
  onChange === null || onChange === void 0 ? void 0 : onChange(selectedItems.filter((item) => item.id !== id).map((item) => item.value));
1310
1320
  }
1311
1321
  else {
@@ -1331,15 +1341,18 @@ const SelectInput = react.forwardRef((_a, ref) => {
1331
1341
  const ItemComponent = multiple ? DropdownMenu.CheckboxItem : DropdownMenu.RadioItem;
1332
1342
  const RenderOption = react.useCallback((option) => {
1333
1343
  return (jsxRuntime.jsx(ItemComponent, { className: cn('w-full cursor-pointer hover:bg-slate-200 dark:hover:bg-slate-700', {
1334
- 'bg-slate-200 dark:bg-slate-700': selectedMap[option.id],
1335
- }), value: String(option.id), checked: !!selectedMap[option.id], onSelect: (event) => {
1344
+ 'bg-slate-200 dark:bg-slate-700': isNotNullOrUndefined(selectedMap[option.id]),
1345
+ }), value: String(option.id), checked: isNotNullOrUndefined(selectedMap[option.id]), onSelect: (event) => {
1336
1346
  multiple && event.preventDefault();
1337
1347
  handleOnSelect(option.id);
1338
- }, children: jsxRuntime.jsx("span", { children: renderItem(option, !!selectedMap[option.id]) }) }));
1348
+ }, children: jsxRuntime.jsx("span", { children: renderItem(option, isNotNullOrUndefined(selectedMap[option.id])) }) }));
1339
1349
  }, [ItemComponent, handleOnSelect, multiple, renderItem, selectedMap]);
1340
1350
  return (jsxRuntime.jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [jsxRuntime.jsx(DropdownMenu.Trigger, { className: cn('w-full', className), children: jsxRuntime.jsx(TextInput, Object.assign({ className: "[&>div>*]:cursor-pointer", inputClassName: "text-left" }, props, { value: text !== null && text !== void 0 ? text : '', clearable: clearable && !!selectedItems.length, onClear: handleOnClear, suffixIcon: lucideReact.ChevronDownIcon, onSuffixIconClick: () => setOpen((open) => !open), ref: ref, readOnly: true })) }), jsxRuntime.jsxs(DropdownMenu.Content, { className: "flex max-h-80 w-[calc(var(--radix-popper-anchor-width))] flex-col overflow-hidden", children: [search && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextInput, { value: searchValue, placeholder: "Search...", size: props.size, onChange: handleOnSearchValueChange, clearable: !!searchValue.length, onClear: clearSearchValue }), jsxRuntime.jsx(DropdownMenu.Separator, { className: "w-full" })] })), filteredItems.length === 0 &&
1341
1351
  (allowAddition && searchValue ? (jsxRuntime.jsxs("button", { className: "rounded bg-slate-100 py-1.5 text-center hover:bg-slate-200 dark:bg-slate-900/30 dark:hover:bg-slate-700/30", onClick: handleOnAddItemClicked, children: ["Add '", searchValue, "'"] })) : (jsxRuntime.jsx("div", { className: "py-1.5 text-center text-slate-500", children: "No items." }))), jsxRuntime.jsx(GroupComponent, { className: "flex flex-col gap-1 overflow-auto", value: !multiple && selectedItems.length ? String(selectedItems[0].id) : undefined, children: filteredItems.map((item, index) => item.group ? (jsxRuntime.jsxs(Flex, { className: "gap-1", direction: "column", fullWidth: true, children: [jsxRuntime.jsx(DropdownMenu.Label, { className: "sticky top-0 z-[51] w-full rounded-md border bg-white py-1 dark:bg-slate-900", children: item.label }), item.items.map((subItem) => (jsxRuntime.jsx(RenderOption, Object.assign({}, subItem), subItem.id))), index < filteredItems.length - 1 && (jsxRuntime.jsx("div", { className: "mb-1 h-px w-full bg-slate-200 dark:bg-slate-700" }))] }, item.id)) : (jsxRuntime.jsx(RenderOption, Object.assign({}, item), item.id))) })] })] }));
1342
1352
  });
1353
+ function isNotNullOrUndefined(value) {
1354
+ return value !== null && value !== undefined;
1355
+ }
1343
1356
 
1344
1357
  const FileInput = react.forwardRef((_a, ref) => {
1345
1358
  var { className, value, onChange, onFileChange, accept } = _a, props = __rest(_a, ["className", "value", "onChange", "onFileChange", "accept"]);
@@ -2054,23 +2067,29 @@ const Sidebar = Object.assign($Sidebar, {
2054
2067
  const Navbar = ({ className, sidebarTriggerClassName, leftSlot, rightSlot, }) => (jsxRuntime.jsx(Block, { className: cn('border-b p-3 dark:border-slate-700', className), fullWidth: true, children: jsxRuntime.jsxs(Flex, { align: "center", justify: "between", children: [jsxRuntime.jsxs(Flex, { align: "center", children: [jsxRuntime.jsx(Sidebar.Trigger, { className: sidebarTriggerClassName }), leftSlot] }), rightSlot] }) }));
2055
2068
 
2056
2069
  const Layout = (_a) => {
2057
- var { children, className } = _a, _b = _a.sidebarProps, { basePath, header, items, footer } = _b, sidebarProps = __rest(_b, ["basePath", "header", "items", "footer"]), { navbarProps } = _a;
2058
- return (jsxRuntime.jsxs(Flex, { className: "h-screen w-screen gap-0 text-black dark:bg-slate-900 dark:text-white", children: [jsxRuntime.jsxs(Sidebar, Object.assign({ collapsible: "icon" }, sidebarProps, { children: [header && (jsxRuntime.jsx(Sidebar.Header, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(Sidebar.MenuItem, { children: header }) }) })), jsxRuntime.jsx(Sidebar.Content, { className: "gap-0", children: items
2059
- .filter((item) => !item.hidden)
2060
- .map((item, index) => item.type === 'item' ? (jsxRuntime.jsx(Sidebar.Group, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, item)) }) }, index)) : (jsxRuntime.jsxs(Sidebar.Group, { children: [item.title && jsxRuntime.jsx(Sidebar.GroupLabel, { children: item.title }), jsxRuntime.jsx(Sidebar.GroupContent, { children: jsxRuntime.jsx(Sidebar.Menu, { children: item.items
2061
- .filter((subItem) => !subItem.hidden)
2062
- .map((subItem, index) => (jsxRuntime.jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, subItem), index))) }) })] }, index))) }), footer && (jsxRuntime.jsx(Sidebar.Footer, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(Sidebar.MenuItem, { children: footer }) }) })), jsxRuntime.jsx(Sidebar.Rail, {})] })), jsxRuntime.jsxs(Flex, { className: "gap-0 overflow-hidden", direction: "column", fullHeight: true, fullWidth: true, children: [navbarProps && jsxRuntime.jsx(Navbar, Object.assign({}, navbarProps)), jsxRuntime.jsx(Flex, { className: cn('overflow-hidden p-3', className), direction: "column", fullWidth: true, fullHeight: true, children: children })] })] }));
2070
+ var { children, className } = _a, _b = _a.sidebarProps, { basePath, header, items, extraContent, footer } = _b, sidebarProps = __rest(_b, ["basePath", "header", "items", "extraContent", "footer"]), { navbarProps } = _a;
2071
+ return (jsxRuntime.jsxs(Flex, { className: "h-screen w-screen gap-0 text-black dark:bg-slate-900 dark:text-white", children: [jsxRuntime.jsxs(Sidebar, Object.assign({ collapsible: "icon" }, sidebarProps, { children: [header && (jsxRuntime.jsx(Sidebar.Header, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(Sidebar.MenuItem, { children: header }) }) })), jsxRuntime.jsxs(Sidebar.Content, { className: "gap-0", children: [items
2072
+ .filter((item) => !item.hidden)
2073
+ .map((item, index) => item.type === 'item' ? (jsxRuntime.jsx(Sidebar.Group, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, item)) }) }, index)) : (jsxRuntime.jsxs(Sidebar.Group, { children: [item.title && jsxRuntime.jsx(Sidebar.GroupLabel, { children: item.title }), jsxRuntime.jsx(Sidebar.GroupContent, { children: jsxRuntime.jsx(Sidebar.Menu, { children: item.items
2074
+ .filter((subItem) => !subItem.hidden)
2075
+ .map((subItem, index) => (jsxRuntime.jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, subItem), index))) }) })] }, index))), extraContent] }), footer && (jsxRuntime.jsx(Sidebar.Footer, { children: jsxRuntime.jsx(Sidebar.Menu, { children: jsxRuntime.jsx(Sidebar.MenuItem, { children: footer }) }) })), jsxRuntime.jsx(Sidebar.Rail, {})] })), jsxRuntime.jsxs(Flex, { className: "gap-0 overflow-hidden", direction: "column", fullHeight: true, fullWidth: true, children: [navbarProps && jsxRuntime.jsx(Navbar, Object.assign({}, navbarProps)), jsxRuntime.jsx(Flex, { className: cn('overflow-hidden p-3', className), direction: "column", fullWidth: true, fullHeight: true, children: children })] })] }));
2063
2076
  };
2064
2077
  const RenderSideBarItem = ({ basePath = '/', pathname, title, Icon, items, }) => {
2065
2078
  const location = reactRouterDom.useLocation();
2066
2079
  const { open } = useSidebar();
2067
2080
  const currentPath = react.useMemo(() => location.pathname.replace(basePath, '').replace(/^\/*/, ''), [basePath, location.pathname]);
2068
- return (jsxRuntime.jsxs(Sidebar.MenuItem, { children: [jsxRuntime.jsx(Sidebar.MenuButton, { asChild: true, tooltip: title, isActive: isLinkStartsWithPathname(currentPath, pathname) &&
2069
- (!items ||
2070
- (!open &&
2071
- items.some((item) => isLinkStartsWithPathname(currentPath, `${pathname}/${item.pathname}`)))), children: jsxRuntime.jsxs(reactRouterDom.Link, { to: pathname, className: "font-medium", children: [Icon && jsxRuntime.jsx(Icon, {}), title] }) }), items && (jsxRuntime.jsx(Sidebar.MenuSub, { children: items
2072
- .filter((subItem) => !subItem.hidden)
2073
- .map((subItem, index) => (jsxRuntime.jsx(Sidebar.MenuSubItem, { children: jsxRuntime.jsx(Sidebar.MenuSubButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`), children: jsxRuntime.jsx(reactRouterDom.Link, { to: `${pathname}/${subItem.pathname}`, children: subItem.title }) }) }, index))) }))] }));
2081
+ if (!(items === null || items === void 0 ? void 0 : items.filter((subItem) => !subItem.hidden).length)) {
2082
+ return (jsxRuntime.jsx(Sidebar.MenuItem, { children: jsxRuntime.jsx(Sidebar.MenuButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, pathname), children: jsxRuntime.jsxs(reactRouterDom.Link, { to: pathname, className: "font-medium", children: [Icon && jsxRuntime.jsx(Icon, {}), title] }) }) }));
2083
+ }
2084
+ const isOpen = open &&
2085
+ (isLinkStartsWithPathname(currentPath, pathname) ||
2086
+ items.some((subItem) => isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`)));
2087
+ return (jsxRuntime.jsx(Collapsible, { asChild: true, open: isOpen, className: "group/collapsible", children: jsxRuntime.jsxs(Sidebar.MenuItem, { children: [jsxRuntime.jsx(Collapsible.Trigger, { asChild: true, children: jsxRuntime.jsx(Sidebar.MenuButton, { asChild: true, tooltip: title, isActive: open
2088
+ ? currentPath === pathname &&
2089
+ !items.some((subItem) => isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`))
2090
+ : isLinkStartsWithPathname(currentPath, pathname), children: jsxRuntime.jsxs(reactRouterDom.Link, { to: pathname, className: "font-medium", children: [Icon && jsxRuntime.jsx(Icon, {}), title, jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })] }) }) }), items && (jsxRuntime.jsx(Collapsible.Content, { children: jsxRuntime.jsx(Sidebar.MenuSub, { children: items
2091
+ .filter((subItem) => !subItem.hidden)
2092
+ .map((subItem, index) => (jsxRuntime.jsx(Sidebar.MenuSubItem, { children: jsxRuntime.jsx(Sidebar.MenuSubButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`), children: jsxRuntime.jsx(reactRouterDom.Link, { to: `${pathname}/${subItem.pathname}`, children: subItem.title }) }) }, index))) }) }))] }) }));
2074
2093
  };
2075
2094
  function isLinkStartsWithPathname(link, pathname) {
2076
2095
  return pathname === '' ? link === pathname : link.startsWith(pathname);
@@ -2183,6 +2202,7 @@ exports.Block = Block;
2183
2202
  exports.Button = Button;
2184
2203
  exports.Card = Card;
2185
2204
  exports.CheckboxInput = CheckboxInput;
2205
+ exports.Collapsible = Collapsible;
2186
2206
  exports.ConfirmDialog = ConfirmDialog;
2187
2207
  exports.DataTable = DataTable;
2188
2208
  exports.DateTimeInput = DateTimeInput;
package/index.esm.js CHANGED
@@ -4,6 +4,7 @@ import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import dayjs from 'dayjs';
6
6
  import advancedFormat from 'dayjs/plugin/advancedFormat';
7
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
7
8
  import { HelpCircle, XIcon, AtSignIcon, EyeIcon, EyeOffIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronDownIcon, CalendarIcon, ClockIcon, CheckIcon, CircleIcon, CloudUploadIcon, ChevronsLeftIcon, ChevronsRightIcon, ChevronsDownUpIcon, ChevronsUpDownIcon, ArrowUpDownIcon, SortAscIcon, SortDescIcon, MinusIcon, PlusIcon, PanelLeft, MoonIcon, SunIcon, MonitorIcon } from 'lucide-react';
8
9
  import localeData from 'dayjs/plugin/localeData';
9
10
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
@@ -597,6 +598,14 @@ const Card = forwardRef((_a, ref) => {
597
598
  return (jsx(Block, Object.assign({ className: cn('rounded-lg border p-3 dark:border-slate-700 dark:bg-slate-900', className) }, blockProps, { ref: ref, children: children })));
598
599
  });
599
600
 
601
+ const $Collapsible = CollapsiblePrimitive.Root;
602
+ const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
603
+ const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
604
+ const Collapsible = Object.assign($Collapsible, {
605
+ Trigger: CollapsibleTrigger,
606
+ Content: CollapsibleContent,
607
+ });
608
+
600
609
  const directionClasses = {
601
610
  row: {
602
611
  normal: 'flex-row',
@@ -1238,7 +1247,7 @@ const SelectInput = forwardRef((_a, ref) => {
1238
1247
  const [open, setOpen] = useState(false);
1239
1248
  const [searchValue, setSearchValue] = useState('');
1240
1249
  const pureItems = useMemo(() => items.flatMap((item) => (item.group ? item.items : [item])), [items]);
1241
- const selectedItems = useMemo(() => value
1250
+ const selectedItems = useMemo(() => isNotNullOrUndefined(value)
1242
1251
  ? !multiple
1243
1252
  ? pureItems.find((item) => selectPredicate(item.value, value))
1244
1253
  ? [pureItems.find((item) => selectPredicate(item.value, value))]
@@ -1278,7 +1287,7 @@ const SelectInput = forwardRef((_a, ref) => {
1278
1287
  }
1279
1288
  }
1280
1289
  else if (multiple) {
1281
- if (selectedMap[id]) {
1290
+ if (isNotNullOrUndefined(selectedMap[id])) {
1282
1291
  onChange === null || onChange === void 0 ? void 0 : onChange(selectedItems.filter((item) => item.id !== id).map((item) => item.value));
1283
1292
  }
1284
1293
  else {
@@ -1304,15 +1313,18 @@ const SelectInput = forwardRef((_a, ref) => {
1304
1313
  const ItemComponent = multiple ? DropdownMenu.CheckboxItem : DropdownMenu.RadioItem;
1305
1314
  const RenderOption = useCallback((option) => {
1306
1315
  return (jsx(ItemComponent, { className: cn('w-full cursor-pointer hover:bg-slate-200 dark:hover:bg-slate-700', {
1307
- 'bg-slate-200 dark:bg-slate-700': selectedMap[option.id],
1308
- }), value: String(option.id), checked: !!selectedMap[option.id], onSelect: (event) => {
1316
+ 'bg-slate-200 dark:bg-slate-700': isNotNullOrUndefined(selectedMap[option.id]),
1317
+ }), value: String(option.id), checked: isNotNullOrUndefined(selectedMap[option.id]), onSelect: (event) => {
1309
1318
  multiple && event.preventDefault();
1310
1319
  handleOnSelect(option.id);
1311
- }, children: jsx("span", { children: renderItem(option, !!selectedMap[option.id]) }) }));
1320
+ }, children: jsx("span", { children: renderItem(option, isNotNullOrUndefined(selectedMap[option.id])) }) }));
1312
1321
  }, [ItemComponent, handleOnSelect, multiple, renderItem, selectedMap]);
1313
1322
  return (jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [jsx(DropdownMenu.Trigger, { className: cn('w-full', className), children: jsx(TextInput, Object.assign({ className: "[&>div>*]:cursor-pointer", inputClassName: "text-left" }, props, { value: text !== null && text !== void 0 ? text : '', clearable: clearable && !!selectedItems.length, onClear: handleOnClear, suffixIcon: ChevronDownIcon, onSuffixIconClick: () => setOpen((open) => !open), ref: ref, readOnly: true })) }), jsxs(DropdownMenu.Content, { className: "flex max-h-80 w-[calc(var(--radix-popper-anchor-width))] flex-col overflow-hidden", children: [search && (jsxs(Fragment, { children: [jsx(TextInput, { value: searchValue, placeholder: "Search...", size: props.size, onChange: handleOnSearchValueChange, clearable: !!searchValue.length, onClear: clearSearchValue }), jsx(DropdownMenu.Separator, { className: "w-full" })] })), filteredItems.length === 0 &&
1314
1323
  (allowAddition && searchValue ? (jsxs("button", { className: "rounded bg-slate-100 py-1.5 text-center hover:bg-slate-200 dark:bg-slate-900/30 dark:hover:bg-slate-700/30", onClick: handleOnAddItemClicked, children: ["Add '", searchValue, "'"] })) : (jsx("div", { className: "py-1.5 text-center text-slate-500", children: "No items." }))), jsx(GroupComponent, { className: "flex flex-col gap-1 overflow-auto", value: !multiple && selectedItems.length ? String(selectedItems[0].id) : undefined, children: filteredItems.map((item, index) => item.group ? (jsxs(Flex, { className: "gap-1", direction: "column", fullWidth: true, children: [jsx(DropdownMenu.Label, { className: "sticky top-0 z-[51] w-full rounded-md border bg-white py-1 dark:bg-slate-900", children: item.label }), item.items.map((subItem) => (jsx(RenderOption, Object.assign({}, subItem), subItem.id))), index < filteredItems.length - 1 && (jsx("div", { className: "mb-1 h-px w-full bg-slate-200 dark:bg-slate-700" }))] }, item.id)) : (jsx(RenderOption, Object.assign({}, item), item.id))) })] })] }));
1315
1324
  });
1325
+ function isNotNullOrUndefined(value) {
1326
+ return value !== null && value !== undefined;
1327
+ }
1316
1328
 
1317
1329
  const FileInput = forwardRef((_a, ref) => {
1318
1330
  var { className, value, onChange, onFileChange, accept } = _a, props = __rest(_a, ["className", "value", "onChange", "onFileChange", "accept"]);
@@ -2027,23 +2039,29 @@ const Sidebar = Object.assign($Sidebar, {
2027
2039
  const Navbar = ({ className, sidebarTriggerClassName, leftSlot, rightSlot, }) => (jsx(Block, { className: cn('border-b p-3 dark:border-slate-700', className), fullWidth: true, children: jsxs(Flex, { align: "center", justify: "between", children: [jsxs(Flex, { align: "center", children: [jsx(Sidebar.Trigger, { className: sidebarTriggerClassName }), leftSlot] }), rightSlot] }) }));
2028
2040
 
2029
2041
  const Layout = (_a) => {
2030
- var { children, className } = _a, _b = _a.sidebarProps, { basePath, header, items, footer } = _b, sidebarProps = __rest(_b, ["basePath", "header", "items", "footer"]), { navbarProps } = _a;
2031
- return (jsxs(Flex, { className: "h-screen w-screen gap-0 text-black dark:bg-slate-900 dark:text-white", children: [jsxs(Sidebar, Object.assign({ collapsible: "icon" }, sidebarProps, { children: [header && (jsx(Sidebar.Header, { children: jsx(Sidebar.Menu, { children: jsx(Sidebar.MenuItem, { children: header }) }) })), jsx(Sidebar.Content, { className: "gap-0", children: items
2032
- .filter((item) => !item.hidden)
2033
- .map((item, index) => item.type === 'item' ? (jsx(Sidebar.Group, { children: jsx(Sidebar.Menu, { children: jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, item)) }) }, index)) : (jsxs(Sidebar.Group, { children: [item.title && jsx(Sidebar.GroupLabel, { children: item.title }), jsx(Sidebar.GroupContent, { children: jsx(Sidebar.Menu, { children: item.items
2034
- .filter((subItem) => !subItem.hidden)
2035
- .map((subItem, index) => (jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, subItem), index))) }) })] }, index))) }), footer && (jsx(Sidebar.Footer, { children: jsx(Sidebar.Menu, { children: jsx(Sidebar.MenuItem, { children: footer }) }) })), jsx(Sidebar.Rail, {})] })), jsxs(Flex, { className: "gap-0 overflow-hidden", direction: "column", fullHeight: true, fullWidth: true, children: [navbarProps && jsx(Navbar, Object.assign({}, navbarProps)), jsx(Flex, { className: cn('overflow-hidden p-3', className), direction: "column", fullWidth: true, fullHeight: true, children: children })] })] }));
2042
+ var { children, className } = _a, _b = _a.sidebarProps, { basePath, header, items, extraContent, footer } = _b, sidebarProps = __rest(_b, ["basePath", "header", "items", "extraContent", "footer"]), { navbarProps } = _a;
2043
+ return (jsxs(Flex, { className: "h-screen w-screen gap-0 text-black dark:bg-slate-900 dark:text-white", children: [jsxs(Sidebar, Object.assign({ collapsible: "icon" }, sidebarProps, { children: [header && (jsx(Sidebar.Header, { children: jsx(Sidebar.Menu, { children: jsx(Sidebar.MenuItem, { children: header }) }) })), jsxs(Sidebar.Content, { className: "gap-0", children: [items
2044
+ .filter((item) => !item.hidden)
2045
+ .map((item, index) => item.type === 'item' ? (jsx(Sidebar.Group, { children: jsx(Sidebar.Menu, { children: jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, item)) }) }, index)) : (jsxs(Sidebar.Group, { children: [item.title && jsx(Sidebar.GroupLabel, { children: item.title }), jsx(Sidebar.GroupContent, { children: jsx(Sidebar.Menu, { children: item.items
2046
+ .filter((subItem) => !subItem.hidden)
2047
+ .map((subItem, index) => (jsx(RenderSideBarItem, Object.assign({ basePath: basePath }, subItem), index))) }) })] }, index))), extraContent] }), footer && (jsx(Sidebar.Footer, { children: jsx(Sidebar.Menu, { children: jsx(Sidebar.MenuItem, { children: footer }) }) })), jsx(Sidebar.Rail, {})] })), jsxs(Flex, { className: "gap-0 overflow-hidden", direction: "column", fullHeight: true, fullWidth: true, children: [navbarProps && jsx(Navbar, Object.assign({}, navbarProps)), jsx(Flex, { className: cn('overflow-hidden p-3', className), direction: "column", fullWidth: true, fullHeight: true, children: children })] })] }));
2036
2048
  };
2037
2049
  const RenderSideBarItem = ({ basePath = '/', pathname, title, Icon, items, }) => {
2038
2050
  const location = useLocation();
2039
2051
  const { open } = useSidebar();
2040
2052
  const currentPath = useMemo(() => location.pathname.replace(basePath, '').replace(/^\/*/, ''), [basePath, location.pathname]);
2041
- return (jsxs(Sidebar.MenuItem, { children: [jsx(Sidebar.MenuButton, { asChild: true, tooltip: title, isActive: isLinkStartsWithPathname(currentPath, pathname) &&
2042
- (!items ||
2043
- (!open &&
2044
- items.some((item) => isLinkStartsWithPathname(currentPath, `${pathname}/${item.pathname}`)))), children: jsxs(Link, { to: pathname, className: "font-medium", children: [Icon && jsx(Icon, {}), title] }) }), items && (jsx(Sidebar.MenuSub, { children: items
2045
- .filter((subItem) => !subItem.hidden)
2046
- .map((subItem, index) => (jsx(Sidebar.MenuSubItem, { children: jsx(Sidebar.MenuSubButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`), children: jsx(Link, { to: `${pathname}/${subItem.pathname}`, children: subItem.title }) }) }, index))) }))] }));
2053
+ if (!(items === null || items === void 0 ? void 0 : items.filter((subItem) => !subItem.hidden).length)) {
2054
+ return (jsx(Sidebar.MenuItem, { children: jsx(Sidebar.MenuButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, pathname), children: jsxs(Link, { to: pathname, className: "font-medium", children: [Icon && jsx(Icon, {}), title] }) }) }));
2055
+ }
2056
+ const isOpen = open &&
2057
+ (isLinkStartsWithPathname(currentPath, pathname) ||
2058
+ items.some((subItem) => isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`)));
2059
+ return (jsx(Collapsible, { asChild: true, open: isOpen, className: "group/collapsible", children: jsxs(Sidebar.MenuItem, { children: [jsx(Collapsible.Trigger, { asChild: true, children: jsx(Sidebar.MenuButton, { asChild: true, tooltip: title, isActive: open
2060
+ ? currentPath === pathname &&
2061
+ !items.some((subItem) => isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`))
2062
+ : isLinkStartsWithPathname(currentPath, pathname), children: jsxs(Link, { to: pathname, className: "font-medium", children: [Icon && jsx(Icon, {}), title, jsx(ChevronRightIcon, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })] }) }) }), items && (jsx(Collapsible.Content, { children: jsx(Sidebar.MenuSub, { children: items
2063
+ .filter((subItem) => !subItem.hidden)
2064
+ .map((subItem, index) => (jsx(Sidebar.MenuSubItem, { children: jsx(Sidebar.MenuSubButton, { asChild: true, isActive: isLinkStartsWithPathname(currentPath, `${pathname}/${subItem.pathname}`), children: jsx(Link, { to: `${pathname}/${subItem.pathname}`, children: subItem.title }) }) }, index))) }) }))] }) }));
2047
2065
  };
2048
2066
  function isLinkStartsWithPathname(link, pathname) {
2049
2067
  return pathname === '' ? link === pathname : link.startsWith(pathname);
@@ -2149,4 +2167,4 @@ const ThemeSelector = ({ className }) => {
2149
2167
  return (jsxs(DropdownMenu, { children: [jsx(DropdownMenu.Trigger, { asChild: true, children: jsx(Button, { prefixIcon: resolvedTheme === 'dark' ? MoonIcon : SunIcon, className: className, variant: "text" }) }), jsxs(DropdownMenu.Content, { children: [jsxs(DropdownMenu.Item, { onClick: () => setTheme('light'), children: [jsx(DropdownMenu.Icon, { icon: SunIcon }), "Light"] }), jsxs(DropdownMenu.Item, { onClick: () => setTheme('dark'), children: [jsx(DropdownMenu.Icon, { icon: MoonIcon }), "Dark"] }), jsxs(DropdownMenu.Item, { onClick: () => setTheme('system'), children: [jsx(DropdownMenu.Icon, { icon: MonitorIcon }), "System"] })] })] }));
2150
2168
  };
2151
2169
 
2152
- export { Badge, BasicInput, BasicInputExtension, Block, Button, Card, CheckboxInput, ConfirmDialog, DataTable, DateTimeInput, Dialog, DropdownMenu, EmailInput, FileInput, Flex, FormDialog, FormGroup, FormInputs, Hint, Label, Layout, LayoutContext, LayoutContextProvider, List, ListSorter, ListSorterDialog, Navbar, NumberInput, Pagination, PasswordInput, PdfViewerDialog, Popover, SHOW_IDS_COOKIE_MAX_AGE, SHOW_IDS_COOKIE_NAME, SIDEBAR_COOKIE_MAX_AGE, SIDEBAR_COOKIE_NAME, SIDEBAR_KEYBOARD_SHORTCUT, SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON, SIDEBAR_WIDTH_MOBILE, SelectInput, Separator, Sheet, Sidebar, SidebarContext, SidebarContextProvider, Skeleton, Spinner, Switch, THEME_COOKIE_MAX_AGE, THEME_COOKIE_NAME, THEME_MEDIA_QUERY, Table, Tabs, TextInput, TextareaInput, ThemeSelector, Tooltip, cn, compareDates, generalComparator, getDisplayDate, getValueFromCookie, isEmpty, mergeRefs, resolveTargetObject, useDays, useIsMobile, useLayoutContext, useLongPress, useMonths, useOnSwipe, useOutsideClick, usePagination, useSidebar };
2170
+ export { Badge, BasicInput, BasicInputExtension, Block, Button, Card, CheckboxInput, Collapsible, ConfirmDialog, DataTable, DateTimeInput, Dialog, DropdownMenu, EmailInput, FileInput, Flex, FormDialog, FormGroup, FormInputs, Hint, Label, Layout, LayoutContext, LayoutContextProvider, List, ListSorter, ListSorterDialog, Navbar, NumberInput, Pagination, PasswordInput, PdfViewerDialog, Popover, SHOW_IDS_COOKIE_MAX_AGE, SHOW_IDS_COOKIE_NAME, SIDEBAR_COOKIE_MAX_AGE, SIDEBAR_COOKIE_NAME, SIDEBAR_KEYBOARD_SHORTCUT, SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON, SIDEBAR_WIDTH_MOBILE, SelectInput, Separator, Sheet, Sidebar, SidebarContext, SidebarContextProvider, Skeleton, Spinner, Switch, THEME_COOKIE_MAX_AGE, THEME_COOKIE_NAME, THEME_MEDIA_QUERY, Table, Tabs, TextInput, TextareaInput, ThemeSelector, Tooltip, cn, compareDates, generalComparator, getDisplayDate, getValueFromCookie, isEmpty, mergeRefs, resolveTargetObject, useDays, useIsMobile, useLayoutContext, useLongPress, useMonths, useOnSwipe, useOutsideClick, usePagination, useSidebar };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tw-react-components",
3
3
  "description": "A set of React components build with TailwindCSS to make a nice dashboard.",
4
- "version": "0.0.146",
4
+ "version": "0.0.148",
5
5
  "license": "MIT",
6
6
  "homepage": "https://bacali95.github.io/tw-react-components",
7
7
  "author": {
@@ -0,0 +1,5 @@
1
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
2
+ export declare const Collapsible: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleProps & import("react").RefAttributes<HTMLDivElement>> & {
3
+ Trigger: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
4
+ Content: import("react").ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleContentProps & import("react").RefAttributes<HTMLDivElement>>;
5
+ };
@@ -20,6 +20,7 @@ export type SidebarProps = ComponentProps<typeof Sidebar> & {
20
20
  hidden?: boolean;
21
21
  items: SidebarItem[];
22
22
  })[];
23
+ extraContent?: ReactNode;
23
24
  footer?: ReactNode;
24
25
  };
25
26
  type Props = {
@@ -2,6 +2,7 @@ export * from './Badge';
2
2
  export * from './Block';
3
3
  export * from './Button';
4
4
  export * from './Card';
5
+ export * from './Collapsible';
5
6
  export * from './DataTable';
6
7
  export * from './Dialog';
7
8
  export * from './DropdownMenu';