@mbao01/common 0.0.21 → 0.0.23

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.
Files changed (31) hide show
  1. package/dist/types/components/Slot/Slot.d.ts +1 -0
  2. package/dist/types/components/Slot/index.d.ts +1 -0
  3. package/dist/types/components/Sonner/Toaster.d.ts +1 -1
  4. package/dist/types/components/Sonner/constants.d.ts +4 -0
  5. package/dist/types/components/Sonner/types.d.ts +6 -2
  6. package/dist/types/components/Table/Table.d.ts +14 -0
  7. package/dist/types/components/Table/constants.d.ts +8 -0
  8. package/dist/types/components/Table/index.d.ts +1 -0
  9. package/dist/types/components/Table/types.d.ts +11 -0
  10. package/dist/types/components/ThemeSwitch/ThemeSwitch.d.ts +2 -0
  11. package/dist/types/components/ThemeSwitch/constants.d.ts +1 -0
  12. package/dist/types/components/ThemeSwitch/index.d.ts +1 -0
  13. package/dist/types/components/ThemeSwitch/types.d.ts +10 -0
  14. package/dist/types/index.d.ts +3 -0
  15. package/dist/types/utilities/theme.d.ts +1 -2
  16. package/package.json +2 -2
  17. package/src/components/Slot/Slot.tsx +1 -0
  18. package/src/components/Slot/index.ts +1 -0
  19. package/src/components/Sonner/Toaster.tsx +17 -11
  20. package/src/components/Sonner/constants.ts +105 -37
  21. package/src/components/Sonner/types.ts +14 -3
  22. package/src/components/Table/Table.tsx +85 -0
  23. package/src/components/Table/constants.ts +27 -0
  24. package/src/components/Table/index.ts +1 -0
  25. package/src/components/Table/types.ts +19 -0
  26. package/src/components/ThemeSwitch/ThemeSwitch.tsx +68 -0
  27. package/src/components/ThemeSwitch/constants.ts +3 -0
  28. package/src/components/ThemeSwitch/index.ts +1 -0
  29. package/src/components/ThemeSwitch/types.ts +10 -0
  30. package/src/index.ts +3 -0
  31. package/src/utilities/theme.ts +3 -5
@@ -0,0 +1 @@
1
+ export { Slot } from "@radix-ui/react-slot";
@@ -0,0 +1 @@
1
+ export { Slot } from "./Slot";
@@ -1,2 +1,2 @@
1
1
  import { type ToasterProps } from "./types";
2
- export declare const Toaster: ({ theme, variant, outline, className, ...props }: ToasterProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const Toaster: ({ theme, variant, actionButton, cancelButton, closeButton, showCloseButton, outline, ...props }: ToasterProps) => import("react/jsx-runtime").JSX.Element;
@@ -2,3 +2,7 @@ export declare const getToastClasses: (props?: ({
2
2
  variant?: "accent" | "default" | "error" | "ghost" | "info" | "neutral" | "primary" | "secondary" | "success" | "warning" | null | undefined;
3
3
  outline?: boolean | null | undefined;
4
4
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ export declare const getToastButtonClasses: (props?: ({
6
+ variant?: "accent" | "error" | "info" | "neutral" | "primary" | "secondary" | "success" | "warning" | "base" | null | undefined;
7
+ outline?: boolean | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -1,5 +1,9 @@
1
1
  /// <reference types="react" />
2
2
  import { Toaster } from "sonner";
3
3
  import { type VariantProps } from "../../libs";
4
- import { getToastClasses } from "./constants";
5
- export type ToasterProps = React.ComponentProps<typeof Toaster> & VariantProps<typeof getToastClasses>;
4
+ import { getToastButtonClasses, getToastClasses } from "./constants";
5
+ type ToastButtonVariantProps = VariantProps<typeof getToastButtonClasses>;
6
+ export type ToasterProps = Omit<React.ComponentProps<typeof Toaster>, "closeButton"> & VariantProps<typeof getToastClasses> & Partial<Record<"actionButton" | "cancelButton" | "closeButton", ToastButtonVariantProps>> & {
7
+ showCloseButton?: boolean;
8
+ };
9
+ export {};
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ import type { TableBodyProps, TableCaptionProps, TableCellProps, TableFooterProps, TableHeadProps, TableHeaderProps, TableProps, TableRowProps } from "./types";
3
+ declare const Table: {
4
+ ({ className, caption, zebra, size, pinRow, pinColumn, ...props }: TableProps): import("react/jsx-runtime").JSX.Element;
5
+ displayName: string;
6
+ Header: import("react").ForwardRefExoticComponent<TableHeaderProps & import("react").RefAttributes<HTMLTableSectionElement>>;
7
+ Body: import("react").ForwardRefExoticComponent<TableBodyProps & import("react").RefAttributes<HTMLTableSectionElement>>;
8
+ Footer: import("react").ForwardRefExoticComponent<TableFooterProps & import("react").RefAttributes<HTMLTableSectionElement>>;
9
+ Head: import("react").ForwardRefExoticComponent<TableHeadProps & import("react").RefAttributes<HTMLTableCellElement>>;
10
+ Row: import("react").ForwardRefExoticComponent<TableRowProps & import("react").RefAttributes<HTMLTableRowElement>>;
11
+ Cell: import("react").ForwardRefExoticComponent<TableCellProps & import("react").RefAttributes<HTMLTableCellElement>>;
12
+ Caption: import("react").ForwardRefExoticComponent<TableCaptionProps & import("react").RefAttributes<HTMLTableCaptionElement>>;
13
+ };
14
+ export { Table };
@@ -0,0 +1,8 @@
1
+ export declare const getTableClasses: (props?: ({
2
+ caption?: "top" | "bottom" | null | undefined;
3
+ zebra?: boolean | null | undefined;
4
+ pinRow?: boolean | null | undefined;
5
+ pinColumn?: boolean | null | undefined;
6
+ size?: "xs" | "sm" | "md" | "lg" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ export declare const getTableHeaderClasses: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
@@ -0,0 +1 @@
1
+ export { Table } from "./Table";
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ import { VariantProps } from "../../libs";
3
+ import { getTableClasses } from "./constants";
4
+ export type TableProps = React.HTMLAttributes<HTMLTableElement> & VariantProps<typeof getTableClasses>;
5
+ export type TableHeaderProps = React.HTMLAttributes<HTMLTableSectionElement>;
6
+ export type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;
7
+ export type TableFooterProps = React.HTMLAttributes<HTMLTableSectionElement>;
8
+ export type TableRowProps = React.HTMLAttributes<HTMLTableRowElement>;
9
+ export type TableHeadProps = React.ThHTMLAttributes<HTMLTableCellElement>;
10
+ export type TableCellProps = React.TdHTMLAttributes<HTMLTableCellElement>;
11
+ export type TableCaptionProps = React.HTMLAttributes<HTMLTableCaptionElement>;
@@ -0,0 +1,2 @@
1
+ import { type ThemeSwitchProps } from "./types";
2
+ export declare const ThemeSwitch: ({ name, render, className, theme: defaultTheme, ...props }: ThemeSwitchProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const getThemeSwitchClasses: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
@@ -0,0 +1 @@
1
+ export { ThemeSwitch } from "./ThemeSwitch";
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { type Theme } from "../../utilities";
3
+ export type ThemeSwitchProps = React.ComponentPropsWithoutRef<"label"> & {
4
+ name?: string;
5
+ theme?: Theme;
6
+ render?: (params: {
7
+ theme: Theme | null;
8
+ setTheme: React.Dispatch<React.SetStateAction<Theme | null>>;
9
+ }) => JSX.Element;
10
+ };
@@ -3,6 +3,7 @@ export * from "./components/Button";
3
3
  export * from "./components/Breadcrumbs";
4
4
  export * from "./components/Menu";
5
5
  export * from "./components/Pagination";
6
+ export * from "./components/ThemeSwitch";
6
7
  export * from "./components/Toggle";
7
8
  export * from "./components/ToggleGroup";
8
9
  /** data display */
@@ -18,6 +19,7 @@ export * from "./components/Progress";
18
19
  export * from "./components/ScrollArea";
19
20
  export * from "./components/Separator";
20
21
  export * from "./components/Sonner";
22
+ export * from "./components/Table";
21
23
  export * from "./components/Tabs";
22
24
  export * from "./components/Text";
23
25
  /** data input */
@@ -34,3 +36,4 @@ export * from "./components/Command";
34
36
  export * from "./components/Dialog";
35
37
  export * from "./components/HoverCard";
36
38
  export * from "./components/Popover";
39
+ export * from "./components/Slot";
@@ -1,4 +1,3 @@
1
- type Theme = "dark" | "light" | "system";
1
+ export type Theme = "dark" | "light";
2
2
  export declare const getTheme: () => Theme | null;
3
3
  export declare const saveTheme: (theme: Theme) => void;
4
- export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mbao01/common",
3
3
  "private": false,
4
- "version": "0.0.21",
4
+ "version": "0.0.23",
5
5
  "type": "module",
6
6
  "author": "Ayomide Bakare",
7
7
  "license": "MIT",
@@ -142,5 +142,5 @@
142
142
  "react-dom": "^18.2.0",
143
143
  "typescript": "^5.2.2"
144
144
  },
145
- "gitHead": "413c452e832fd947234ffac4d61aaa3dd20c7a0f"
145
+ "gitHead": "ba76159ca3d5d96cbdcbc04b7dbd545f071027b6"
146
146
  }
@@ -0,0 +1 @@
1
+ export { Slot } from "@radix-ui/react-slot";
@@ -0,0 +1 @@
1
+ export { Slot } from "./Slot";
@@ -3,30 +3,36 @@
3
3
  import { Toaster as Sonner } from "sonner";
4
4
  import { type ToasterProps } from "./types";
5
5
  import { cn } from "../../utilities";
6
- import { getToastClasses } from "./constants";
6
+ import { getToastButtonClasses, getToastClasses } from "./constants";
7
7
 
8
8
  export const Toaster = ({
9
9
  theme,
10
10
  variant,
11
+ actionButton,
12
+ cancelButton,
13
+ closeButton,
14
+ showCloseButton,
11
15
  outline,
12
- className,
13
16
  ...props
14
17
  }: ToasterProps) => {
15
18
  return (
16
19
  <Sonner
17
20
  theme={theme}
18
- className={cn("toaster group", className)}
21
+ closeButton={showCloseButton}
19
22
  toastOptions={{
20
23
  classNames: {
21
- toast: cn(
22
- "group sonn group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
23
- getToastClasses({ variant, outline })
24
+ toast: cn(getToastClasses({ variant, outline })),
25
+ actionButton: cn(getToastButtonClasses(actionButton)),
26
+ cancelButton: cn(
27
+ getToastButtonClasses({
28
+ outline: true,
29
+ variant: "base",
30
+ ...cancelButton,
31
+ })
32
+ ),
33
+ closeButton: cn(
34
+ getToastButtonClasses({ variant: "neutral", ...closeButton })
24
35
  ),
25
- description: "group-[.sonn]:text-muted-foreground",
26
- actionButton:
27
- "group-[.sonn]:bg-primary group-[.sonn]:text-primary-foreground",
28
- cancelButton:
29
- "group-[.sonn]:bg-muted group-[.sonn]:text-muted-foreground",
30
36
  },
31
37
  }}
32
38
  {...props}
@@ -1,39 +1,107 @@
1
1
  import { cva } from "../../libs";
2
2
 
3
- export const getToastClasses = cva(
4
- "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-inherit",
5
- {
6
- variants: {
7
- variant: {
8
- accent: "bg-accent text-accent-content border-accent",
9
- default: "bg-default text-default-content border-default",
10
- error: "bg-error text-error-content border-error",
11
- ghost: "bg-ghost text-ghost-content border-transparent",
12
- info: "bg-info text-info-content border-info",
13
- neutral: "bg-neutral text-neutral-content border-neutral",
14
- primary: "bg-primary text-primary-content border-primary",
15
- secondary: "bg-secondary text-secondary-content border-secondary",
16
- success: "bg-success text-success-content border-success",
17
- warning: "bg-warning text-warning-content border-warning",
18
- },
19
- outline: {
20
- true: "border bg-default",
21
- },
22
- },
23
- compoundVariants: [
24
- { outline: true, variant: "accent", className: "text-accent" },
25
- { outline: true, variant: "default", className: "text-default" },
26
- { outline: true, variant: "error", className: "text-error" },
27
- { outline: true, variant: "ghost", className: "text-ghost" },
28
- { outline: true, variant: "info", className: "text-info" },
29
- { outline: true, variant: "neutral", className: "text-neutral" },
30
- { outline: true, variant: "primary", className: "text-primary" },
31
- { outline: true, variant: "secondary", className: "text-secondary" },
32
- { outline: true, variant: "success", className: "text-success" },
33
- { outline: true, variant: "warning", className: "text-warning" },
34
- ],
35
- defaultVariants: {
36
- variant: "default",
37
- },
38
- }
39
- );
3
+ export const getToastClasses = cva("sonner group", {
4
+ variants: {
5
+ variant: {
6
+ accent: "bg-accent text-accent-content border-accent",
7
+ default: "bg-default text-default-content border-default",
8
+ error: "bg-error text-error-content border-error",
9
+ ghost: "bg-ghost text-ghost-content border-transparent",
10
+ info: "bg-info text-info-content border-info",
11
+ neutral: "bg-neutral text-neutral-content border-neutral",
12
+ primary: "bg-primary text-primary-content border-primary",
13
+ secondary: "bg-secondary text-secondary-content border-secondary",
14
+ success: "bg-success text-success-content border-success",
15
+ warning: "bg-warning text-warning-content border-warning",
16
+ },
17
+ outline: {
18
+ true: "border bg-default",
19
+ },
20
+ },
21
+ compoundVariants: [
22
+ { outline: true, variant: "accent", className: "text-accent" },
23
+ { outline: true, variant: "default", className: "text-default" },
24
+ { outline: true, variant: "error", className: "text-error" },
25
+ { outline: true, variant: "ghost", className: "text-ghost" },
26
+ { outline: true, variant: "info", className: "text-info" },
27
+ { outline: true, variant: "neutral", className: "text-neutral" },
28
+ { outline: true, variant: "primary", className: "text-primary" },
29
+ { outline: true, variant: "secondary", className: "text-secondary" },
30
+ { outline: true, variant: "success", className: "text-success" },
31
+ { outline: true, variant: "warning", className: "text-warning" },
32
+ ],
33
+ defaultVariants: {
34
+ variant: "default",
35
+ },
36
+ });
37
+
38
+ export const getToastButtonClasses = cva("", {
39
+ variants: {
40
+ variant: {
41
+ base: "group-[.sonner]:!bg-base-300 group-[.sonner]:!text-base-content",
42
+ accent: "group-[.sonner]:!bg-accent group-[.sonner]:!text-accent-content",
43
+ error: "group-[.sonner]:!bg-error group-[.sonner]:!text-error-content",
44
+ info: "group-[.sonner]:!bg-info group-[.sonner]:!text-info-content",
45
+ neutral:
46
+ "group-[.sonner]:!bg-neutral group-[.sonner]:!text-neutral-content",
47
+ primary:
48
+ "group-[.sonner]:!bg-primary group-[.sonner]:!text-primary-content",
49
+ secondary:
50
+ "group-[.sonner]:!bg-secondary group-[.sonner]:!text-secondary-content",
51
+ success:
52
+ "group-[.sonner]:!bg-success group-[.sonner]:!text-success-content",
53
+ warning:
54
+ "group-[.sonner]:!bg-warning group-[.sonner]:!text-warning-content",
55
+ },
56
+ outline: {
57
+ true: "group-[.sonner]:!border group-[.sonner]:!border-solid group-[.sonner]:!bg-transparent",
58
+ },
59
+ },
60
+ compoundVariants: [
61
+ {
62
+ outline: true,
63
+ variant: "accent",
64
+ className: "group-[.sonner]:!border-accent group-[.sonner]:!text-accent",
65
+ },
66
+ {
67
+ outline: true,
68
+ variant: "error",
69
+ className: "group-[.sonner]:!border-error group-[.sonner]:!text-error",
70
+ },
71
+ {
72
+ outline: true,
73
+ variant: "info",
74
+ className: "group-[.sonner]:!text-info",
75
+ },
76
+ {
77
+ outline: true,
78
+ variant: "neutral",
79
+ className:
80
+ "group-[.sonner]:!border-neutral group-[.sonner]:!text-neutral",
81
+ },
82
+ {
83
+ outline: true,
84
+ variant: "primary",
85
+ className:
86
+ "group-[.sonner]:!border-primary group-[.sonner]:!text-primary",
87
+ },
88
+ {
89
+ outline: true,
90
+ variant: "secondary",
91
+ className:
92
+ "group-[.sonner]:!border-secondary group-[.sonner]:!text-secondary",
93
+ },
94
+ {
95
+ outline: true,
96
+ variant: "success",
97
+ className:
98
+ "group-[.sonner]:!border-success group-[.sonner]:!text-success",
99
+ },
100
+ {
101
+ outline: true,
102
+ variant: "warning",
103
+ className:
104
+ "group-[.sonner]:!border-warning group-[.sonner]:!text-warning",
105
+ },
106
+ ],
107
+ });
@@ -1,6 +1,17 @@
1
1
  import { Toaster } from "sonner";
2
2
  import { type VariantProps } from "../../libs";
3
- import { getToastClasses } from "./constants";
3
+ import { getToastButtonClasses, getToastClasses } from "./constants";
4
4
 
5
- export type ToasterProps = React.ComponentProps<typeof Toaster> &
6
- VariantProps<typeof getToastClasses>;
5
+ type ToastButtonVariantProps = VariantProps<typeof getToastButtonClasses>;
6
+
7
+ export type ToasterProps = Omit<
8
+ React.ComponentProps<typeof Toaster>,
9
+ "closeButton"
10
+ > &
11
+ VariantProps<typeof getToastClasses> &
12
+ Partial<
13
+ Record<
14
+ "actionButton" | "cancelButton" | "closeButton",
15
+ ToastButtonVariantProps
16
+ >
17
+ > & { showCloseButton?: boolean };
@@ -0,0 +1,85 @@
1
+ import { forwardRef } from "react";
2
+ import { cn } from "../../utilities";
3
+ import type {
4
+ TableBodyProps,
5
+ TableCaptionProps,
6
+ TableCellProps,
7
+ TableFooterProps,
8
+ TableHeadProps,
9
+ TableHeaderProps,
10
+ TableProps,
11
+ TableRowProps,
12
+ } from "./types";
13
+ import { getTableClasses, getTableHeaderClasses } from "./constants";
14
+
15
+ const Table = ({
16
+ className,
17
+ caption,
18
+ zebra,
19
+ size,
20
+ pinRow,
21
+ pinColumn,
22
+ ...props
23
+ }: TableProps) => (
24
+ <div className="relative w-full overflow-auto">
25
+ <table
26
+ className={cn(
27
+ getTableClasses({ caption, zebra, size, pinRow, pinColumn }),
28
+ className
29
+ )}
30
+ {...props}
31
+ />
32
+ </div>
33
+ );
34
+ Table.displayName = "Table";
35
+
36
+ const TableHeader = forwardRef<HTMLTableSectionElement, TableHeaderProps>(
37
+ ({ className, ...props }, ref) => (
38
+ <thead
39
+ ref={ref}
40
+ className={cn(getTableHeaderClasses(), className)}
41
+ {...props}
42
+ />
43
+ )
44
+ );
45
+ TableHeader.displayName = "TableHeader";
46
+
47
+ const TableBody = forwardRef<HTMLTableSectionElement, TableBodyProps>(
48
+ (props, ref) => <tbody ref={ref} {...props} />
49
+ );
50
+ TableBody.displayName = "TableBody";
51
+
52
+ const TableFooter = forwardRef<HTMLTableSectionElement, TableFooterProps>(
53
+ (props, ref) => <tfoot ref={ref} {...props} />
54
+ );
55
+ TableFooter.displayName = "TableFooter";
56
+
57
+ const TableRow = forwardRef<HTMLTableRowElement, TableRowProps>(
58
+ (props, ref) => <tr ref={ref} {...props} />
59
+ );
60
+ TableRow.displayName = "TableRow";
61
+
62
+ const TableHead = forwardRef<HTMLTableCellElement, TableHeadProps>(
63
+ (props, ref) => <th ref={ref} {...props} />
64
+ );
65
+ TableHead.displayName = "TableHead";
66
+
67
+ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(
68
+ (props, ref) => <td ref={ref} {...props} />
69
+ );
70
+ TableCell.displayName = "TableCell";
71
+
72
+ const TableCaption = forwardRef<HTMLTableCaptionElement, TableCaptionProps>(
73
+ (props, ref) => <caption ref={ref} {...props} />
74
+ );
75
+ TableCaption.displayName = "TableCaption";
76
+
77
+ Table.Header = TableHeader;
78
+ Table.Body = TableBody;
79
+ Table.Footer = TableFooter;
80
+ Table.Head = TableHead;
81
+ Table.Row = TableRow;
82
+ Table.Cell = TableCell;
83
+ Table.Caption = TableCaption;
84
+
85
+ export { Table };
@@ -0,0 +1,27 @@
1
+ import { cva } from "../../libs";
2
+
3
+ export const getTableClasses = cva("table", {
4
+ variants: {
5
+ caption: {
6
+ top: "caption-top",
7
+ bottom: "caption-bottom",
8
+ },
9
+ zebra: {
10
+ true: "table-zebra",
11
+ },
12
+ pinRow: {
13
+ true: "table-pin-rows",
14
+ },
15
+ pinColumn: {
16
+ true: "table-pin-cols",
17
+ },
18
+ size: {
19
+ xs: "table-xs",
20
+ sm: "table-sm",
21
+ md: "table-md",
22
+ lg: "table-lg",
23
+ },
24
+ },
25
+ });
26
+
27
+ export const getTableHeaderClasses = cva("[&_tr]:border-b");
@@ -0,0 +1 @@
1
+ export { Table } from "./Table";
@@ -0,0 +1,19 @@
1
+ import { VariantProps } from "../../libs";
2
+ import { getTableClasses } from "./constants";
3
+
4
+ export type TableProps = React.HTMLAttributes<HTMLTableElement> &
5
+ VariantProps<typeof getTableClasses>;
6
+
7
+ export type TableHeaderProps = React.HTMLAttributes<HTMLTableSectionElement>;
8
+
9
+ export type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;
10
+
11
+ export type TableFooterProps = React.HTMLAttributes<HTMLTableSectionElement>;
12
+
13
+ export type TableRowProps = React.HTMLAttributes<HTMLTableRowElement>;
14
+
15
+ export type TableHeadProps = React.ThHTMLAttributes<HTMLTableCellElement>;
16
+
17
+ export type TableCellProps = React.TdHTMLAttributes<HTMLTableCellElement>;
18
+
19
+ export type TableCaptionProps = React.HTMLAttributes<HTMLTableCaptionElement>;
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ import { type ChangeEvent, useLayoutEffect, useState } from "react";
4
+ import { type ThemeSwitchProps } from "./types";
5
+ import { cn, getTheme, saveTheme } from "../../utilities";
6
+ import { getThemeSwitchClasses } from "./constants";
7
+
8
+ const MoonIcon = ({ title }: { title: string }) => (
9
+ <svg
10
+ className="swap-on h-4 w-4 fill-current"
11
+ xmlns="http://www.w3.org/2000/svg"
12
+ viewBox="0 0 24 24"
13
+ >
14
+ {title && <title>{title}</title>}
15
+ <path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
16
+ </svg>
17
+ );
18
+
19
+ const SunIcon = ({ title }: { title: string }) => (
20
+ <svg
21
+ className="swap-off h-4 w-4 fill-current"
22
+ xmlns="http://www.w3.org/2000/svg"
23
+ viewBox="0 0 24 24"
24
+ xlinkTitle="sun-icon"
25
+ >
26
+ {title && <title>{title}</title>}
27
+ <path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
28
+ </svg>
29
+ );
30
+
31
+ export const ThemeSwitch = ({
32
+ name,
33
+ render,
34
+ className,
35
+ theme: defaultTheme,
36
+ ...props
37
+ }: ThemeSwitchProps) => {
38
+ const [theme, setTheme] = useState(defaultTheme ?? getTheme);
39
+
40
+ useLayoutEffect(() => {
41
+ if (theme) saveTheme(theme);
42
+ }, [theme]);
43
+
44
+ if (render) {
45
+ return render({ theme, setTheme });
46
+ }
47
+
48
+ const changeTheme = (e: ChangeEvent<HTMLInputElement>) => {
49
+ const t = e.target.checked ? "light" : "dark";
50
+ setTheme(t);
51
+ };
52
+
53
+ return (
54
+ <label className={cn(getThemeSwitchClasses(), className)} {...props}>
55
+ {/* this hidden checkbox controls the state */}
56
+ <input
57
+ hidden
58
+ name={name}
59
+ type="checkbox"
60
+ className="theme-controller"
61
+ checked={theme === "light"}
62
+ onChange={changeTheme}
63
+ />
64
+ <MoonIcon title="Switch to dark theme" />
65
+ <SunIcon title="Switch to light theme" />
66
+ </label>
67
+ );
68
+ };
@@ -0,0 +1,3 @@
1
+ import { cva } from "../../libs";
2
+
3
+ export const getThemeSwitchClasses = cva("swap swap-rotate");
@@ -0,0 +1 @@
1
+ export { ThemeSwitch } from "./ThemeSwitch";
@@ -0,0 +1,10 @@
1
+ import { type Theme } from "../../utilities";
2
+
3
+ export type ThemeSwitchProps = React.ComponentPropsWithoutRef<"label"> & {
4
+ name?: string;
5
+ theme?: Theme;
6
+ render?: (params: {
7
+ theme: Theme | null;
8
+ setTheme: React.Dispatch<React.SetStateAction<Theme | null>>;
9
+ }) => JSX.Element;
10
+ };
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./components/Button";
3
3
  export * from "./components/Breadcrumbs";
4
4
  export * from "./components/Menu";
5
5
  export * from "./components/Pagination";
6
+ export * from "./components/ThemeSwitch";
6
7
  export * from "./components/Toggle";
7
8
  export * from "./components/ToggleGroup";
8
9
 
@@ -19,6 +20,7 @@ export * from "./components/Progress";
19
20
  export * from "./components/ScrollArea";
20
21
  export * from "./components/Separator";
21
22
  export * from "./components/Sonner";
23
+ export * from "./components/Table";
22
24
  export * from "./components/Tabs";
23
25
  export * from "./components/Text";
24
26
 
@@ -38,3 +40,4 @@ export * from "./components/Command";
38
40
  export * from "./components/Dialog";
39
41
  export * from "./components/HoverCard";
40
42
  export * from "./components/Popover";
43
+ export * from "./components/Slot";
@@ -1,4 +1,4 @@
1
- type Theme = "dark" | "light" | "system";
1
+ export type Theme = "dark" | "light";
2
2
 
3
3
  export const getTheme = () => {
4
4
  if (typeof window === "undefined") return null;
@@ -7,13 +7,11 @@ export const getTheme = () => {
7
7
  if (!t)
8
8
  t = window.matchMedia("(prefers-color-scheme: dark)")?.matches
9
9
  ? "dark"
10
- : window.matchMedia("(prefers-color-scheme: light)")?.matches
11
- ? "light"
12
- : "system";
10
+ : "light";
13
11
  return t;
14
12
  };
15
13
 
16
14
  export const saveTheme = (theme: Theme) => {
17
15
  document.body.setAttribute("data-theme", theme);
18
- localStorage.setItem("__theme", theme);
16
+ window.localStorage.setItem("__theme", theme);
19
17
  };