@douglasneuroinformatics/libui 2.0.0-beta.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,6 +40,20 @@ designed as a generic implementation.
40
40
  pnpm install @douglasneuroinformatics/libui
41
41
  ```
42
42
 
43
+ ## Usage
44
+
45
+ **tailwind.config.cjs**
46
+
47
+ ```javascript
48
+ const baseConfig = require('@douglasneuroinformatics/libui/tailwind.config.cjs');
49
+
50
+ /** @type {import('tailwindcss').Config} */
51
+ module.exports {
52
+ content: [...baseConfig.content, './src/**/*.{js,ts,jsx,tsx}'],
53
+ presets: [baseConfig]
54
+ };
55
+ ```
56
+
43
57
  ## Contributing
44
58
 
45
59
  We welcome contributions! If you're interested in improving the library or adding new features, please refer to our contribution guide.
@@ -869,8 +869,10 @@ type LanguageToggleProps = {
869
869
  options: {
870
870
  [key: string]: string;
871
871
  };
872
+ triggerClassName?: string;
873
+ variant?: ButtonProps['variant'];
872
874
  };
873
- declare const LanguageToggle: ({ align, options }?: LanguageToggleProps) => react_jsx_runtime.JSX.Element;
875
+ declare const LanguageToggle: ({ align, options, triggerClassName, variant }: LanguageToggleProps) => react_jsx_runtime.JSX.Element;
874
876
 
875
877
  type LegacyDropdownOptions = {
876
878
  [key: string]: string;
@@ -1930,17 +1932,26 @@ declare const Resizable: ResizableType;
1930
1932
 
1931
1933
  declare const ScrollArea: react__default.ForwardRefExoticComponent<Omit<_radix_ui_react_scroll_area.ScrollAreaProps & react__default.RefAttributes<HTMLDivElement>, "ref"> & react__default.RefAttributes<HTMLDivElement>>;
1932
1934
 
1933
- type SearchBarProps = {
1935
+ type BaseSearchBarProps = {
1934
1936
  /** Additional CSS classes to add to the wrapper form component, potentially overriding default styling */
1935
1937
  className?: string;
1936
- /** Event handler called when the value changes */
1937
- onValueChange: (value: string) => void;
1938
+ /** An optional callback invoked when the user clicks the search bar */
1939
+ onClick?: () => void;
1938
1940
  /** Custom placeholder to use instead of the default */
1939
1941
  placeholder?: string;
1942
+ };
1943
+ type ControlledSearchBarProps = BaseSearchBarProps & {
1944
+ /** Event handler called when the value changes */
1945
+ onValueChange: (value: string) => void;
1940
1946
  /** The controlled value of the search bar, which should be used in conjunction with onValueChange */
1941
1947
  value: string;
1942
1948
  };
1943
- declare const SearchBar: ({ className, onValueChange, placeholder, value }: SearchBarProps) => react_jsx_runtime.JSX.Element;
1949
+ type UncontrolledSearchBarProps = BaseSearchBarProps & {
1950
+ onValueChange?: never;
1951
+ value?: never;
1952
+ };
1953
+ type SearchBarProps = ControlledSearchBarProps | UncontrolledSearchBarProps;
1954
+ declare const SearchBar: ({ className, onClick, onValueChange, placeholder, value }: SearchBarProps) => react_jsx_runtime.JSX.Element;
1944
1955
 
1945
1956
  declare const Select: react.FC<SelectPrimitive.SelectProps> & {
1946
1957
  Content: react.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
@@ -1997,10 +2008,8 @@ declare const Tabs: react.ForwardRefExoticComponent<TabsPrimitive.TabsProps & re
1997
2008
  type TextAreaProps = react__default.TextareaHTMLAttributes<HTMLTextAreaElement>;
1998
2009
  declare const TextArea: react__default.ForwardRefExoticComponent<TextAreaProps & react__default.RefAttributes<HTMLTextAreaElement>>;
1999
2010
 
2000
- type ThemeToggleProps = {
2001
- align?: 'center' | 'end' | 'start';
2002
- };
2003
- declare const ThemeToggle: () => react_jsx_runtime.JSX.Element;
2011
+ type ThemeToggleProps = Omit<ButtonProps, 'children' | 'size'>;
2012
+ declare const ThemeToggle: ({ onClick, variant, ...props }: ThemeToggleProps) => react_jsx_runtime.JSX.Element;
2004
2013
 
2005
2014
  type TooltipTriggerProps = Omit<ButtonProps, 'asChild'>;
2006
2015
 
@@ -2031,4 +2040,4 @@ declare const Tooltip: (({ children, delayDuration, skipDelayDuration }: Tooltip
2031
2040
  Trigger: react.ForwardRefExoticComponent<TooltipTriggerProps & react.RefAttributes<HTMLButtonElement>>;
2032
2041
  };
2033
2042
 
2034
- export { Accordion, AlertDialog, ArrowToggle, type ArrowToggleProps, Avatar, BUTTON_ICON_SIZE, Badge, type BadgeProps, Breadcrumb, Button, type ButtonProps, Card, Checkbox, Collapsible, Command, ContextMenu, DatePicker, type DatePickerProps, Dialog, Drawer, DropdownButton, DropdownMenu, ErrorBoundary, ErrorFallback, type ErrorFallbackProps, Form, type FormProps, Heading, type HeadingProps, HoverCard, Input, type InputProps, Label, LanguageToggle, type LanguageToggleProps, LegacyClientTable, LegacyDropdown, type LegacyDropdownProps, type LegacyFieldFactory, LegacyModal, type LegacyModalProps, LegacySelectDropdown, type LegacySelectDropdownProps, type LegacySelectOption, LegacySlider, type LegacySliderProps, LegacyStepper, type LegacyStepperProps, LegacyTable, type LegacyTableColumn, type LegacyTableEntry, type LegacyTableProps, LineGraph, type LineGraphData, type LineGraphLine, MenuBar, NotificationHub, type NotificationHubProps, Pagination, Popover, Progress, RadioGroup, type RadioGroupProps, Resizable, ScrollArea, SearchBar, type SearchBarProps, Select, Separator, Sheet, Slider, Spinner, SpinnerIcon, type Step, Switch, Table, Tabs, TextArea, type TextAreaProps, ThemeToggle, type ThemeToggleProps, Tooltip, badgeVariants, buttonVariants, labelVariants };
2043
+ export { Accordion, AlertDialog, ArrowToggle, type ArrowToggleProps, Avatar, BUTTON_ICON_SIZE, Badge, type BadgeProps, type BaseSearchBarProps, Breadcrumb, Button, type ButtonProps, Card, Checkbox, Collapsible, Command, ContextMenu, DatePicker, type DatePickerProps, Dialog, Drawer, DropdownButton, DropdownMenu, ErrorBoundary, ErrorFallback, type ErrorFallbackProps, Form, type FormProps, Heading, type HeadingProps, HoverCard, Input, type InputProps, Label, LanguageToggle, type LanguageToggleProps, LegacyClientTable, LegacyDropdown, type LegacyDropdownProps, type LegacyFieldFactory, LegacyModal, type LegacyModalProps, LegacySelectDropdown, type LegacySelectDropdownProps, type LegacySelectOption, LegacySlider, type LegacySliderProps, LegacyStepper, type LegacyStepperProps, LegacyTable, type LegacyTableColumn, type LegacyTableEntry, type LegacyTableProps, LineGraph, type LineGraphData, type LineGraphLine, MenuBar, NotificationHub, type NotificationHubProps, Pagination, Popover, Progress, RadioGroup, type RadioGroupProps, Resizable, ScrollArea, SearchBar, type SearchBarProps, Select, Separator, Sheet, Slider, Spinner, SpinnerIcon, type Step, Switch, Table, Tabs, TextArea, type TextAreaProps, ThemeToggle, type ThemeToggleProps, Tooltip, badgeVariants, buttonVariants, labelVariants };
@@ -1737,7 +1737,7 @@ var NumberRecordField = ({
1737
1737
  }
1738
1738
  return /* @__PURE__ */ jsxs25("div", { className: "space-y-4", children: [
1739
1739
  /* @__PURE__ */ jsx89(Heading, { variant: "h5", children: label }),
1740
- /* @__PURE__ */ jsx89("div", { className: "space-y-8", children: Object.keys(items).map((name) => {
1740
+ /* @__PURE__ */ jsx89("div", { className: "space-y-6", children: Object.keys(items).map((name) => {
1741
1741
  const item = items[name];
1742
1742
  return /* @__PURE__ */ jsx89(
1743
1743
  NumberField,
@@ -2306,7 +2306,7 @@ var RecordArrayField = memo(function RecordArrayField2({
2306
2306
  setValue: setArrayValue,
2307
2307
  value: arrayValue
2308
2308
  }) {
2309
- const { t } = useTranslation4();
2309
+ const { t } = useTranslation4("libui");
2310
2310
  const createNewRecord = () => Object.fromEntries(Object.keys(fieldset).map((fieldName) => [fieldName, void 0]));
2311
2311
  useEffect6(() => {
2312
2312
  setArrayValue([createNewRecord()]);
@@ -2324,7 +2324,7 @@ var RecordArrayField = memo(function RecordArrayField2({
2324
2324
  };
2325
2325
  return /* @__PURE__ */ jsxs38("div", { className: "space-y-4", children: [
2326
2326
  /* @__PURE__ */ jsx113(Heading, { variant: "h5", children: label }),
2327
- /* @__PURE__ */ jsx113("div", { className: "space-y-8", children: arrayValue.map((fields, i) => /* @__PURE__ */ jsxs38("div", { className: "space-y-4", children: [
2327
+ /* @__PURE__ */ jsx113("div", { className: "space-y-6", children: arrayValue.map((fields, i) => /* @__PURE__ */ jsxs38("div", { className: "space-y-4", children: [
2328
2328
  /* @__PURE__ */ jsx113(Label3, { className: "font-semibold italic", children: label + " " + (i + 1) }),
2329
2329
  Object.keys(fields).map((name) => {
2330
2330
  const field = fieldset[name];
@@ -2493,7 +2493,7 @@ var Form = ({
2493
2493
  validationSchema,
2494
2494
  ...props
2495
2495
  }) => {
2496
- const { t } = useTranslation5();
2496
+ const { t } = useTranslation5("libui");
2497
2497
  const [rootError, setRootError] = useState5(null);
2498
2498
  const [errors, setErrors] = useState5({});
2499
2499
  const [values, setValues] = useState5(
@@ -2536,16 +2536,16 @@ var Form = ({
2536
2536
  "form",
2537
2537
  {
2538
2538
  autoComplete: "off",
2539
- className: twMerge("my-8 w-full", isGrouped ? "space-y-8 divide-y" : "space-y-8", className),
2539
+ className: twMerge("w-full", isGrouped ? "space-y-8 divide-y" : "space-y-6", className),
2540
2540
  id,
2541
2541
  onSubmit: handleSubmit,
2542
2542
  ...props,
2543
2543
  children: [
2544
2544
  isGrouped ? content.map((fieldGroup, i) => {
2545
- return /* @__PURE__ */ jsxs39("div", { className: "space-y-8 [&:not(:first-child)]:pt-8", children: [
2546
- /* @__PURE__ */ jsxs39("div", { children: [
2545
+ return /* @__PURE__ */ jsxs39("div", { className: "space-y-6 [&:not(:first-child)]:pt-8", children: [
2546
+ /* @__PURE__ */ jsxs39("div", { className: "space-y-1", children: [
2547
2547
  /* @__PURE__ */ jsx116(Heading, { variant: "h4", children: fieldGroup.title }),
2548
- fieldGroup.description && /* @__PURE__ */ jsx116("small", { className: "text-sm italic text-muted-foreground", children: fieldGroup.description })
2548
+ fieldGroup.description && /* @__PURE__ */ jsx116("p", { className: "text-sm italic leading-tight text-muted-foreground", children: fieldGroup.description })
2549
2549
  ] }),
2550
2550
  /* @__PURE__ */ jsx116(
2551
2551
  FieldsComponent,
@@ -2612,10 +2612,15 @@ var HoverCard = Object.assign(Root14, {
2612
2612
  import { LanguagesIcon } from "lucide-react";
2613
2613
  import { useTranslation as useTranslation6 } from "react-i18next";
2614
2614
  import { jsx as jsx118, jsxs as jsxs40 } from "react/jsx-runtime";
2615
- var LanguageToggle = ({ align, options } = { align: "start", options: {} }) => {
2616
- const { i18n } = useTranslation6();
2615
+ var LanguageToggle = ({
2616
+ align = "start",
2617
+ options = {},
2618
+ triggerClassName,
2619
+ variant = "outline"
2620
+ }) => {
2621
+ const { i18n } = useTranslation6("libui");
2617
2622
  return /* @__PURE__ */ jsxs40(DropdownMenu, { children: [
2618
- /* @__PURE__ */ jsx118(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx118(Button, { size: "icon", variant: "outline", children: /* @__PURE__ */ jsx118(LanguagesIcon, {}) }) }),
2623
+ /* @__PURE__ */ jsx118(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx118(Button, { className: triggerClassName, size: "icon", variant, children: /* @__PURE__ */ jsx118(LanguagesIcon, {}) }) }),
2619
2624
  /* @__PURE__ */ jsx118(DropdownMenu.Content, { align, children: Object.keys(options).map((option) => /* @__PURE__ */ jsx118(DropdownMenu.Item, { onClick: () => void i18n.changeLanguage(option), children: options[option] }, option)) })
2620
2625
  ] });
2621
2626
  };
@@ -3051,7 +3056,7 @@ import { jsx as jsx126, jsxs as jsxs48 } from "react/jsx-runtime";
3051
3056
  var LegacyClientTable = ({ data, ...props }) => {
3052
3057
  const [currentPage, setCurrentPage] = useState7(1);
3053
3058
  const [entriesPerPage] = useState7(10);
3054
- const { t } = useTranslation7();
3059
+ const { t } = useTranslation7("libui");
3055
3060
  const pageCount = Math.ceil(data.length / entriesPerPage);
3056
3061
  const firstEntry = data.length === 0 ? 0 : (currentPage - 1) * entriesPerPage + 1;
3057
3062
  const lastEntry = Math.min(firstEntry + entriesPerPage - 1, data.length);
@@ -3059,7 +3064,7 @@ var LegacyClientTable = ({ data, ...props }) => {
3059
3064
  return /* @__PURE__ */ jsxs48("div", { children: [
3060
3065
  /* @__PURE__ */ jsx126(LegacyTable, { data: currentEntries, ...props }),
3061
3066
  /* @__PURE__ */ jsxs48("div", { className: "flex items-center justify-between px-1 py-3", children: [
3062
- /* @__PURE__ */ jsx126("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsx126("p", { className: "text-sm font-medium text-muted-foreground", children: t("table.pagination.info", {
3067
+ /* @__PURE__ */ jsx126("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsx126("p", { className: "text-sm font-medium text-muted-foreground", children: t("pagination.info", {
3063
3068
  first: firstEntry,
3064
3069
  last: lastEntry,
3065
3070
  total: data.length
@@ -3073,7 +3078,7 @@ var LegacyClientTable = ({ data, ...props }) => {
3073
3078
  onClick: () => {
3074
3079
  setCurrentPage(currentPage - 1);
3075
3080
  },
3076
- children: t("table.pagination.previous")
3081
+ children: t("pagination.previous")
3077
3082
  }
3078
3083
  ),
3079
3084
  /* @__PURE__ */ jsx126(
@@ -3084,7 +3089,7 @@ var LegacyClientTable = ({ data, ...props }) => {
3084
3089
  onClick: () => {
3085
3090
  setCurrentPage(currentPage + 1);
3086
3091
  },
3087
- children: t("table.pagination.next")
3092
+ children: t("pagination.next")
3088
3093
  }
3089
3094
  )
3090
3095
  ] })
@@ -3135,7 +3140,7 @@ function LineGraphComponent({
3135
3140
  lines,
3136
3141
  xAxis
3137
3142
  }) {
3138
- const { i18n } = useTranslation8();
3143
+ const { i18n } = useTranslation8("libui");
3139
3144
  const [theme] = useTheme();
3140
3145
  return /* @__PURE__ */ jsx127(ResponsiveContainer, { height: 400, width: "100%", children: /* @__PURE__ */ jsxs49(LineChart, { data: [...data], margin: { bottom: 5, left: 15, right: 15, top: 5 }, children: [
3141
3146
  /* @__PURE__ */ jsx127(CartesianGrid, { stroke: "#64748b", strokeDasharray: "5 5" }),
@@ -3432,7 +3437,7 @@ var NotificationIcon = ({ type }) => {
3432
3437
  // src/components/NotificationHub/NotificationHub.tsx
3433
3438
  import { jsx as jsx140, jsxs as jsxs53 } from "react/jsx-runtime";
3434
3439
  var NotificationHub = ({ timeout = 5e3 }) => {
3435
- const { t } = useTranslation9();
3440
+ const { t } = useTranslation9("libui");
3436
3441
  const { dismissNotification, notifications } = useNotificationsStore();
3437
3442
  return /* @__PURE__ */ jsx140("div", { className: "fixed bottom-0 z-50 w-full print:hidden", children: /* @__PURE__ */ jsx140(AnimatePresence3, { children: notifications.map((item) => /* @__PURE__ */ jsx140(
3438
3443
  motion3.div,
@@ -3630,8 +3635,8 @@ var Resizable = Object.assign(ResizableRoot, {
3630
3635
  import { SearchIcon as SearchIcon2 } from "lucide-react";
3631
3636
  import { useTranslation as useTranslation12 } from "react-i18next";
3632
3637
  import { jsx as jsx152, jsxs as jsxs57 } from "react/jsx-runtime";
3633
- var SearchBar = ({ className, onValueChange, placeholder, value }) => {
3634
- const { t } = useTranslation12();
3638
+ var SearchBar = ({ className, onClick, onValueChange, placeholder, value }) => {
3639
+ const { t } = useTranslation12("libui");
3635
3640
  return /* @__PURE__ */ jsxs57("form", { className: cn("relative", className), children: [
3636
3641
  /* @__PURE__ */ jsx152(SearchIcon2, { className: "absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" }),
3637
3642
  /* @__PURE__ */ jsx152(
@@ -3643,7 +3648,8 @@ var SearchBar = ({ className, onValueChange, placeholder, value }) => {
3643
3648
  value,
3644
3649
  onChange: (event) => {
3645
3650
  onValueChange?.(event.target.value);
3646
- }
3651
+ },
3652
+ onClick: () => onClick?.()
3647
3653
  }
3648
3654
  )
3649
3655
  ] });
@@ -4003,15 +4009,27 @@ var Tabs = Object.assign(TabsPrimitive4.Root, {
4003
4009
  // src/components/ThemeToggle/ThemeToggle.tsx
4004
4010
  import { MoonIcon, SunIcon } from "lucide-react";
4005
4011
  import { jsx as jsx174, jsxs as jsxs59 } from "react/jsx-runtime";
4006
- var ThemeToggle = () => {
4012
+ var ThemeToggle = ({ onClick, variant = "outline", ...props }) => {
4007
4013
  const [theme, setTheme] = useTheme();
4008
4014
  const toggleTheme = () => {
4009
4015
  setTheme(theme === "dark" ? "light" : "dark");
4010
4016
  };
4011
- return /* @__PURE__ */ jsxs59(Button, { size: "icon", variant: "outline", onClick: toggleTheme, children: [
4012
- /* @__PURE__ */ jsx174(SunIcon, { className: "rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
4013
- /* @__PURE__ */ jsx174(MoonIcon, { className: "absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
4014
- ] });
4017
+ return /* @__PURE__ */ jsxs59(
4018
+ Button,
4019
+ {
4020
+ size: "icon",
4021
+ variant,
4022
+ onClick: (event) => {
4023
+ toggleTheme();
4024
+ onClick?.(event);
4025
+ },
4026
+ ...props,
4027
+ children: [
4028
+ /* @__PURE__ */ jsx174(SunIcon, { className: "rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
4029
+ /* @__PURE__ */ jsx174(MoonIcon, { className: "absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
4030
+ ]
4031
+ }
4032
+ );
4015
4033
  };
4016
4034
 
4017
4035
  // src/components/Tooltip/TooltipContent.tsx