tw-react-components 0.0.139 → 0.0.140
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 +65 -40
- package/index.esm.js +56 -40
- package/package.json +1 -1
- package/src/components/Button/index.d.ts +2 -0
- package/src/components/Navbar/index.d.ts +1 -0
- package/src/components/Sidebar/index.d.ts +7 -0
- package/src/components/{ThemeSwitcher → ThemeSelector}/index.d.ts +1 -1
- package/src/components/index.d.ts +1 -1
- package/src/contexts/LayoutContext.d.ts +6 -3
- package/src/helpers/getValueFromCookie.d.ts +1 -0
- package/src/helpers/index.d.ts +1 -0
package/index.cjs.js
CHANGED
|
@@ -123,6 +123,19 @@ function getDisplayDate(date, format, locale) {
|
|
|
123
123
|
return (locale ? dayjs(date).locale(locale) : dayjs(date)).format(format);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
function getValueFromCookie(key, _default) {
|
|
127
|
+
var _a, _b;
|
|
128
|
+
const transformers = {
|
|
129
|
+
string: String,
|
|
130
|
+
boolean: (value) => value === 'true',
|
|
131
|
+
};
|
|
132
|
+
return typeof window !== 'undefined'
|
|
133
|
+
? transformers[typeof _default]((_b = (_a = document.cookie
|
|
134
|
+
.split('; ')
|
|
135
|
+
.find((row) => row.startsWith(key))) === null || _a === void 0 ? void 0 : _a.split('=')[1]) !== null && _b !== void 0 ? _b : _default)
|
|
136
|
+
: _default;
|
|
137
|
+
}
|
|
138
|
+
|
|
126
139
|
function isEmpty(s) {
|
|
127
140
|
if (Array.isArray(s))
|
|
128
141
|
return s.length === 0;
|
|
@@ -586,10 +599,10 @@ const sizeClassNames = {
|
|
|
586
599
|
},
|
|
587
600
|
};
|
|
588
601
|
const Button = react.forwardRef((_a, ref) => {
|
|
589
|
-
var { children, className, size = 'medium', color = 'slate', variant = 'filled', rounded, prefixIcon: PrefixIcon, suffixIcon: SuffixIcon } = _a, props = __rest(_a, ["children", "className", "size", "color", "variant", "rounded", "prefixIcon", "suffixIcon"]);
|
|
602
|
+
var { children, className, size = 'medium', color = 'slate', variant = 'filled', rounded, prefixIcon: PrefixIcon, suffixIcon: SuffixIcon, unstyled } = _a, props = __rest(_a, ["children", "className", "size", "color", "variant", "rounded", "prefixIcon", "suffixIcon", "unstyled"]);
|
|
590
603
|
return (jsxRuntime.jsxs("button", Object.assign({ className: cn('relative flex aspect-square items-center font-medium duration-200', sizeClassNames[size].base, variantClassNames[variant][color].base, rounded ? 'rounded-full' : 'rounded-md', props.disabled
|
|
591
604
|
? 'cursor-not-allowed opacity-50'
|
|
592
|
-
:
|
|
605
|
+
: !unstyled
|
|
593
606
|
? `${variantClassNames[variant][color].hover} ${variantClassNames[variant][color].focus} ${variantClassNames[variant][color].active}`
|
|
594
607
|
: 'cursor-default', children ? `${sizeClassNames[size].withChildren} aspect-[initial]` : 'justify-center', className), type: "button" }, props, { ref: ref, children: [PrefixIcon && (jsxRuntime.jsx(PrefixIcon, { className: children ? sizeClassNames[size].icon.withChildren : sizeClassNames[size].icon.base })), children, SuffixIcon && (jsxRuntime.jsx(SuffixIcon, { className: children ? sizeClassNames[size].icon.withChildren : sizeClassNames[size].icon.base }))] })));
|
|
595
608
|
});
|
|
@@ -1794,15 +1807,16 @@ const SidebarContextProvider = react.forwardRef((_a, ref) => {
|
|
|
1794
1807
|
const screenRef = react.useRef(document.documentElement);
|
|
1795
1808
|
// This is the internal state of the sidebar.
|
|
1796
1809
|
// We use openProp and setOpenProp for control from outside the component.
|
|
1797
|
-
const [_open, _setOpen] = react.useState(defaultOpen);
|
|
1810
|
+
const [_open, _setOpen] = react.useState(getValueFromCookie(SIDEBAR_COOKIE_NAME, defaultOpen));
|
|
1798
1811
|
const open = openProp !== null && openProp !== void 0 ? openProp : _open;
|
|
1799
1812
|
const setOpen = react.useCallback((value) => {
|
|
1800
1813
|
if (setOpenProp) {
|
|
1801
1814
|
return setOpenProp === null || setOpenProp === void 0 ? void 0 : setOpenProp(typeof value === 'function' ? value(open) : value);
|
|
1802
1815
|
}
|
|
1803
|
-
|
|
1816
|
+
const newValue = typeof value === 'function' ? value(open) : value;
|
|
1817
|
+
_setOpen(newValue);
|
|
1804
1818
|
// This sets the cookie to keep the sidebar state.
|
|
1805
|
-
document.cookie = `${SIDEBAR_COOKIE_NAME}=${
|
|
1819
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${newValue}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
1806
1820
|
}, [setOpenProp, open]);
|
|
1807
1821
|
// Helper to toggle the sidebar.
|
|
1808
1822
|
const toggleSidebar = react.useCallback(() => {
|
|
@@ -1861,7 +1875,7 @@ $Sidebar.displayName = 'Sidebar';
|
|
|
1861
1875
|
const SidebarTrigger = react.forwardRef((_a, ref) => {
|
|
1862
1876
|
var { className, onClick } = _a, props = __rest(_a, ["className", "onClick"]);
|
|
1863
1877
|
const { toggleSidebar } = useSidebar();
|
|
1864
|
-
return (jsxRuntime.jsx(Button, Object.assign({ ref: ref, "data-sidebar": "trigger", variant: "text", suffixIcon: lucideReact.PanelLeft, className:
|
|
1878
|
+
return (jsxRuntime.jsx(Button, Object.assign({ ref: ref, "data-sidebar": "trigger", variant: "text", suffixIcon: lucideReact.PanelLeft, className: className, onClick: (event) => {
|
|
1865
1879
|
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
1866
1880
|
toggleSidebar();
|
|
1867
1881
|
} }, props)));
|
|
@@ -2035,7 +2049,7 @@ const Sidebar = Object.assign($Sidebar, {
|
|
|
2035
2049
|
Trigger: SidebarTrigger,
|
|
2036
2050
|
});
|
|
2037
2051
|
|
|
2038
|
-
const Navbar = ({ className, 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, {}), leftSlot] }), rightSlot] }) }));
|
|
2052
|
+
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] }) }));
|
|
2039
2053
|
|
|
2040
2054
|
const Layout = (_a) => {
|
|
2041
2055
|
var { children, className } = _a, _b = _a.sidebarProps, { basePath, smallLogo, fullLogo, items } = _b, sidebarProps = __rest(_b, ["basePath", "smallLogo", "fullLogo", "items"]), { navbarProps } = _a;
|
|
@@ -2095,26 +2109,37 @@ const Tabs = Object.assign($Tabs, {
|
|
|
2095
2109
|
});
|
|
2096
2110
|
|
|
2097
2111
|
const LayoutContext = react.createContext(undefined);
|
|
2112
|
+
const THEME_MEDIA_QUERY = '(prefers-color-scheme: dark)';
|
|
2113
|
+
const THEME_COOKIE_NAME = 'theme:state';
|
|
2114
|
+
const THEME_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
2098
2115
|
const LayoutContextProvider = ({ children }) => {
|
|
2099
|
-
const [theme,
|
|
2116
|
+
const [theme, _setTheme] = react.useState(getValueFromCookie(THEME_COOKIE_NAME, 'system'));
|
|
2117
|
+
const [resolvedTheme, setResolvedTheme] = react.useState(() => theme === 'system' ? getSystemTheme() : theme);
|
|
2100
2118
|
react.useEffect(() => {
|
|
2101
|
-
if (
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2119
|
+
if (resolvedTheme === 'dark') {
|
|
2120
|
+
document.documentElement.classList.add('dark');
|
|
2121
|
+
}
|
|
2122
|
+
else {
|
|
2123
|
+
document.documentElement.classList.remove('dark');
|
|
2124
|
+
}
|
|
2125
|
+
}, [resolvedTheme]);
|
|
2126
|
+
react.useEffect(() => {
|
|
2127
|
+
if (theme !== 'system') {
|
|
2128
|
+
setResolvedTheme(theme);
|
|
2129
|
+
return;
|
|
2108
2130
|
}
|
|
2131
|
+
setResolvedTheme(getSystemTheme());
|
|
2132
|
+
const handleMediaQuery = (e) => setResolvedTheme(getSystemTheme(e));
|
|
2133
|
+
const mediaQuery = window.matchMedia(THEME_MEDIA_QUERY);
|
|
2134
|
+
mediaQuery.addEventListener('change', handleMediaQuery);
|
|
2135
|
+
return () => mediaQuery.removeEventListener('change', handleMediaQuery);
|
|
2109
2136
|
}, [theme]);
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
return newValue;
|
|
2115
|
-
});
|
|
2137
|
+
const setTheme = (theme) => {
|
|
2138
|
+
_setTheme(theme);
|
|
2139
|
+
// This sets the cookie to keep the theme state.
|
|
2140
|
+
document.cookie = `${THEME_COOKIE_NAME}=${theme}; path=/; max-age=${THEME_COOKIE_MAX_AGE}`;
|
|
2116
2141
|
};
|
|
2117
|
-
return jsxRuntime.jsx(LayoutContext.Provider, { value: { theme,
|
|
2142
|
+
return (jsxRuntime.jsx(LayoutContext.Provider, { value: { theme, resolvedTheme, setTheme }, children: children }));
|
|
2118
2143
|
};
|
|
2119
2144
|
function useLayoutContext() {
|
|
2120
2145
|
const context = react.useContext(LayoutContext);
|
|
@@ -2123,24 +2148,15 @@ function useLayoutContext() {
|
|
|
2123
2148
|
}
|
|
2124
2149
|
return context;
|
|
2125
2150
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
string: String,
|
|
2131
|
-
boolean: (value) => value === 'true',
|
|
2132
|
-
};
|
|
2133
|
-
return typeof window !== 'undefined'
|
|
2134
|
-
? transformers[typeof _default]((_a = window.localStorage.getItem(key)) !== null && _a !== void 0 ? _a : _default)
|
|
2135
|
-
: _default;
|
|
2151
|
+
function getSystemTheme(e) {
|
|
2152
|
+
if (!e)
|
|
2153
|
+
e = window.matchMedia(THEME_MEDIA_QUERY);
|
|
2154
|
+
return e.matches ? 'dark' : 'light';
|
|
2136
2155
|
}
|
|
2137
2156
|
|
|
2138
|
-
const
|
|
2139
|
-
const {
|
|
2140
|
-
|
|
2141
|
-
return (jsxRuntime.jsx(Switch, { className: className, checked: darkMode, onCheckedChange: toggleTheme, thumbProps: {
|
|
2142
|
-
children: darkMode ? (jsxRuntime.jsx(lucideReact.MoonIcon, { className: "h-6 w-6 rounded-full bg-slate-900 p-1 text-white" })) : (jsxRuntime.jsx(lucideReact.SunIcon, { className: "h-6 w-6 rounded-full bg-white p-1 text-black" })),
|
|
2143
|
-
} }));
|
|
2157
|
+
const ThemeSelector = ({ className }) => {
|
|
2158
|
+
const { resolvedTheme, setTheme } = useLayoutContext();
|
|
2159
|
+
return (jsxRuntime.jsxs(DropdownMenu, { children: [jsxRuntime.jsx(DropdownMenu.Trigger, { asChild: true, children: jsxRuntime.jsx(Button, { prefixIcon: resolvedTheme === 'dark' ? lucideReact.MoonIcon : lucideReact.SunIcon, className: className, variant: "text" }) }), jsxRuntime.jsxs(DropdownMenu.Content, { children: [jsxRuntime.jsxs(DropdownMenu.Item, { onClick: () => setTheme('light'), children: [jsxRuntime.jsx(DropdownMenu.Icon, { icon: lucideReact.SunIcon }), "Light"] }), jsxRuntime.jsxs(DropdownMenu.Item, { onClick: () => setTheme('dark'), children: [jsxRuntime.jsx(DropdownMenu.Icon, { icon: lucideReact.MoonIcon }), "Dark"] }), jsxRuntime.jsxs(DropdownMenu.Item, { onClick: () => setTheme('system'), children: [jsxRuntime.jsx(DropdownMenu.Icon, { icon: lucideReact.MonitorIcon }), "System"] })] })] }));
|
|
2144
2160
|
};
|
|
2145
2161
|
|
|
2146
2162
|
exports.Badge = Badge;
|
|
@@ -2175,6 +2191,12 @@ exports.Pagination = Pagination;
|
|
|
2175
2191
|
exports.PasswordInput = PasswordInput;
|
|
2176
2192
|
exports.PdfViewerDialog = PdfViewerDialog;
|
|
2177
2193
|
exports.Popover = Popover;
|
|
2194
|
+
exports.SIDEBAR_COOKIE_MAX_AGE = SIDEBAR_COOKIE_MAX_AGE;
|
|
2195
|
+
exports.SIDEBAR_COOKIE_NAME = SIDEBAR_COOKIE_NAME;
|
|
2196
|
+
exports.SIDEBAR_KEYBOARD_SHORTCUT = SIDEBAR_KEYBOARD_SHORTCUT;
|
|
2197
|
+
exports.SIDEBAR_WIDTH = SIDEBAR_WIDTH;
|
|
2198
|
+
exports.SIDEBAR_WIDTH_ICON = SIDEBAR_WIDTH_ICON;
|
|
2199
|
+
exports.SIDEBAR_WIDTH_MOBILE = SIDEBAR_WIDTH_MOBILE;
|
|
2178
2200
|
exports.SelectInput = SelectInput;
|
|
2179
2201
|
exports.Separator = Separator;
|
|
2180
2202
|
exports.Sheet = Sheet;
|
|
@@ -2184,17 +2206,20 @@ exports.SidebarContextProvider = SidebarContextProvider;
|
|
|
2184
2206
|
exports.Skeleton = Skeleton;
|
|
2185
2207
|
exports.Spinner = Spinner;
|
|
2186
2208
|
exports.Switch = Switch;
|
|
2187
|
-
exports.
|
|
2209
|
+
exports.THEME_COOKIE_MAX_AGE = THEME_COOKIE_MAX_AGE;
|
|
2210
|
+
exports.THEME_COOKIE_NAME = THEME_COOKIE_NAME;
|
|
2211
|
+
exports.THEME_MEDIA_QUERY = THEME_MEDIA_QUERY;
|
|
2188
2212
|
exports.Table = Table;
|
|
2189
2213
|
exports.Tabs = Tabs;
|
|
2190
2214
|
exports.TextInput = TextInput;
|
|
2191
2215
|
exports.TextareaInput = TextareaInput;
|
|
2192
|
-
exports.
|
|
2216
|
+
exports.ThemeSelector = ThemeSelector;
|
|
2193
2217
|
exports.Tooltip = Tooltip;
|
|
2194
2218
|
exports.cn = cn;
|
|
2195
2219
|
exports.compareDates = compareDates;
|
|
2196
2220
|
exports.generalComparator = generalComparator;
|
|
2197
2221
|
exports.getDisplayDate = getDisplayDate;
|
|
2222
|
+
exports.getValueFromCookie = getValueFromCookie;
|
|
2198
2223
|
exports.isEmpty = isEmpty;
|
|
2199
2224
|
exports.mergeRefs = mergeRefs;
|
|
2200
2225
|
exports.resolveTargetObject = resolveTargetObject;
|
package/index.esm.js
CHANGED
|
@@ -4,7 +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 { 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 } from 'lucide-react';
|
|
7
|
+
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
8
|
import localeData from 'dayjs/plugin/localeData';
|
|
9
9
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
10
10
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
@@ -96,6 +96,19 @@ function getDisplayDate(date, format, locale) {
|
|
|
96
96
|
return (locale ? dayjs(date).locale(locale) : dayjs(date)).format(format);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
function getValueFromCookie(key, _default) {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
const transformers = {
|
|
102
|
+
string: String,
|
|
103
|
+
boolean: (value) => value === 'true',
|
|
104
|
+
};
|
|
105
|
+
return typeof window !== 'undefined'
|
|
106
|
+
? transformers[typeof _default]((_b = (_a = document.cookie
|
|
107
|
+
.split('; ')
|
|
108
|
+
.find((row) => row.startsWith(key))) === null || _a === void 0 ? void 0 : _a.split('=')[1]) !== null && _b !== void 0 ? _b : _default)
|
|
109
|
+
: _default;
|
|
110
|
+
}
|
|
111
|
+
|
|
99
112
|
function isEmpty(s) {
|
|
100
113
|
if (Array.isArray(s))
|
|
101
114
|
return s.length === 0;
|
|
@@ -559,10 +572,10 @@ const sizeClassNames = {
|
|
|
559
572
|
},
|
|
560
573
|
};
|
|
561
574
|
const Button = forwardRef((_a, ref) => {
|
|
562
|
-
var { children, className, size = 'medium', color = 'slate', variant = 'filled', rounded, prefixIcon: PrefixIcon, suffixIcon: SuffixIcon } = _a, props = __rest(_a, ["children", "className", "size", "color", "variant", "rounded", "prefixIcon", "suffixIcon"]);
|
|
575
|
+
var { children, className, size = 'medium', color = 'slate', variant = 'filled', rounded, prefixIcon: PrefixIcon, suffixIcon: SuffixIcon, unstyled } = _a, props = __rest(_a, ["children", "className", "size", "color", "variant", "rounded", "prefixIcon", "suffixIcon", "unstyled"]);
|
|
563
576
|
return (jsxs("button", Object.assign({ className: cn('relative flex aspect-square items-center font-medium duration-200', sizeClassNames[size].base, variantClassNames[variant][color].base, rounded ? 'rounded-full' : 'rounded-md', props.disabled
|
|
564
577
|
? 'cursor-not-allowed opacity-50'
|
|
565
|
-
:
|
|
578
|
+
: !unstyled
|
|
566
579
|
? `${variantClassNames[variant][color].hover} ${variantClassNames[variant][color].focus} ${variantClassNames[variant][color].active}`
|
|
567
580
|
: 'cursor-default', children ? `${sizeClassNames[size].withChildren} aspect-[initial]` : 'justify-center', className), type: "button" }, props, { ref: ref, children: [PrefixIcon && (jsx(PrefixIcon, { className: children ? sizeClassNames[size].icon.withChildren : sizeClassNames[size].icon.base })), children, SuffixIcon && (jsx(SuffixIcon, { className: children ? sizeClassNames[size].icon.withChildren : sizeClassNames[size].icon.base }))] })));
|
|
568
581
|
});
|
|
@@ -1767,15 +1780,16 @@ const SidebarContextProvider = forwardRef((_a, ref) => {
|
|
|
1767
1780
|
const screenRef = useRef(document.documentElement);
|
|
1768
1781
|
// This is the internal state of the sidebar.
|
|
1769
1782
|
// We use openProp and setOpenProp for control from outside the component.
|
|
1770
|
-
const [_open, _setOpen] = useState(defaultOpen);
|
|
1783
|
+
const [_open, _setOpen] = useState(getValueFromCookie(SIDEBAR_COOKIE_NAME, defaultOpen));
|
|
1771
1784
|
const open = openProp !== null && openProp !== void 0 ? openProp : _open;
|
|
1772
1785
|
const setOpen = useCallback((value) => {
|
|
1773
1786
|
if (setOpenProp) {
|
|
1774
1787
|
return setOpenProp === null || setOpenProp === void 0 ? void 0 : setOpenProp(typeof value === 'function' ? value(open) : value);
|
|
1775
1788
|
}
|
|
1776
|
-
|
|
1789
|
+
const newValue = typeof value === 'function' ? value(open) : value;
|
|
1790
|
+
_setOpen(newValue);
|
|
1777
1791
|
// This sets the cookie to keep the sidebar state.
|
|
1778
|
-
document.cookie = `${SIDEBAR_COOKIE_NAME}=${
|
|
1792
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${newValue}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
1779
1793
|
}, [setOpenProp, open]);
|
|
1780
1794
|
// Helper to toggle the sidebar.
|
|
1781
1795
|
const toggleSidebar = useCallback(() => {
|
|
@@ -1834,7 +1848,7 @@ $Sidebar.displayName = 'Sidebar';
|
|
|
1834
1848
|
const SidebarTrigger = forwardRef((_a, ref) => {
|
|
1835
1849
|
var { className, onClick } = _a, props = __rest(_a, ["className", "onClick"]);
|
|
1836
1850
|
const { toggleSidebar } = useSidebar();
|
|
1837
|
-
return (jsx(Button, Object.assign({ ref: ref, "data-sidebar": "trigger", variant: "text", suffixIcon: PanelLeft, className:
|
|
1851
|
+
return (jsx(Button, Object.assign({ ref: ref, "data-sidebar": "trigger", variant: "text", suffixIcon: PanelLeft, className: className, onClick: (event) => {
|
|
1838
1852
|
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
1839
1853
|
toggleSidebar();
|
|
1840
1854
|
} }, props)));
|
|
@@ -2008,7 +2022,7 @@ const Sidebar = Object.assign($Sidebar, {
|
|
|
2008
2022
|
Trigger: SidebarTrigger,
|
|
2009
2023
|
});
|
|
2010
2024
|
|
|
2011
|
-
const Navbar = ({ className, 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, {}), leftSlot] }), rightSlot] }) }));
|
|
2025
|
+
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] }) }));
|
|
2012
2026
|
|
|
2013
2027
|
const Layout = (_a) => {
|
|
2014
2028
|
var { children, className } = _a, _b = _a.sidebarProps, { basePath, smallLogo, fullLogo, items } = _b, sidebarProps = __rest(_b, ["basePath", "smallLogo", "fullLogo", "items"]), { navbarProps } = _a;
|
|
@@ -2068,26 +2082,37 @@ const Tabs = Object.assign($Tabs, {
|
|
|
2068
2082
|
});
|
|
2069
2083
|
|
|
2070
2084
|
const LayoutContext = createContext(undefined);
|
|
2085
|
+
const THEME_MEDIA_QUERY = '(prefers-color-scheme: dark)';
|
|
2086
|
+
const THEME_COOKIE_NAME = 'theme:state';
|
|
2087
|
+
const THEME_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
2071
2088
|
const LayoutContextProvider = ({ children }) => {
|
|
2072
|
-
const [theme,
|
|
2089
|
+
const [theme, _setTheme] = useState(getValueFromCookie(THEME_COOKIE_NAME, 'system'));
|
|
2090
|
+
const [resolvedTheme, setResolvedTheme] = useState(() => theme === 'system' ? getSystemTheme() : theme);
|
|
2073
2091
|
useEffect(() => {
|
|
2074
|
-
if (
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2092
|
+
if (resolvedTheme === 'dark') {
|
|
2093
|
+
document.documentElement.classList.add('dark');
|
|
2094
|
+
}
|
|
2095
|
+
else {
|
|
2096
|
+
document.documentElement.classList.remove('dark');
|
|
2097
|
+
}
|
|
2098
|
+
}, [resolvedTheme]);
|
|
2099
|
+
useEffect(() => {
|
|
2100
|
+
if (theme !== 'system') {
|
|
2101
|
+
setResolvedTheme(theme);
|
|
2102
|
+
return;
|
|
2081
2103
|
}
|
|
2104
|
+
setResolvedTheme(getSystemTheme());
|
|
2105
|
+
const handleMediaQuery = (e) => setResolvedTheme(getSystemTheme(e));
|
|
2106
|
+
const mediaQuery = window.matchMedia(THEME_MEDIA_QUERY);
|
|
2107
|
+
mediaQuery.addEventListener('change', handleMediaQuery);
|
|
2108
|
+
return () => mediaQuery.removeEventListener('change', handleMediaQuery);
|
|
2082
2109
|
}, [theme]);
|
|
2083
|
-
const
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
return newValue;
|
|
2088
|
-
});
|
|
2110
|
+
const setTheme = (theme) => {
|
|
2111
|
+
_setTheme(theme);
|
|
2112
|
+
// This sets the cookie to keep the theme state.
|
|
2113
|
+
document.cookie = `${THEME_COOKIE_NAME}=${theme}; path=/; max-age=${THEME_COOKIE_MAX_AGE}`;
|
|
2089
2114
|
};
|
|
2090
|
-
return jsx(LayoutContext.Provider, { value: { theme,
|
|
2115
|
+
return (jsx(LayoutContext.Provider, { value: { theme, resolvedTheme, setTheme }, children: children }));
|
|
2091
2116
|
};
|
|
2092
2117
|
function useLayoutContext() {
|
|
2093
2118
|
const context = useContext(LayoutContext);
|
|
@@ -2096,24 +2121,15 @@ function useLayoutContext() {
|
|
|
2096
2121
|
}
|
|
2097
2122
|
return context;
|
|
2098
2123
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
string: String,
|
|
2104
|
-
boolean: (value) => value === 'true',
|
|
2105
|
-
};
|
|
2106
|
-
return typeof window !== 'undefined'
|
|
2107
|
-
? transformers[typeof _default]((_a = window.localStorage.getItem(key)) !== null && _a !== void 0 ? _a : _default)
|
|
2108
|
-
: _default;
|
|
2124
|
+
function getSystemTheme(e) {
|
|
2125
|
+
if (!e)
|
|
2126
|
+
e = window.matchMedia(THEME_MEDIA_QUERY);
|
|
2127
|
+
return e.matches ? 'dark' : 'light';
|
|
2109
2128
|
}
|
|
2110
2129
|
|
|
2111
|
-
const
|
|
2112
|
-
const {
|
|
2113
|
-
|
|
2114
|
-
return (jsx(Switch, { className: className, checked: darkMode, onCheckedChange: toggleTheme, thumbProps: {
|
|
2115
|
-
children: darkMode ? (jsx(MoonIcon, { className: "h-6 w-6 rounded-full bg-slate-900 p-1 text-white" })) : (jsx(SunIcon, { className: "h-6 w-6 rounded-full bg-white p-1 text-black" })),
|
|
2116
|
-
} }));
|
|
2130
|
+
const ThemeSelector = ({ className }) => {
|
|
2131
|
+
const { resolvedTheme, setTheme } = useLayoutContext();
|
|
2132
|
+
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"] })] })] }));
|
|
2117
2133
|
};
|
|
2118
2134
|
|
|
2119
|
-
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, SelectInput, Separator, Sheet, Sidebar, SidebarContext, SidebarContextProvider, Skeleton, Spinner, Switch,
|
|
2135
|
+
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, 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.
|
|
4
|
+
"version": "0.0.140",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://bacali95.github.io/tw-react-components",
|
|
7
7
|
"author": {
|
|
@@ -9,6 +9,7 @@ export type ButtonProps = PropsWithoutRef<ComponentProps<'button'>> & {
|
|
|
9
9
|
rounded?: boolean;
|
|
10
10
|
prefixIcon?: LucideIcon;
|
|
11
11
|
suffixIcon?: LucideIcon;
|
|
12
|
+
unstyled?: boolean;
|
|
12
13
|
};
|
|
13
14
|
export declare const Button: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
|
14
15
|
size?: Size;
|
|
@@ -17,4 +18,5 @@ export declare const Button: import("react").ForwardRefExoticComponent<Omit<impo
|
|
|
17
18
|
rounded?: boolean;
|
|
18
19
|
prefixIcon?: LucideIcon;
|
|
19
20
|
suffixIcon?: LucideIcon;
|
|
21
|
+
unstyled?: boolean;
|
|
20
22
|
} & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type VariantProps } from 'class-variance-authority';
|
|
2
2
|
import { ComponentProps } from 'react';
|
|
3
3
|
import { Tooltip } from '../Tooltip';
|
|
4
|
+
export declare const SIDEBAR_COOKIE_NAME = "sidebar:state";
|
|
5
|
+
export declare const SIDEBAR_COOKIE_MAX_AGE: number;
|
|
6
|
+
export declare const SIDEBAR_WIDTH = "16rem";
|
|
7
|
+
export declare const SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
8
|
+
export declare const SIDEBAR_WIDTH_ICON = "3rem";
|
|
9
|
+
export declare const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
4
10
|
export type SidebarContext = {
|
|
5
11
|
state: 'expanded' | 'collapsed';
|
|
6
12
|
open: boolean;
|
|
@@ -81,5 +87,6 @@ export declare const Sidebar: import("react").ForwardRefExoticComponent<Omit<imp
|
|
|
81
87
|
rounded?: boolean;
|
|
82
88
|
prefixIcon?: import("lucide-react").LucideIcon;
|
|
83
89
|
suffixIcon?: import("lucide-react").LucideIcon;
|
|
90
|
+
unstyled?: boolean;
|
|
84
91
|
} & import("react").RefAttributes<HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
85
92
|
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
export type ThemeState = 'dark' | 'light' | 'system';
|
|
2
3
|
export type LayoutContext = {
|
|
3
4
|
theme: ThemeState;
|
|
4
|
-
|
|
5
|
+
resolvedTheme: Exclude<ThemeState, 'system'>;
|
|
6
|
+
setTheme: (theme: ThemeState) => void;
|
|
5
7
|
};
|
|
6
8
|
export declare const LayoutContext: import("react").Context<LayoutContext | undefined>;
|
|
9
|
+
export declare const THEME_MEDIA_QUERY = "(prefers-color-scheme: dark)";
|
|
10
|
+
export declare const THEME_COOKIE_NAME = "theme:state";
|
|
11
|
+
export declare const THEME_COOKIE_MAX_AGE: number;
|
|
7
12
|
export declare const LayoutContextProvider: FC<PropsWithChildren>;
|
|
8
13
|
export declare function useLayoutContext(): LayoutContext;
|
|
9
|
-
export type ThemeState = 'dark' | 'light';
|
|
10
|
-
export declare const THEME_KEY = "tw-react-components__theme";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getValueFromCookie<T extends string | boolean>(key: string, _default: T): T;
|
package/src/helpers/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './cn';
|
|
|
2
2
|
export * from './compareDates';
|
|
3
3
|
export * from './generalComparator';
|
|
4
4
|
export * from './getDisplayDate';
|
|
5
|
+
export * from './getValueFromCookie';
|
|
5
6
|
export * from './isEmpty';
|
|
6
7
|
export * from './mergeRefs';
|
|
7
8
|
export * from './resolveTargetObject';
|