@bouku/core 0.4.2 → 0.4.3

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 (33) hide show
  1. package/dist/assets/icons/trash.svg +6 -0
  2. package/dist/components/button/normal.d.ts +2 -2
  3. package/dist/components/button/normal.js +3 -2
  4. package/dist/components/container/flex.d.ts +5 -8
  5. package/dist/components/container/flex.js +0 -7
  6. package/dist/components/date/_.d.ts +1 -0
  7. package/dist/components/date/_.js +1 -0
  8. package/dist/components/date/date-picker.d.ts +38 -0
  9. package/dist/components/date/date-picker.js +52 -0
  10. package/dist/components/miscellaneous/checkbox/index.d.ts +3 -3
  11. package/dist/components/miscellaneous/checkbox/index.js +12 -18
  12. package/dist/components/miscellaneous/dropdown/multi-select.d.ts +4 -2
  13. package/dist/components/miscellaneous/dropdown/multi-select.js +4 -4
  14. package/dist/components/miscellaneous/dropdown/normal.d.ts +2 -1
  15. package/dist/components/miscellaneous/dropdown/normal.js +4 -4
  16. package/dist/components/miscellaneous/dropdown/select.d.ts +4 -2
  17. package/dist/components/miscellaneous/dropdown/select.js +3 -3
  18. package/dist/components/table/actions.js +1 -1
  19. package/dist/components/table/date-range.d.ts +8 -0
  20. package/dist/components/table/date-range.js +10 -0
  21. package/dist/components/table/filters.d.ts +10 -0
  22. package/dist/components/table/filters.js +32 -0
  23. package/dist/components/table/header.d.ts +5 -1
  24. package/dist/components/table/header.js +7 -4
  25. package/dist/components/table/index.d.ts +8 -2
  26. package/dist/components/table/index.js +44 -30
  27. package/dist/components/table/row.d.ts +3 -1
  28. package/dist/components/table/row.js +16 -7
  29. package/dist/components/table/search-bar.js +2 -1
  30. package/dist/components/table/state/filters.js +0 -1
  31. package/dist/components/table/state/sort.js +7 -3
  32. package/dist/components/table/utils/date.js +4 -3
  33. package/package.json +1 -1
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width="1em" height="1em">
2
+ <path
3
+ d="M232.7 69.9C237.1 56.8 249.3 48 263.1 48L377 48C390.8 48 403 56.8 407.4 69.9L416 96L512 96C529.7 96 544 110.3 544 128C544 145.7 529.7 160 512 160L128 160C110.3 160 96 145.7 96 128C96 110.3 110.3 96 128 96L224 96L232.7 69.9zM128 208L512 208L512 512C512 547.3 483.3 576 448 576L192 576C156.7 576 128 547.3 128 512L128 208zM216 272C202.7 272 192 282.7 192 296L192 488C192 501.3 202.7 512 216 512C229.3 512 240 501.3 240 488L240 296C240 282.7 229.3 272 216 272zM320 272C306.7 272 296 282.7 296 296L296 488C296 501.3 306.7 512 320 512C333.3 512 344 501.3 344 488L344 296C344 282.7 333.3 272 320 272zM424 272C410.7 272 400 282.7 400 296L400 488C400 501.3 410.7 512 424 512C437.3 512 448 501.3 448 488L448 296C448 282.7 437.3 272 424 272z"
4
+ fill="currentColor"
5
+ />
6
+ </svg>
@@ -1,6 +1,6 @@
1
- import { type Component } from "../../utils/index.js";
1
+ import type { Component } from "../../utils/types/element.js";
2
2
  export type ButtonProps = Component & {
3
- size?: "xs" | "sm" | "md" | "lg";
3
+ size?: "icon" | "xs" | "sm" | "md" | "lg";
4
4
  variant?: "surface" | "accent" | "outline" | "ghost" | "error";
5
5
  icon?: React.ReactNode;
6
6
  action?: () => void;
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
- import { cn } from "../../utils/index.js";
5
- import { tv } from "tailwind-variants";
6
4
  import Spinner from "../../assets/icons/spinner.svg";
5
+ import { cn } from "../../utils/functions/style.js";
6
+ import { tv } from "tailwind-variants";
7
7
  export function Button({ style, size = "md", variant = "surface", icon, action, oops = console.log, disabled, children }) {
8
8
  const [isLoading, setLoading] = useState(false);
9
9
  const handleClick = async () => {
@@ -28,6 +28,7 @@ const styles = tv({
28
28
  base: "relative flex justify-center items-center border outline-none rounded font-semibold shadow duration-200 cursor-pointer disabled:cursor-not-allowed hover:brightness-125",
29
29
  variants: {
30
30
  size: {
31
+ icon: "p-2 text-sm rounded-full",
31
32
  xs: "gap-2 px-3 py-2 text-xs",
32
33
  sm: "gap-2 px-3 py-2 text-xs sm:text-sm",
33
34
  md: "gap-2 px-4 py-2 text-xs sm:text-sm",
@@ -1,17 +1,14 @@
1
- import { Component, Hoverable } from "../../utils/index.js";
1
+ import type { Hoverable } from "../../utils/types/element.js";
2
+ type Component = {
3
+ style?: string;
4
+ children?: React.ReactNode;
5
+ };
2
6
  type Props = Component & Hoverable & {
3
7
  center?: boolean;
4
8
  centerX?: boolean;
5
9
  centerY?: boolean;
6
10
  equal?: boolean;
7
11
  };
8
- /**
9
- * Flex containers with configurable alignment and styling.
10
- *
11
- * @param {string} style - Additional styles for container.
12
- * @param {ReactNode} children - Child elements to render inside the row.
13
- * @param {Props} opts - Variant options for styling.
14
- **/
15
12
  export declare function RowBox({ style, children, onHover, onLeave, ...opts }: Props): import("react").JSX.Element | null;
16
13
  export declare function ColumnBox({ style, children, onHover, onLeave, ...opts }: Props): import("react").JSX.Element | null;
17
14
  export {};
@@ -1,13 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/functions/style.js";
3
3
  import { tv } from "tailwind-variants";
4
- /**
5
- * Flex containers with configurable alignment and styling.
6
- *
7
- * @param {string} style - Additional styles for container.
8
- * @param {ReactNode} children - Child elements to render inside the row.
9
- * @param {Props} opts - Variant options for styling.
10
- **/
11
4
  export function RowBox({ style, children, onHover, onLeave, ...opts }) {
12
5
  if (!children)
13
6
  return null;
@@ -1 +1,2 @@
1
1
  export { default as TimeAgo } from "./time-ago.js";
2
+ export { default as DatePicker } from "./date-picker.js";
@@ -1 +1,2 @@
1
1
  export { default as TimeAgo } from "./time-ago.js";
2
+ export { default as DatePicker } from "./date-picker.js";
@@ -0,0 +1,38 @@
1
+ import type { ReactNode } from "react";
2
+ type FieldProps<T> = {
3
+ id?: string;
4
+ label?: string;
5
+ style?: string;
6
+ value?: T;
7
+ update?: (x: T) => void;
8
+ updateForm?: (id: string, x: T) => void;
9
+ required?: boolean;
10
+ disabled?: boolean;
11
+ note?: ReactNode;
12
+ };
13
+ type Variant = "normal" | "ghost";
14
+ type DatePickerProps = FieldProps<string> & {
15
+ variant?: Variant;
16
+ size?: "sm" | "md";
17
+ style?: string;
18
+ min?: string;
19
+ max?: string;
20
+ };
21
+ /**
22
+ * Date picker field component.
23
+ *
24
+ * Wraps the native `input[type="date"]` element with custom styling.
25
+ * It displays an optional label and note, and can be marked as required.
26
+ * The value is controlled externally as an ISO date string (`YYYY-MM-DD`).
27
+ *
28
+ * Variants:
29
+ * - `normal`: Standard input with primary color scheme.
30
+ * - `ghost`: Transparent for injecting input inside another component.
31
+ *
32
+ * @param {Variant} variant - Visual style variant. (optional, default = normal)
33
+ * @param {string} style - Additional class names for styling. (optional)
34
+ * @param {string} min - Earliest selectable date in `YYYY-MM-DD` format. (optional)
35
+ * @param {string} max - Latest selectable date in `YYYY-MM-DD` format. (optional)
36
+ */
37
+ export declare function DatePicker({ id, variant, size, value, update, updateForm, disabled, min, max, ...props }: DatePickerProps): import("react").JSX.Element;
38
+ export default DatePicker;
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cn } from "../../utils/functions/style.js";
4
+ import { tv } from "tailwind-variants";
5
+ function Field({ style, label, required = true, note, children }) {
6
+ return (_jsxs("div", { className: cn(fieldStyles.container, style), children: [label && _jsxs("span", { className: fieldStyles.label, children: [label, " ", !required ? _jsx("span", { className: "italic text-slate-400", children: "(optional)" }) : ""] }), children, note && _jsx("span", { className: fieldStyles.note, children: note })] }));
7
+ }
8
+ const fieldStyles = {
9
+ container: "flex flex-col shrink-0 gap-2 overflow-hidden",
10
+ label: "text-xs text-primary-dark",
11
+ note: "mt-1 text-xs text-slate-500 whitespace-pre-line"
12
+ };
13
+ /**
14
+ * Date picker field component.
15
+ *
16
+ * Wraps the native `input[type="date"]` element with custom styling.
17
+ * It displays an optional label and note, and can be marked as required.
18
+ * The value is controlled externally as an ISO date string (`YYYY-MM-DD`).
19
+ *
20
+ * Variants:
21
+ * - `normal`: Standard input with primary color scheme.
22
+ * - `ghost`: Transparent for injecting input inside another component.
23
+ *
24
+ * @param {Variant} variant - Visual style variant. (optional, default = normal)
25
+ * @param {string} style - Additional class names for styling. (optional)
26
+ * @param {string} min - Earliest selectable date in `YYYY-MM-DD` format. (optional)
27
+ * @param {string} max - Latest selectable date in `YYYY-MM-DD` format. (optional)
28
+ */
29
+ export function DatePicker({ id, variant, size = "md", value, update, updateForm, disabled = false, min, max, ...props }) {
30
+ const handleUpdate = (value) => {
31
+ if (id && updateForm)
32
+ updateForm(id, value);
33
+ else
34
+ update?.(value);
35
+ };
36
+ return (_jsx(Field, { ...props, children: _jsx("input", { type: "date", className: styles({ variant, size }), value: value || "", onChange: ({ target: { value } }) => handleUpdate(value), autoComplete: "off", disabled: disabled, min: min, max: max }) }));
37
+ }
38
+ const styles = tv({
39
+ base: "px-3 py-2 duration-200 rounded placeholder:text-primary-darker text-primary disabled:brightness-90 disabled:cursor-not-allowed",
40
+ defaultVariants: { variant: "normal", size: "md" },
41
+ variants: {
42
+ variant: {
43
+ normal: "bg-input border border-outline focus:border-outline-light outline-none",
44
+ ghost: "p-0 bg-transparent border-none outline-none"
45
+ },
46
+ size: {
47
+ sm: "px-2 text-xs",
48
+ md: "text-xs sm:text-sm"
49
+ }
50
+ }
51
+ });
52
+ export default DatePicker;
@@ -1,9 +1,9 @@
1
1
  interface Props {
2
- size?: "sm" | "md" | "lg";
3
- label: string;
2
+ size?: "sm" | "md";
3
+ label?: string;
4
4
  value: boolean;
5
5
  update: (x: boolean) => void;
6
6
  disabled?: boolean;
7
7
  }
8
- export declare const CheckBox: ({ size, label, value: isChecked, update, disabled }: Props) => import("react").JSX.Element;
8
+ export declare function CheckBox({ size, label, value: isChecked, update, disabled }: Props): import("react").JSX.Element;
9
9
  export default CheckBox;
@@ -1,24 +1,21 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { RowBox } from "@bouku/core";
2
+ import { RowBox } from "../../container/flex.js";
3
3
  import Check from "../../../assets/icons/check.svg";
4
4
  import { cn } from "../../../utils/functions/style.js";
5
5
  import { tv } from "tailwind-variants";
6
- export const CheckBox = ({ size, label, value: isChecked, update, disabled = false }) => {
7
- const s = baseStyles({
6
+ export function CheckBox({ size, label, value: isChecked, update, disabled = false }) {
7
+ const s = getStyle({
8
8
  size,
9
9
  active: isChecked
10
10
  });
11
- return (_jsxs(RowBox, { style: s.container(), children: [_jsx("div", { className: cn(s.box(), disabled && "pointer-events-none"), onClick: () => !disabled ? update(!isChecked) : null, children: isChecked && _jsx(Check, { className: s.check() }) }), _jsx("span", { className: s.label(), children: label })] }));
12
- };
13
- const baseStyles = tv({
11
+ return (_jsxs(RowBox, { style: s.container(), children: [_jsx("div", { className: cn(s.box(), disabled && "pointer-events-none"), onClick: () => !disabled ? update(!isChecked) : null, children: isChecked && _jsx(Check, { className: s.check() }) }), label && (_jsx("span", { className: s.label(), children: label }))] }));
12
+ }
13
+ const getStyle = tv({
14
14
  slots: {
15
15
  container: "items-center",
16
- box: "flex justify-center items-center bg-input hover:bg-input-dark border rounded border-outline duration-200 cursor-pointer",
16
+ box: "flex justify-center items-center hover:bg-accent border rounded border-outline duration-200 cursor-pointer",
17
17
  check: "text-background",
18
- label: "text-primary"
19
- },
20
- defaultVariants: {
21
- size: "md"
18
+ label: "text-primary-dark"
22
19
  },
23
20
  variants: {
24
21
  size: {
@@ -29,12 +26,6 @@ const baseStyles = tv({
29
26
  label: "text-xs"
30
27
  },
31
28
  md: {
32
- container: "gap-3",
33
- box: "size-5 min-w-5",
34
- check: "size-3",
35
- label: "text-sm"
36
- },
37
- lg: {
38
29
  container: "gap-3",
39
30
  box: "size-5 min-w-5",
40
31
  check: "size-3",
@@ -43,9 +34,12 @@ const baseStyles = tv({
43
34
  },
44
35
  active: {
45
36
  true: {
46
- box: "!bg-accent border-accent-darker"
37
+ box: "bg-accent"
47
38
  }
48
39
  }
40
+ },
41
+ defaultVariants: {
42
+ size: "md"
49
43
  }
50
44
  });
51
45
  export default CheckBox;
@@ -1,11 +1,13 @@
1
1
  import { type ReactNode } from "react";
2
- import type { LabeledItem } from "../../../utils/types/_.js";
2
+ import type { LabeledItem } from "../../../utils/types/element.js";
3
3
  interface Props {
4
+ size?: "xs" | "sm";
5
+ style?: string;
4
6
  prefix?: ReactNode;
5
7
  align?: "left" | "right";
6
8
  options: LabeledItem[];
7
9
  values?: string[];
8
10
  update: (x: string) => void;
9
11
  }
10
- export declare function MultiSelect({ prefix, align, options, values, update }: Props): import("react").JSX.Element;
12
+ export declare function MultiSelect({ size, style, prefix, align, options, values, update }: Props): import("react").JSX.Element;
11
13
  export default MultiSelect;
@@ -3,11 +3,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef, useEffect, } from "react";
4
4
  import ChevronDown from "../../../assets/icons/chevron-down.svg";
5
5
  import { AnimatePresence, motion } from "framer-motion";
6
- import { Button } from "../../button/normal.js";
7
6
  import { CheckBox } from "../checkbox/index.js";
8
- import { cn } from "../../../utils/functions/_.js";
7
+ import { Button } from "../../button/normal.js";
8
+ import { cn } from "../../../utils/functions/style.js";
9
9
  ;
10
- export function MultiSelect({ prefix, align = "left", options, values = [], update }) {
10
+ export function MultiSelect({ size = "sm", style, prefix, align = "left", options, values = [], update }) {
11
11
  const [isOpen, setOpen] = useState(false);
12
12
  const ref = useRef(null);
13
13
  const activeOpts = options.filter(({ id }) => (values?.includes(id)));
@@ -21,7 +21,7 @@ export function MultiSelect({ prefix, align = "left", options, values = [], upda
21
21
  document.removeEventListener("mousedown", handleClickOutside);
22
22
  };
23
23
  }, []);
24
- return (_jsxs("div", { className: s.container, ref: ref, children: [_jsxs(Button, { size: "sm", action: () => setOpen(o => !o), children: [prefix, activeOpts.length > 0 && (_jsx("span", { className: "text-primary-dark", children: activeOpts.map(({ label }) => label).join(", ") })), _jsx(ChevronDown, { className: s.chevron })] }), _jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { className: cn(s.dropdown, align === "left" ? "left-0" : "right-0"), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: options.map(({ id, label }) => (_jsx("div", { className: s.option, onClick: () => update(id), children: _jsx(CheckBox, { size: "sm", label: label, value: !!values?.includes(id), update: () => console.log("hi"), disabled: true }) }, id))) })) })] }));
24
+ return (_jsxs("div", { className: s.container, ref: ref, children: [_jsxs(Button, { size: size, style: style, action: () => setOpen(o => !o), children: [prefix, activeOpts.length > 0 && (_jsx("span", { className: "text-primary-dark", children: activeOpts.map(({ label }) => label).join(", ") })), _jsx(ChevronDown, { className: s.chevron })] }), _jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { className: cn(s.dropdown, align === "left" ? "left-0" : "right-0"), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: options.map(({ id, label }) => (_jsx("div", { className: s.option, onClick: () => update(id), children: _jsx(CheckBox, { size: "sm", label: label, value: !!values?.includes(id), update: () => console.log("hi"), disabled: true }) }, id))) })) })] }));
25
25
  }
26
26
  const s = {
27
27
  container: "relative shrink-0",
@@ -3,7 +3,8 @@ interface Props {
3
3
  trigger: ReactNode;
4
4
  align?: "left" | "right";
5
5
  direction?: "up" | "down";
6
+ style?: string;
6
7
  children: ReactNode;
7
8
  }
8
- export declare function Dropdown({ trigger, align, direction, children }: Props): import("react").JSX.Element;
9
+ export declare function Dropdown({ trigger, align, direction, style, children }: Props): import("react").JSX.Element;
9
10
  export default Dropdown;
@@ -2,9 +2,9 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef, useEffect } from "react";
4
4
  import { AnimatePresence, motion } from "framer-motion";
5
- import { cn } from "../../../utils/functions/_.js";
5
+ import { cn } from "../../../utils/functions/style.js";
6
6
  ;
7
- export function Dropdown({ trigger, align = "left", direction = "down", children }) {
7
+ export function Dropdown({ trigger, align = "left", direction = "down", style, children }) {
8
8
  const [isOpen, setOpen] = useState(false);
9
9
  const ref = useRef(null);
10
10
  useEffect(() => {
@@ -19,10 +19,10 @@ export function Dropdown({ trigger, align = "left", direction = "down", children
19
19
  }, []);
20
20
  return (_jsxs("div", { ref: ref, className: styles.container, children: [_jsx("div", { onClick: () => setOpen(open => !open), children: trigger }), _jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { className: cn(styles.dropdown, align === "left" ? "left-0" : "right-0", direction === "down"
21
21
  ? "top-full mt-2"
22
- : "bottom-full mb-2"), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: children })) })] }));
22
+ : "bottom-full mb-2", style), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: children })) })] }));
23
23
  }
24
24
  const styles = {
25
25
  container: "relative shrink-0",
26
- dropdown: "absolute z-50 flex flex-col gap-2 min-w-full w-max bg-surface-darker rounded-md border border-border-darker p-2 text-sm shadow-md"
26
+ dropdown: "absolute z-50 flex flex-col gap-2 min-w-full w-max bg-surface-dark rounded-md border border-border-dark p-2 text-sm shadow"
27
27
  };
28
28
  export default Dropdown;
@@ -1,11 +1,13 @@
1
1
  import { type ReactNode } from "react";
2
- import type { LabeledItem } from "../../../utils/types/_.js";
2
+ import type { LabeledItem } from "../../../utils/types/element.js";
3
3
  interface Props {
4
+ size?: "xs" | "sm";
5
+ style?: string;
4
6
  prefix?: ReactNode;
5
7
  align?: "left" | "right";
6
8
  options: LabeledItem[];
7
9
  value?: string;
8
10
  update: (x: string) => void;
9
11
  }
10
- export declare function Select({ prefix, align, options, value, update }: Props): import("react").JSX.Element;
12
+ export declare function Select({ size, style, prefix, align, options, value, update }: Props): import("react").JSX.Element;
11
13
  export default Select;
@@ -4,9 +4,9 @@ import { useState, useRef, useEffect, } from "react";
4
4
  import ChevronDown from "../../../assets/icons/chevron-down.svg";
5
5
  import { AnimatePresence, motion } from "framer-motion";
6
6
  import { Button } from "../../button/normal.js";
7
- import { cn } from "../../../utils/functions/_.js";
7
+ import { cn } from "../../../utils/functions/style.js";
8
8
  ;
9
- export function Select({ prefix, align = "left", options, value, update }) {
9
+ export function Select({ size = "sm", style, prefix, align = "left", options, value, update }) {
10
10
  const [isOpen, setOpen] = useState(false);
11
11
  const ref = useRef(null);
12
12
  const active = options.find(o => o.id === value);
@@ -24,7 +24,7 @@ export function Select({ prefix, align = "left", options, value, update }) {
24
24
  update(x);
25
25
  setOpen(false);
26
26
  };
27
- return (_jsxs("div", { ref: ref, className: s.container, children: [_jsxs(Button, { size: "sm", action: () => setOpen(open => !open), children: [prefix, _jsx("span", { className: "text-primary-dark", children: active && active.label }), _jsx(ChevronDown, { className: s.chevron })] }), _jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { className: cn(s.dropdown, align === "left" ? "left-0" : "right-0"), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: options.map(({ id, label }) => (_jsx("span", { className: cn(s.option, id === value && "text-accent pointer-events-none"), onClick: () => setValue(id), children: label }, id))) })) })] }));
27
+ return (_jsxs("div", { ref: ref, className: s.container, children: [_jsxs(Button, { size: size, style: style, action: () => setOpen(open => !open), children: [prefix, _jsx("span", { className: "text-primary-dark", children: active && active.label }), _jsx(ChevronDown, { className: s.chevron })] }), _jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { className: cn(s.dropdown, align === "left" ? "left-0" : "right-0"), initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: options.map(({ id, label }) => (_jsx("span", { className: cn(s.option, id === value && "text-accent pointer-events-none"), onClick: () => setValue(id), children: label }, id))) })) })] }));
28
28
  }
29
29
  const s = {
30
30
  container: "relative shrink-0",
@@ -6,6 +6,6 @@ export function Actions({ row, actions }) {
6
6
  return (_jsx(RowBox, { style: "gap-2 items-center", children: actions.map(action => {
7
7
  if (action.hidden?.(row))
8
8
  return null;
9
- return (_jsx(Button, { size: "xs", variant: action.variant ?? "surface", style: action.style, icon: action.icon, action: () => action.handler(row), children: action.label }, action.id));
9
+ return (_jsx(Button, { size: "icon", variant: action.variant ?? "surface", style: action.style, icon: action.icon, action: () => action.handler(row), children: action.label }, action.id));
10
10
  }) }));
11
11
  }
@@ -0,0 +1,8 @@
1
+ import type { Dispatch, SetStateAction } from "react";
2
+ import type { DateRange } from "./utils/types.js";
3
+ type Props = DateRange & {
4
+ update: Dispatch<SetStateAction<DateRange>>;
5
+ initial: DateRange;
6
+ };
7
+ export default function DateRange({ from, to, update, initial }: Props): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1,10 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Dropdown } from "../miscellaneous/dropdown/normal.js";
3
+ import { DatePicker } from "../date/date-picker.js";
4
+ import { Button } from "../button/normal.js";
5
+ import Trash from "../../assets/icons/trash.svg";
6
+ import { formatDateLabel } from "./utils/date.js";
7
+ export default function DateRange({ from, to, update, initial }) {
8
+ const Trigger = (_jsxs(Button, { size: "xs", style: "bg-surface-dark border-border-darker", children: [formatDateLabel(from), " \u2013 ", formatDateLabel(to)] }));
9
+ return (_jsxs(Dropdown, { trigger: Trigger, align: "right", style: "gap-3 min-w-56 p-4", children: [_jsx(DatePicker, { id: "from", label: "From", size: "sm", style: "gap-1", value: from, update: v => update(prev => ({ ...prev, from: v })) }), _jsx(DatePicker, { id: "to", label: "To", size: "sm", style: "gap-1", value: to, update: v => update(prev => ({ ...prev, to: v })) }), (from || to) && (_jsx(Button, { size: "xs", style: "mx-auto py-1 px-2 gap-1", variant: "error", icon: _jsx(Trash, {}), action: () => update(initial), disabled: from === initial.from && to === initial.to, children: "Clear" }))] }));
10
+ }
@@ -0,0 +1,10 @@
1
+ import type { CellValue, Column, TableRow } from "./utils/types.js";
2
+ type Props<T extends TableRow> = {
3
+ columns: Column<T>[];
4
+ items: Map<keyof T, Set<CellValue>>;
5
+ options: Partial<Record<keyof T, CellValue[]>>;
6
+ update: (column: keyof T, value: CellValue) => void;
7
+ clear: (column: keyof T) => void;
8
+ };
9
+ export default function Filters<T extends TableRow>({ columns, items, options, update, clear }: Props<T>): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Dropdown, MultiSelect } from "../miscellaneous/dropdown/_.js";
3
+ import { Button } from "../button/normal.js";
4
+ import FilterIcon from "../../assets/icons/filter.svg";
5
+ import Trash from "../../assets/icons/trash.svg";
6
+ export default function Filters({ columns, items, options, update, clear }) {
7
+ const filterColumns = columns
8
+ .filter(column => column.filter === "select")
9
+ .map(column => column.key);
10
+ const activeFilterCount = Array.from(items.values())
11
+ .filter(values => values.size > 0)
12
+ .length;
13
+ const getColumnLabel = (key) => {
14
+ const col = columns.find(column => column.key === key);
15
+ return col?.label ?? key.toString().replaceAll("_", " ");
16
+ };
17
+ const clearFilters = () => {
18
+ for (const c of filterColumns)
19
+ clear(c);
20
+ };
21
+ const Trigger = (_jsxs(Button, { size: "xs", style: "bg-surface-dark border-border-darker", icon: _jsx(FilterIcon, {}), children: ["Filter", activeFilterCount > 0 && (_jsx("span", { className: s.count, children: activeFilterCount }))] }));
22
+ return (_jsxs(Dropdown, { trigger: Trigger, style: "p-3 gap-3", children: [filterColumns.map(column => {
23
+ const myFilters = items.get(column);
24
+ return (_jsx(MultiSelect, { size: "xs", prefix: getColumnLabel(column).toUpperCase(), options: (options[column] || []).filter(v => v !== null).map(value => ({
25
+ id: String(value),
26
+ label: String(value)
27
+ })), values: Array.from(myFilters || []).map(f => String(f)), update: (x) => update(column, x) }, String(column)));
28
+ }), _jsx(Button, { size: "xs", style: "mx-auto py-1 px-2 gap-1", variant: "error", icon: _jsx(Trash, {}), action: clearFilters, disabled: activeFilterCount === 0, children: "Clear" })] }));
29
+ }
30
+ const s = {
31
+ count: "flex justify-center items-center ml-1 bg-accent border border-accent-dark size-4 rounded-full text-px font-bold"
32
+ };
@@ -6,6 +6,10 @@ type Props<T> = {
6
6
  hasActions: boolean;
7
7
  sortBy: (x: string | null) => void;
8
8
  toggleSortDirection: () => void;
9
+ selection?: {
10
+ allSelected: boolean;
11
+ toggleAll: () => void;
12
+ };
9
13
  };
10
- export declare const Header: <T extends Record<keyof T, CellValue>>({ columnLabels, sortColumn, sortDirection, hasActions, sortBy, toggleSortDirection }: Props<T>) => import("react").JSX.Element;
14
+ export declare const Header: <T extends Record<keyof T, CellValue>>({ columnLabels, sortColumn, sortDirection, hasActions, sortBy, toggleSortDirection, selection }: Props<T>) => import("react").JSX.Element;
11
15
  export {};
@@ -2,12 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Fragment } from "react";
4
4
  import { RowBox } from "../container/flex.js";
5
- import ArrowUp from "../../assets/icons/arrow-up.svg";
6
- import ArrowDown from "../../assets/icons/arrow-down.svg";
7
- export const Header = ({ columnLabels, sortColumn, sortDirection, hasActions, sortBy, toggleSortDirection }) => (_jsxs(RowBox, { style: s.container, children: [Object.entries(columnLabels).map(([col, label], i) => (_jsxs(RowBox, { style: s.column, children: [_jsx("span", { className: s.label, onClick: () => sortBy(col), children: label }), col === sortColumn && (_jsxs(Fragment, { children: [sortDirection === "desc" && _jsx(ArrowDown, { className: s.sorter, onClick: () => toggleSortDirection() }), sortDirection === "asc" && _jsx(ArrowUp, { className: s.sorter, onClick: () => toggleSortDirection() })] }))] }, i))), hasActions && (_jsx(RowBox, { style: s.column, children: _jsx("span", { children: "Actions" }) }))] }));
5
+ import { CheckBox } from "../miscellaneous/checkbox/index.js";
6
+ import { cn } from "../../utils/functions/style.js";
7
+ import ArrowUp from "../static/icons/arrow-up.svg";
8
+ import ArrowDown from "../static/icons/arrow-down.svg";
9
+ export const Header = ({ columnLabels, sortColumn, sortDirection, hasActions, sortBy, toggleSortDirection, selection }) => (_jsxs(RowBox, { style: s.container, children: [selection && (_jsx(RowBox, { style: s.selection, children: _jsx(CheckBox, { size: "sm", value: selection.allSelected, update: selection.toggleAll }) })), Object.entries(columnLabels).map(([col, label], i) => (_jsxs(RowBox, { style: cn(s.column, i === 0 && "justify-start"), children: [_jsx("span", { className: s.label, onClick: () => sortBy(col), children: label }), col === sortColumn && (_jsxs(Fragment, { children: [sortDirection === "desc" && _jsx(ArrowDown, { className: s.sorter, onClick: () => toggleSortDirection() }), sortDirection === "asc" && _jsx(ArrowUp, { className: s.sorter, onClick: () => toggleSortDirection() })] }))] }, i))), hasActions && (_jsx(RowBox, { style: s.column, children: _jsx("span", { children: "Actions" }) }))] }));
8
10
  const s = {
9
- container: "w-full px-4 py-3 bg-background-light border-b border-border",
11
+ container: "w-full px-4 h-11 shrink-0 bg-background-light border-b border-border",
10
12
  column: "flex-1 gap-1 first:justify-start justify-center last:justify-end items-center uppercase text-primary-dark font-light text-sm",
13
+ selection: "w-10 shrink-0 flex items-center justify-start",
11
14
  label: "hover:brightness-120 duration-200 cursor-pointer",
12
15
  sorter: "hover:text-primary cursor-pointer duration-200"
13
16
  };
@@ -1,12 +1,18 @@
1
1
  import type { Column, TableAction } from "./utils/types.js";
2
+ import type { SetState } from "../../utils/types/state.js";
2
3
  import { type Row } from "./row.js";
3
- type Props<T extends Row> = {
4
+ type Props<T extends Row, K extends keyof T = keyof T> = {
4
5
  style?: string;
5
6
  title?: string;
6
7
  columns: Column<T>[];
7
8
  items: T[];
8
9
  actions?: TableAction<T>[];
9
10
  initialSort?: keyof T;
11
+ selection?: {
12
+ key: K;
13
+ values: T[K][];
14
+ update: SetState<T[K][]>;
15
+ };
10
16
  };
11
- export declare function Table<T extends Row>({ style, title, columns, items, actions, initialSort }: Props<T>): import("react").JSX.Element;
17
+ export declare function Table<T extends Row, K extends keyof T = keyof T>({ style, title, columns, items, actions, initialSort, selection }: Props<T, K>): import("react").JSX.Element;
12
18
  export type { TableAction } from "./utils/types.js";
@@ -1,56 +1,70 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTableData } from "./state/_.js";
4
- import Filter from "../../assets/icons/filter.svg";
4
+ import { condenseArray } from "ts-helper-kit";
5
5
  import { ColumnBox, RowBox } from "../container/flex.js";
6
- import { Button } from "../button/normal.js";
6
+ import { Select } from "../miscellaneous/dropdown/select.js";
7
7
  import { Header } from "./header.js";
8
8
  import { TableRow } from "./row.js";
9
- import { Dropdown, Select, MultiSelect } from "../miscellaneous/dropdown/_.js";
10
9
  import { SearchBar } from "./search-bar.js";
11
- import { condenseArray } from "ts-helper-kit";
12
- import { formatDateLabel } from "./utils/date.js";
13
- import { cn } from "../../utils/functions/_.js";
14
- export function Table({ style, title, columns, items, actions, initialSort }) {
10
+ import Filters from "./filters.js";
11
+ import DateRange from "./date-range.js";
12
+ import { cn } from "../../utils/functions/style.js";
13
+ export function Table({ style, title, columns, items, actions, initialSort, selection }) {
15
14
  const columnKeys = columns.map(column => column.key);
16
15
  const filterColumns = columns
17
16
  .filter(column => column.filter === "select")
18
17
  .map(column => column.key);
19
18
  const dateColumn = columns.find(column => column.filter === "date")?.key;
20
- const { sortedItems, search, setSearch, dateRange, setDateRange, initialDateRange, sortBy, sortColumn, sortDirection, toggleSortDirection, filterOptions, selectedFilters, toggleFilter } = useTableData(items, columns, initialSort);
19
+ const { sortedItems, search, setSearch, dateRange, setDateRange, initialDateRange, sortBy, sortColumn, sortDirection, toggleSortDirection, filterOptions, selectedFilters, toggleFilter, clearFilter } = useTableData(items, columns, initialSort);
20
+ const toggleSelection = (item) => {
21
+ if (!selection)
22
+ return;
23
+ const value = item[selection.key];
24
+ selection.update(selection.values.includes(value)
25
+ ? selection.values.filter(x => x !== value)
26
+ : [...selection.values, value]);
27
+ };
21
28
  const condensedItems = condenseArray(sortedItems, columnKeys);
22
- const activeFilterCount = Array.from(selectedFilters.values())
23
- .filter(values => values.size > 0)
24
- .length;
29
+ const visibleSelectionValues = selection
30
+ ? condensedItems.map(({ item }) => item[selection.key])
31
+ : [];
32
+ const allSelected = selection
33
+ ? visibleSelectionValues.length > 0 &&
34
+ visibleSelectionValues.every(value => selection.values.includes(value))
35
+ : false;
36
+ const toggleAll = () => {
37
+ if (!selection)
38
+ return;
39
+ selection.update(current => {
40
+ if (allSelected) {
41
+ return current.filter(value => !visibleSelectionValues.includes(value));
42
+ }
43
+ return [
44
+ ...current,
45
+ ...visibleSelectionValues.filter(value => !current.includes(value))
46
+ ];
47
+ });
48
+ };
25
49
  const getColumnLabel = (key) => {
26
50
  const col = columns.find(column => column.key === key);
27
51
  return col?.label ?? key.toString().replaceAll("_", " ");
28
52
  };
29
- return (_jsxs(ColumnBox, { style: cn(s.container, style), children: [title && (_jsx("span", { className: s.title, children: title })), _jsxs(RowBox, { style: "gap-3 mb-1", children: [_jsx(SearchBar, { value: search, update: setSearch, resultCount: sortedItems.length }), filterColumns.length > 0 && (_jsx(Dropdown, { trigger: _jsxs(Button, { size: "sm", icon: _jsx(Filter, {}), children: ["Filter", activeFilterCount > 0 && (_jsx("span", { className: "flex justify-center items-center ml-1 bg-accent border border-accent-dark size-4 rounded-full text-px font-bold", children: activeFilterCount }))] }), children: filterColumns.map(column => {
30
- const myFilters = selectedFilters.get(column);
31
- return (_jsx(MultiSelect, { prefix: getColumnLabel(column).toUpperCase(), options: (filterOptions[column] || []).map(value => ({
32
- id: String(value),
33
- label: String(value)
34
- })), values: Array.from(myFilters || []).map(f => String(f)), update: (x) => toggleFilter(column, x) }, String(column)));
35
- }) })), _jsx(Select, { prefix: "Sort By", options: columns.map(column => ({
53
+ return (_jsxs(ColumnBox, { style: cn(s.container, style), children: [title && (_jsx("span", { className: s.title, children: title })), _jsxs(RowBox, { style: "gap-3 items-center mb-1", children: [_jsx(SearchBar, { value: search, update: setSearch, resultCount: sortedItems.length }), filterColumns.length > 0 && (_jsx(Filters, { columns: columns, items: selectedFilters, options: filterOptions, update: toggleFilter, clear: clearFilter })), _jsx(Select, { size: "xs", style: "bg-surface-dark border-border-darker", prefix: "Sort By", options: columns.map(column => ({
36
54
  id: column.key.toString(),
37
55
  label: getColumnLabel(column.key).toUpperCase()
38
- })), value: sortColumn?.toString(), update: x => sortBy(x) }), dateColumn && (_jsx(Dropdown, { align: "right", trigger: _jsx(Button, { size: "sm", children: dateRange.from && dateRange.to
39
- ? `${formatDateLabel(dateRange.from)} – ${formatDateLabel(dateRange.to)}`
40
- : getColumnLabel(dateColumn) }), children: _jsxs(ColumnBox, { style: "gap-3 p-3 min-w-64", children: [_jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["From", _jsx("input", { type: "date", value: dateRange.from, onChange: e => setDateRange(prev => ({
41
- ...prev,
42
- from: e.target.value
43
- })), className: "px-3 py-2 bg-input border border-border rounded-md" })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["To", _jsx("input", { type: "date", value: dateRange.to, onChange: e => setDateRange(prev => ({
44
- ...prev,
45
- to: e.target.value
46
- })), className: "px-3 py-2 bg-input border border-border rounded-md" })] }), (dateRange.from || dateRange.to) && (_jsx(Button, { size: "sm", action: () => setDateRange(initialDateRange), children: "Clear" }))] }) }))] }), _jsxs(ColumnBox, { style: s.subcontainer, children: [_jsx(Header, { sortBy: sortBy, sortColumn: sortColumn, sortDirection: sortDirection, toggleSortDirection: toggleSortDirection, hasActions: !!actions?.length, columnLabels: Object.fromEntries(columns.map(column => [
56
+ })), value: sortColumn?.toString(), update: x => sortBy(x) }), dateColumn && (_jsx(DateRange, { ...dateRange, update: setDateRange, initial: initialDateRange }))] }), _jsxs(ColumnBox, { style: s.subcontainer, children: [_jsx(Header, { sortBy: sortBy, sortColumn: sortColumn, sortDirection: sortDirection, toggleSortDirection: toggleSortDirection, hasActions: !!actions?.length, columnLabels: Object.fromEntries(columns.map(column => [
47
57
  column.key,
48
58
  getColumnLabel(column.key)
49
- ])) }), _jsx(ColumnBox, { style: s.rows, children: condensedItems.map(({ item, count }, i) => (_jsx(TableRow, { columns: columns, data: item, count: count, actions: actions }, i))) })] })] }));
59
+ ])), selection: selection ? { allSelected, toggleAll } : undefined }), _jsx(ColumnBox, { style: s.rows, children: condensedItems.map(({ item, count }, i) => (_jsx(TableRow, { columns: columns, data: item, count: count, actions: actions, selected: selection
60
+ ? selection.values.includes(item[selection.key])
61
+ : undefined, toggleSelected: selection
62
+ ? () => toggleSelection(item)
63
+ : undefined }, i))) })] })] }));
50
64
  }
51
65
  const s = {
52
- container: "grow gap-3 overflow-hidden",
66
+ container: "grow gap-3 shadow-md overflow-hidden",
53
67
  title: "text-xl font-bold text-primary",
54
- subcontainer: "grow w-full border border-border rounded-md overflow-hidden",
68
+ subcontainer: "w-full grow border border-border-dark rounded-md overflow-hidden",
55
69
  rows: "grow overflow-y-auto no-scrollbar"
56
70
  };
@@ -5,7 +5,9 @@ interface Props<T extends TableRowType> {
5
5
  data: T;
6
6
  count: number;
7
7
  actions?: TableAction<T>[];
8
+ selected?: boolean;
9
+ toggleSelected?: () => void;
8
10
  }
9
11
  export type Row = Record<string, CellValue>;
10
- export declare const TableRow: <T extends Row>({ columns, data, actions, count }: Props<T>) => import("react").JSX.Element;
12
+ export declare const TableRow: <T extends Row>({ columns, data, actions, count, selected, toggleSelected }: Props<T>) => import("react").JSX.Element;
11
13
  export {};
@@ -1,19 +1,28 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { RowBox } from "../container/flex.js";
2
+ import { RowBox, cn } from "@bouku/core";
3
+ import { CheckBox } from "../miscellaneous/checkbox/index.js";
3
4
  import { Actions } from "./actions.js";
4
5
  import CheckCircle from "../../assets/icons/check-circle.svg";
5
6
  import XCircle from "../../assets/icons/x-circle.svg";
6
7
  export const isDateLike = (val) => !isNaN(Date.parse(val)) && isNaN(Number(val));
7
- ;
8
- export const TableRow = ({ columns, data, actions, count }) => (_jsxs(RowBox, { style: s.container, children: [columns.map(({ key, format }, i) => {
8
+ export const TableRow = ({ columns, data, actions, count, selected, toggleSelected }) => (_jsxs(RowBox, { style: s.container, children: [toggleSelected && (_jsx(RowBox, { style: s.selection, children: _jsx(CheckBox, { size: "sm", value: selected ?? false, update: toggleSelected }) })), columns.map(({ key, format }, i) => {
9
9
  const rawValue = data[key];
10
- const value = rawValue === 0 ? 0 : (data[key] ?? "-");
10
+ const value = rawValue === 0
11
+ ? 0
12
+ : (data[key] ?? "-");
11
13
  let cellValue = value;
12
- if (format && format === "date" && isDateLike(value.toString()))
14
+ if (format === "date" &&
15
+ isDateLike(value.toString())) {
13
16
  cellValue = new Date(cellValue.toString()).toLocaleDateString();
14
- return (_jsx(RowBox, { style: s.cell, children: _jsx("span", { className: "truncate", children: value === true ? _jsx(CheckCircle, { className: "text-success" }) : value === false ? _jsx(XCircle, { className: "text-error" }) : cellValue }) }, i));
17
+ }
18
+ return (_jsx(RowBox, { style: cn(s.cell, i === 0 && "justify-start"), children: _jsx("span", { className: "truncate", children: value === true
19
+ ? _jsx(CheckCircle, { className: "text-success" })
20
+ : value === false
21
+ ? _jsx(XCircle, { className: "text-error" })
22
+ : cellValue }) }, i));
15
23
  }), actions && (_jsx(RowBox, { style: s.cell, children: _jsx(Actions, { row: data, actions: actions }) })), count > 1 && (_jsx("span", { className: "absolute top-0 left-0 pb-px px-1 bg-surface-light border-b border-r rounded-br border-border-light font-bold font-mono text-px text-accent", children: count }))] }));
16
24
  const s = {
17
- container: "relative w-full px-4 py-4 bg-background even:bg-surface border-b border-border last:border-b-0",
25
+ container: "relative w-full px-4 h-15 shrink-0 bg-background even:bg-surface/50 border-b border-border last:border-b-0",
26
+ selection: "w-10 shrink-0 flex items-center justify-start",
18
27
  cell: "flex-1 first-of-type:justify-start justify-center last-of-type:justify-end items-center gap-2 font-mono overflow-hidden"
19
28
  };
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { RowBox } from "../container/flex.js";
3
+ import { cn } from "../../utils/functions/style.js";
3
4
  import MagnifyGlass from "../../assets/icons/magnify-glass.svg";
4
5
  export function SearchBar({ value, update, resultCount }) {
5
- return (_jsxs(RowBox, { style: "items-center gap-3 mr-auto px-3", children: [_jsx(MagnifyGlass, { className: "text-lg text-primary/70" }), _jsx("input", { className: "outline-0 text-primary placeholder:text-primary-dark", placeholder: `Search ${resultCount} result${resultCount !== 1 ? "s" : ""}...`, value: value, onChange: e => update(e.target.value) })] }));
6
+ return (_jsxs(RowBox, { style: "group items-center gap-2 mr-auto w-56 px-3 py-2 bg-surface-dark border border-border-darker shadow rounded", children: [_jsx(MagnifyGlass, { className: cn("text-base text-primary-darker group-focus-within:text-primary duration-200", value && value !== "" && "text-primary") }), _jsx("input", { className: "outline-0 text-primary placeholder:text-primary-dark text-xs", placeholder: `Search ${resultCount} result${resultCount !== 1 ? "s" : ""}...`, value: value, onChange: e => update(e.target.value) })] }));
6
7
  }
7
8
  export default SearchBar;
@@ -1,6 +1,5 @@
1
1
  import { useMemo, useState } from "react";
2
2
  export function useFilters(items, columns) {
3
- console.log(items, columns);
4
3
  const [selectedFilters, setSelectedFilters] = useState(new Map());
5
4
  const filterOptions = useMemo(() => {
6
5
  return Object.fromEntries(columns.map(column => [
@@ -20,16 +20,20 @@ export function useSort(items, initialSort) {
20
20
  if (valB === undefined || valB === null)
21
21
  return -1;
22
22
  let comparison;
23
- if (isDateLike(valA) && isDateLike(valB))
23
+ if (isDateLike(valA) && isDateLike(valB)) {
24
24
  comparison =
25
25
  parseDate(valA).getTime() -
26
26
  parseDate(valB).getTime();
27
- else if (typeof valA === "number" && typeof valB === "number")
27
+ }
28
+ else if (typeof valA === "number" &&
29
+ typeof valB === "number") {
28
30
  comparison = valA - valB;
29
- else
31
+ }
32
+ else {
30
33
  comparison = String(valA)
31
34
  .toLowerCase()
32
35
  .localeCompare(String(valB).toLowerCase());
36
+ }
33
37
  return isDescending ? -comparison : comparison;
34
38
  });
35
39
  }, [items, column, isDescending]);
@@ -41,6 +41,7 @@ export const formatDateLabel = (value) => {
41
41
  year: "numeric"
42
42
  });
43
43
  };
44
- export const isDateLike = (value) => value instanceof Date || (typeof value === "string" &&
45
- !Number.isNaN(Date.parse(value)) &&
46
- Number.isNaN(Number(value)));
44
+ export const isDateLike = (value) => value instanceof Date ||
45
+ (typeof value === "string" &&
46
+ !Number.isNaN(Date.parse(value)) &&
47
+ Number.isNaN(Number(value)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bouku/core",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "main": "./dist/index.js",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",