pentatrion-design 0.0.14 → 0.0.16

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 (48) hide show
  1. package/components/autocomplete/Autocomplete.d.ts +2 -2
  2. package/components/autocomplete/Autocomplete.js +6 -6
  3. package/components/autocomplete/AutocompleteOption.d.ts +1 -3
  4. package/components/autocomplete/AutocompleteOption.js +3 -4
  5. package/components/autocomplete/LazyAutocomplete.d.ts +2 -2
  6. package/components/autocomplete/LazyAutocomplete.js +1 -2
  7. package/components/autocomplete/SimpleAutocomplete.d.ts +2 -2
  8. package/components/autocomplete/SimpleAutocomplete.js +1 -1
  9. package/components/autocomplete/_fixtures.d.ts +1 -0
  10. package/components/autocomplete/_fixtures.js +21 -0
  11. package/components/autocomplete/index.d.ts +2 -2
  12. package/components/autocomplete/index.js +2 -2
  13. package/components/badge/Badge.js +4 -2
  14. package/components/button/Button.test.js +1 -1
  15. package/components/button/LinkButton.js +1 -1
  16. package/components/context-menu/ContextMenu.js +1 -1
  17. package/components/dropdown-menu/DropdownMenu.js +2 -1
  18. package/components/dropdown-menu/DropdownMenuContent.js +1 -1
  19. package/components/dropdown-menu/DropdownMenuItem.js +1 -1
  20. package/components/dropdown-menu/DropdownMenuTrigger.js +1 -1
  21. package/components/dropdown-menu/useDropdownMenuContext.d.ts +1 -1
  22. package/components/dropdown-menu-nested/DropdownMenuNested.d.ts +1 -1
  23. package/components/dropdown-menu-nested/DropdownMenuNested.js +1 -1
  24. package/components/dropdown-menu-nested/MenuItemWithChildren.d.ts +1 -1
  25. package/components/dropdown-menu-nested/MenuItemWithChildren.js +2 -2
  26. package/components/href/Href.d.ts +1 -2
  27. package/components/input/Color.js +1 -1
  28. package/components/input/Input.js +7 -3
  29. package/components/input/Input.test.js +1 -1
  30. package/components/input-field/InputField.d.ts +1 -1
  31. package/components/modal/Components.js +3 -3
  32. package/components/modal/ModalContent.js +2 -2
  33. package/components/modal/ModalTrigger.js +2 -2
  34. package/components/notification/NotificationsProvider.js +1 -1
  35. package/components/notification/useFetch.js +1 -1
  36. package/components/select/Select.d.ts +1 -1
  37. package/components/select/Select.js +15 -11
  38. package/components/tooltip/SimpleTooltip.js +3 -1
  39. package/components/tooltip/Tooltip.js +2 -1
  40. package/components/tooltip/Tooltip.test.js +1 -1
  41. package/components/tooltip/TooltipContent.js +2 -2
  42. package/components/tooltip/TooltipTrigger.js +1 -1
  43. package/components/tooltip/useTooltipContext.d.ts +1 -1
  44. package/hooks/useRipple.js +1 -1
  45. package/package.json +1 -1
  46. package/tailwind/base.js +42 -0
  47. package/tailwind/components.js +9 -33
  48. package/tailwind/utilities.js +5 -14
@@ -39,6 +39,6 @@ export interface AutocompleteProps<O extends OptionLike = Option> {
39
39
  loading?: boolean;
40
40
  clearSearchButton?: boolean;
41
41
  selectOnFocus?: boolean;
42
+ readOnly?: boolean;
42
43
  }
43
- declare const _default: <O extends OptionLike = Option>(props: AutocompleteProps<O> & import("react").RefAttributes<HTMLInputElement>) => React.ReactElement | null;
44
- export default _default;
44
+ export declare const Autocomplete: <O extends OptionLike = Option>(props: AutocompleteProps<O> & import("react").RefAttributes<HTMLInputElement>) => React.ReactElement | null;
@@ -1,7 +1,7 @@
1
1
  import { createElement as _createElement } from "react";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useMemo, useRef, useState, forwardRef, } from "react";
4
- import AutocompleteOption from "./AutocompleteOption";
4
+ import { AutocompleteOption } from "./AutocompleteOption";
5
5
  import { FloatingFocusManager, FloatingList, FloatingPortal, autoUpdate, flip, offset, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, } from "@floating-ui/react";
6
6
  import { AutocompleteContext } from "./useAutocompleteContext";
7
7
  import clsx from "clsx";
@@ -11,7 +11,7 @@ import { Button } from "../button";
11
11
  import { Dialog } from "../dialog";
12
12
  import { Loader } from "../loader";
13
13
  import { inputConfig } from "../input/Input";
14
- function Autocomplete({ className, icon = true, color = "yellow", selectionSuffix, noSearchSuffix, placement = "bottom", placeholder = "Search...", selection = null, onChangeSelection, autocompleteOptionComponent, loading = false, clearSearchButton = false, searchValue, onChangeSearchValue, options, selectOnFocus = true, }, inputRef) {
14
+ export const Autocomplete = forwardRef(function Autocomplete({ className, icon = true, color = "yellow", selectionSuffix, noSearchSuffix, placement = "bottom", placeholder = "Search...", selection = null, onChangeSelection, autocompleteOptionComponent, loading = false, clearSearchButton = false, searchValue, onChangeSearchValue, options, selectOnFocus = true, readOnly = false, }, inputRef) {
15
15
  const [isOpen, setIsOpen] = useState(false);
16
16
  const [activeIndex, setActiveIndex] = useState(null);
17
17
  const onChangeSearchValueStable = useEventCallback(onChangeSearchValue);
@@ -94,7 +94,8 @@ function Autocomplete({ className, icon = true, color = "yellow", selectionSuffi
94
94
  getItemProps,
95
95
  handleSelect,
96
96
  }), [activeIndex, selection, getItemProps, handleSelect]);
97
- return (_jsxs("div", { className: className, children: [_jsxs("div", { className: clsx(inputConfig.container), ref: refs.setReference, "data-color": color, children: [icon !== false && (_jsxs("div", { className: "relative flex-center", children: [loading && _jsx(Loader, { size: "medium", color: "gray", className: "absolute left-0 top-0" }), icon === true ? (_jsx("span", { className: "h-8 w-8 flex-center", children: _jsx("i", { className: "fe-search" }) })) : (icon)] })), _jsx("input", { spellCheck: "false", className: clsx(inputConfig.input, icon === false && "pl-4"), ref: inputRef, type: "search", value: searchValue, placeholder: placeholder, "aria-autocomplete": "list", ...getReferenceProps({
97
+ const showClearSearchButton = !readOnly && clearSearchButton && (searchValue.trim() !== "" || selection !== null);
98
+ return (_jsxs("div", { className: className, children: [_jsxs("div", { className: clsx(inputConfig.container, readOnly && "readonly"), ref: refs.setReference, "data-color": color, children: [icon !== false && (_jsxs("div", { className: "relative flex-center", children: [loading && _jsx(Loader, { size: "medium", color: "gray", className: "absolute left-0 top-0" }), icon === true ? (_jsx("span", { className: "h-8 w-8 flex-center", children: _jsx("i", { className: "fe-search" }) })) : (icon)] })), _jsx("input", { spellCheck: "false", className: clsx(inputConfig.input, icon === false && "pl-4"), ref: inputRef, type: "search", readOnly: readOnly, value: searchValue, placeholder: placeholder, "aria-autocomplete": "list", ...getReferenceProps({
98
99
  onFocus() {
99
100
  if (selectOnFocus) {
100
101
  document.activeElement?.select();
@@ -120,7 +121,7 @@ function Autocomplete({ className, icon = true, color = "yellow", selectionSuffi
120
121
  handleSelect(activeIndex);
121
122
  }
122
123
  },
123
- }) }), _jsxs("div", { className: "relative flex-center", children: [selection && selectionSuffix, clearSearchButton && (searchValue.trim() !== "" || selection !== null) && (_jsx(Button, { withRipple: false, icon: true, color: "gray", variant: "text", onClick: () => {
124
+ }) }), _jsxs("div", { className: "relative flex-center", children: [selection && selectionSuffix, showClearSearchButton && (_jsx(Button, { withRipple: false, icon: true, color: "gray", variant: "text", onClick: () => {
124
125
  setIsOpen(false);
125
126
  onChangeSelectionStable(null);
126
127
  setActiveIndex(null);
@@ -128,5 +129,4 @@ function Autocomplete({ className, icon = true, color = "yellow", selectionSuffi
128
129
  }, children: _jsx("i", { className: "fe-cancel" }) })), icon === false && loading && _jsx(Loader, { size: "medium", color: "gray" }), !selection && searchValue === "" && noSearchSuffix] })] }), _jsx(FloatingPortal, { children: _jsx(AutocompleteContext.Provider, { value: autocompleteContext, children: isOpen && (_jsx(FloatingFocusManager, { disabled: selectOnFocus, context: context, initialFocus: -1, visuallyHiddenDismiss: true, children: _jsx("div", { className: "z-dialog outline-none", ref: refs.setFloating, style: floatingStyles, ...getFloatingProps(), children: _jsx(Dialog, { placement: context.placement, className: "overflow-auto motion-safe:animate-fade-in-list", children: _jsx(FloatingList, { elementsRef: listRef, children: options.map((option) => {
129
130
  return _createElement(OptionComponent, { ...option, key: getOptionValue(option) });
130
131
  }) }) }) }) })) }) })] }));
131
- }
132
- export default forwardRef(Autocomplete);
132
+ });
@@ -1,5 +1,3 @@
1
1
  import { OptionLike } from "../select";
2
2
  export type AutocompleteOptionProps<O extends OptionLike> = O;
3
- declare function AutocompleteOption<O extends OptionLike>(props: AutocompleteOptionProps<O>): import("react/jsx-runtime").JSX.Element;
4
- declare const _default: import("react").MemoExoticComponent<typeof AutocompleteOption>;
5
- export default _default;
3
+ export declare const AutocompleteOption: import("react").MemoExoticComponent<(<O extends OptionLike>(props: AutocompleteOptionProps<O>) => import("react/jsx-runtime").JSX.Element)>;
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo, useId } from "react";
3
3
  import { useListItem } from "@floating-ui/react";
4
- import { useAutocomplete } from ".";
4
+ import { useAutocomplete } from "./useAutocompleteContext";
5
5
  import clsx from "clsx";
6
6
  import { getOptionLabel, getOptionValue } from "./util";
7
- function AutocompleteOption(props) {
7
+ export const AutocompleteOption = memo(function AutocompleteOption(props) {
8
8
  const label = getOptionLabel(props);
9
9
  const id = useId();
10
10
  const { activeIndex, selection, getItemProps, handleSelect } = useAutocomplete();
@@ -14,5 +14,4 @@ function AutocompleteOption(props) {
14
14
  return (_jsx("div", { className: clsx("option", isSelected ? "bg-gray-2" : isActive && "bg-gray-1"), ref: ref, role: "option", id: id, "aria-selected": isActive, ...getItemProps({
15
15
  onClick: () => handleSelect(index),
16
16
  }), children: label }));
17
- }
18
- export default memo(AutocompleteOption);
17
+ });
@@ -1,6 +1,6 @@
1
- import { AutocompleteProps } from ".";
1
+ import { AutocompleteProps } from "./Autocomplete";
2
2
  import { OptionLike, Option } from "../select";
3
- interface Props<O extends OptionLike = Option> extends Pick<AutocompleteProps<O>, "className" | "icon" | "color" | "selectionSuffix" | "noSearchSuffix" | "placement" | "placeholder" | "selection" | "onChangeSelection" | "autocompleteOptionComponent" | "loading" | "clearSearchButton"> {
3
+ interface Props<O extends OptionLike = Option> extends Pick<AutocompleteProps<O>, "className" | "icon" | "color" | "selectionSuffix" | "noSearchSuffix" | "placement" | "placeholder" | "selection" | "onChangeSelection" | "autocompleteOptionComponent" | "loading" | "clearSearchButton" | "readOnly"> {
4
4
  onChangeSearchValueCallback: (searchValue: string) => Promise<O[]>;
5
5
  debounce?: number;
6
6
  }
@@ -1,13 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
- import { Autocomplete } from ".";
3
+ import { Autocomplete } from "./Autocomplete";
4
4
  import { getOptionLabel } from "./util";
5
5
  import { useStateDebounce, useEventCallback } from "../../hooks";
6
6
  export function LazyAutocomplete({ onChangeSearchValueCallback, debounce = 5000, selection = null, onChangeSelection, ...rest }) {
7
7
  const onChangeSelectionStable = useEventCallback(onChangeSelection);
8
8
  const onChangeSearchValueCallbackStable = useEventCallback(onChangeSearchValueCallback);
9
9
  const [searchValue, searchValueDebounced, setSearchValue] = useStateDebounce(selection ? getOptionLabel(selection) : "", debounce);
10
- // console.log(searchValue, searchValueDebounced);
11
10
  const searchValueRef = useRef(searchValue);
12
11
  searchValueRef.current = searchValue;
13
12
  const inputRef = useRef(null);
@@ -1,6 +1,6 @@
1
- import { AutocompleteProps } from ".";
1
+ import { AutocompleteProps } from "./Autocomplete";
2
2
  import { Option, OptionLike } from "../select";
3
- interface Props<O extends OptionLike = Option> extends Pick<AutocompleteProps<O>, "className" | "icon" | "color" | "placement" | "placeholder" | "selection" | "onChangeSelection" | "autocompleteOptionComponent" | "options" | "selection"> {
3
+ interface Props<O extends OptionLike = Option> extends Pick<AutocompleteProps<O>, "className" | "icon" | "color" | "placement" | "placeholder" | "selection" | "onChangeSelection" | "autocompleteOptionComponent" | "options" | "selection" | "readOnly"> {
4
4
  }
5
5
  export declare function SimpleAutocomplete<O extends OptionLike = Option>({ options, selection, onChangeSelection, ...rest }: Props<O>): import("react/jsx-runtime").JSX.Element;
6
6
  export {};
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useLayoutEffect, useRef, useState } from "react";
3
- import { Autocomplete } from ".";
3
+ import { Autocomplete } from "./Autocomplete";
4
4
  import { useEventCallback } from "../../hooks";
5
5
  import { getOptionLabel } from "./util";
6
6
  export function SimpleAutocomplete({ options, selection = null, onChangeSelection, ...rest }) {
@@ -1,2 +1,3 @@
1
1
  import { Option } from "../select";
2
2
  export declare const options: Option[];
3
+ export declare const handleChangeSearchValue: (searchValue: string) => Promise<Option[]>;
@@ -1,3 +1,4 @@
1
+ import Fuse from "fuse.js";
1
2
  export const options = [
2
3
  { value: "abbeville", label: "Abbeville" },
3
4
  { value: "agde", label: "Agde" },
@@ -23,3 +24,23 @@ export const options = [
23
24
  { value: "avoriaz", label: "Avoriaz" },
24
25
  { value: "avray", label: "Avray" },
25
26
  ];
27
+ async function mockServerRequest(searchValue) {
28
+ await new Promise((resolve) => {
29
+ setTimeout(resolve, Math.random() * 1000);
30
+ });
31
+ const res = await fetch(`/town-74.json`);
32
+ const towns = (await res.json());
33
+ const fuse = new Fuse(towns, {
34
+ minMatchCharLength: 2,
35
+ keys: ["nom_commune"],
36
+ });
37
+ const results = fuse.search(searchValue);
38
+ return results.map(({ item }) => ({
39
+ label: item.context,
40
+ value: item.insee,
41
+ }));
42
+ }
43
+ export const handleChangeSearchValue = async (searchValue) => {
44
+ const results = await mockServerRequest(searchValue);
45
+ return results;
46
+ };
@@ -1,6 +1,6 @@
1
- export { default as Autocomplete, type AutocompleteProps } from "./Autocomplete";
1
+ export { Autocomplete, type AutocompleteProps } from "./Autocomplete";
2
2
  export { SimpleAutocomplete } from "./SimpleAutocomplete";
3
- export { default as AutocompleteOption } from "./AutocompleteOption";
3
+ export { AutocompleteOption } from "./AutocompleteOption";
4
4
  export { LazyAutocomplete } from "./LazyAutocomplete";
5
5
  export { useAutocomplete } from "./useAutocompleteContext";
6
6
  export { getOptionValue, getOptionLabel } from "./util";
@@ -1,6 +1,6 @@
1
- export { default as Autocomplete } from "./Autocomplete";
1
+ export { Autocomplete } from "./Autocomplete";
2
2
  export { SimpleAutocomplete } from "./SimpleAutocomplete";
3
- export { default as AutocompleteOption } from "./AutocompleteOption";
3
+ export { AutocompleteOption } from "./AutocompleteOption";
4
4
  export { LazyAutocomplete } from "./LazyAutocomplete";
5
5
  export { useAutocomplete } from "./useAutocompleteContext";
6
6
  export { getOptionValue, getOptionLabel } from "./util";
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import clsx from "clsx";
3
- import { buttonVariants } from "../button";
3
+ import { buttonVariants } from "../button/Button";
4
4
  import { Href } from "../href";
5
- import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip";
5
+ import { Tooltip } from "../tooltip/Tooltip";
6
+ import { TooltipContent } from "../tooltip/TooltipContent";
7
+ import { TooltipTrigger } from "../tooltip/TooltipTrigger";
6
8
  export function Badge({ children, className, onRemove, onClick, tooltip, url, color = "yellow", }) {
7
9
  const badge = (_jsxs("span", { className: clsx("ll-badge", "inline-flex w-fit items-stretch overflow-hidden rounded-full text-xs shadow", buttonVariants.variant.contained(color),
8
10
  // badgeVariants.color[color],
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cleanup, fireEvent, render } from "@testing-library/react";
3
3
  import { describe, it, expect, vi, afterEach } from "vitest";
4
- import { Button } from ".";
4
+ import { Button } from "./Button";
5
5
  afterEach(cleanup);
6
6
  describe("<Button />", () => {
7
7
  it("forwards className", () => {
@@ -1,7 +1,7 @@
1
1
  import { jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef, useImperativeHandle, useRef } from "react";
3
3
  import clsx from "clsx";
4
- import { useRipple } from "../../hooks";
4
+ import { useRipple } from "../../hooks/useRipple";
5
5
  import { buttonVariants } from "./Button";
6
6
  export const LinkButton = forwardRef(function LinkButton({ withRipple = true, variant = "contained", color = "yellow", size = "medium", focusable = true, fullWidth, className, children, selected = false, icon = false, href, ...props }, ref) {
7
7
  const anchorRef = useRef(null);
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Children, cloneElement, isValidElement, useEffect, useRef, useState, } from "react";
3
3
  import { FloatingFocusManager, FloatingPortal, autoUpdate, flip, offset, shift, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, useTypeahead, } from "@floating-ui/react";
4
- import { Dialog } from "../dialog";
4
+ import { Dialog } from "../dialog/Dialog";
5
5
  import { useEventCallback, useRefDebounce } from "../../hooks";
6
6
  export function ContextMenu({ targetRef, children, style, eventName = "contextmenu" }) {
7
7
  const [activeIndex, setActiveIndex] = useState(null);
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { DropdownMenuContext, useDropdownMenu } from ".";
2
+ import { DropdownMenuContext } from "./useDropdownMenuContext";
3
+ import { useDropdownMenu } from "./useDropdownMenu";
3
4
  export function DropdownMenu({ children, ...options }) {
4
5
  const popover = useDropdownMenu(options);
5
6
  return _jsx(DropdownMenuContext.Provider, { value: popover, children: children });
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { useDropdownMenuContext } from ".";
3
+ import { useDropdownMenuContext } from "./useDropdownMenuContext";
4
4
  import { FloatingFocusManager, FloatingList, FloatingPortal, useMergeRefs, } from "@floating-ui/react";
5
5
  import clsx from "clsx";
6
6
  import { Dialog } from "../dialog";
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useListItem } from "@floating-ui/react";
3
3
  import clsx from "clsx";
4
- import { useDropdownMenuContext } from ".";
4
+ import { useDropdownMenuContext } from "./useDropdownMenuContext";
5
5
  export function DropdownMenuItem({ children, onClick, ...rest }) {
6
6
  const { activeIndex, getItemProps, handleSelect } = useDropdownMenuContext();
7
7
  const { ref, index } = useListItem({ label: children?.toString() });
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cloneElement, forwardRef, isValidElement } from "react";
3
- import { useDropdownMenuContext } from ".";
3
+ import { useDropdownMenuContext } from "./useDropdownMenuContext";
4
4
  import { useMergeRefs } from "@floating-ui/react";
5
5
  import { Button } from "../button";
6
6
  export const DropdownMenuTrigger = forwardRef(({ children, asChild = false, ...props }, propRef) => {
@@ -1,4 +1,4 @@
1
- import { useDropdownMenu } from ".";
1
+ import { useDropdownMenu } from "./useDropdownMenu";
2
2
  type ContextType = ReturnType<typeof useDropdownMenu> | null;
3
3
  export declare const DropdownMenuContext: import("react").Context<ContextType>;
4
4
  export declare function useDropdownMenuContext(): {
@@ -1,4 +1,4 @@
1
- import { Button, type ButtonProps } from "../button";
1
+ import { Button, type ButtonProps } from "../button/Button";
2
2
  export interface Props extends ButtonProps {
3
3
  label: string;
4
4
  triggerComponent: typeof Button;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { MenuItemWithChildren } from ".";
3
+ import { MenuItemWithChildren } from "./MenuItemWithChildren";
4
4
  import { FloatingTree } from "@floating-ui/react";
5
5
  export const DropdownMenuNested = forwardRef((props, ref) => {
6
6
  return (_jsx(FloatingTree, { children: _jsx(MenuItemWithChildren, { ...props, ref: ref }) }));
@@ -1,4 +1,4 @@
1
- import { Button, type ButtonProps } from "../button";
1
+ import { Button, type ButtonProps } from "../button/Button";
2
2
  export interface Props extends ButtonProps {
3
3
  label?: string;
4
4
  triggerComponent?: typeof Button;
@@ -3,8 +3,8 @@ import { FloatingFocusManager, FloatingList, FloatingNode, FloatingPortal, autoU
3
3
  import { forwardRef, useContext, useEffect, useRef, useState } from "react";
4
4
  import { MenuContext } from "./MenuContext";
5
5
  import clsx from "clsx";
6
- import { Button } from "../button";
7
- import { Dialog } from "../dialog";
6
+ import { Button } from "../button/Button";
7
+ import { Dialog } from "../dialog/Dialog";
8
8
  export const MenuItemWithChildren = forwardRef(({ children, label, triggerComponent: TriggerComponent = Button, ...props }, forwardedRef) => {
9
9
  const [isOpen, setIsOpen] = useState(false);
10
10
  const [hasFocusInside, setHasFocusInside] = useState(false);
@@ -1,7 +1,6 @@
1
1
  import { ComponentPropsWithRef, ReactNode } from "react";
2
- interface Props extends ComponentPropsWithRef<"a"> {
2
+ export interface Props extends ComponentPropsWithRef<"a"> {
3
3
  children: ReactNode;
4
4
  ghost?: boolean;
5
5
  }
6
6
  export declare const Href: (props: Props & import("react").RefAttributes<HTMLAnchorElement>) => React.ReactElement | null;
7
- export {};
@@ -7,5 +7,5 @@ export const Color = forwardRef(({ value, withRipple = true, color = "yellow", l
7
7
  const buttonRef = useRef(null);
8
8
  useImperativeHandle(ref, () => buttonRef.current);
9
9
  const ripples = useRipple(buttonRef);
10
- return (_jsxs("button", { ref: buttonRef, "data-color": color, className: "p8n-input-text relative flex h-8 overflow-clip rounded-2xl p-1 outline-offset-[-1px]", ...rest, children: [withRipple && ripples, _jsx("span", { className: clsx("flex items-center justify-center rounded-2xl px-2", valueToShow === null && "min-w-12", className), style: { backgroundColor: value }, children: valueToShow })] }));
10
+ return (_jsxs("button", { ref: buttonRef, "data-color": color, className: "p8n-input-text relative flex h-8 overflow-clip rounded-2xl p-1 outline-offset-[-1px]", ...rest, children: [withRipple && ripples, _jsx("span", { className: clsx("flex h-full items-center justify-center rounded-2xl px-2", valueToShow === null && "min-w-12", className), style: { backgroundColor: value }, children: valueToShow })] }));
11
11
  });
@@ -5,11 +5,15 @@ export const inputConfig = {
5
5
  container: "p8n-input-text rounded-2xl outline-offset-[-1px] flex ",
6
6
  input: "h-8 flex-1 appearance-none outline-none filter-none min-w-0 bg-transparent",
7
7
  };
8
- export const Input = forwardRef(({ variant = "normal", color = "yellow", disabled = false, prefix, suffix, className, ...rest }, ref) => {
9
- return (_jsxs("div", { "data-color": color, "data-variant": variant, className: clsx(inputConfig.container, disabled && "disabled", className), children: [prefix && (_jsx("div", { className: clsx([
8
+ export const Input = forwardRef(({ variant = "normal", color = "yellow", disabled = false, prefix, suffix, className, readOnly, ...rest }, ref) => {
9
+ return (_jsxs("div", { "data-color": color, "data-variant": variant, className: clsx(inputConfig.container, disabled && "disabled", readOnly && "readonly", className), children: [prefix && (_jsx("div", { className: clsx([
10
10
  "relative flex-center",
11
11
  typeof prefix === "string" && "mx-2 select-none text-gray-6",
12
- ]), children: prefix })), _jsx("input", { ref: ref, className: clsx(inputConfig.input, !prefix && "pl-4", !suffix && "pr-4"), ...rest, disabled: disabled }), suffix && (_jsx("div", { className: clsx([
12
+ ]), children: prefix })), _jsx("input", { ref: ref, className: clsx(inputConfig.input, !prefix && "pl-4", !suffix && "pr-4"), disabled: disabled, readOnly: readOnly, onFocus: () => {
13
+ if (readOnly) {
14
+ document.activeElement?.select();
15
+ }
16
+ }, ...rest }), suffix && (_jsx("div", { className: clsx([
13
17
  "relative flex-center",
14
18
  typeof suffix === "string" && "mx-2 select-none text-gray-6",
15
19
  ]), children: suffix }))] }));
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { describe, it, expect } from "vitest";
3
3
  import { render } from "@testing-library/react";
4
- import { Input } from ".";
4
+ import { Input } from "./Input";
5
5
  describe("Input component", () => {
6
6
  it("forward className to <input> element", () => {
7
7
  const { container } = render(_jsx(Input, { className: "custom" }));
@@ -8,6 +8,6 @@ interface InputFieldOwnProps {
8
8
  warning?: ReactNode | boolean;
9
9
  }
10
10
  declare const defaultElement: (props: import("../input/Input").InputProps & import("react").RefAttributes<HTMLInputElement>) => React.ReactElement | null;
11
- type Props<E extends ElementType> = PolymorphicPropsWithRef<InputFieldOwnProps, E>;
11
+ export type Props<E extends ElementType> = PolymorphicPropsWithRef<InputFieldOwnProps, E>;
12
12
  export declare const InputField: <E extends ElementType = typeof defaultElement>(props: Props<E>) => ReactNode;
13
13
  export {};
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useModalContext } from ".";
2
+ import { useModalContext } from "./useModalContext";
3
3
  import clsx from "clsx";
4
- import { Button } from "../button";
5
- import { Scroll } from "../scroll";
4
+ import { Button } from "../button/Button";
5
+ import { Scroll } from "../scroll/Scroll";
6
6
  export function ModalHeader({ children, className, closeButton = true, ...props }) {
7
7
  const { setOpen } = useModalContext();
8
8
  return (_jsxs(_Fragment, { children: [closeButton && (_jsx("div", { className: "float-right p-1", children: _jsx(Button, { icon: true, variant: "text", color: "gray", onClick: () => setOpen(false), children: _jsx("i", { className: "fe-cancel" }) }) })), _jsx("header", { className: clsx("flex items-center px-2 pt-2", className), ...props, children: _jsx("h4", { className: "font-semibold leading-6", children: children }) })] }));
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useMergeRefs, } from "@floating-ui/react";
3
3
  import { forwardRef } from "react";
4
- import { useModalContext } from ".";
4
+ import { useModalContext } from "./useModalContext";
5
5
  import clsx from "clsx";
6
- import { Dialog } from "../dialog";
6
+ import { Dialog } from "../dialog/Dialog";
7
7
  export const ModalContent = forwardRef(({ style, className, children, ...props }, propRef) => {
8
8
  const context = useModalContext();
9
9
  const floatingContext = context.context;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cloneElement, forwardRef, isValidElement } from "react";
3
3
  import { useMergeRefs } from "@floating-ui/react";
4
- import { Button } from "../button";
5
- import { useModalContext } from ".";
4
+ import { Button } from "../button/Button";
5
+ import { useModalContext } from "./useModalContext";
6
6
  export const ModalTrigger = forwardRef(({ children, asChild = false, ...props }, propRef) => {
7
7
  const context = useModalContext();
8
8
  const childrenRef = children.ref;
@@ -3,7 +3,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { createPortal } from "react-dom";
5
5
  import { NotificationsContext, createNotificationsManager, } from "./NotificationsContext";
6
- import { Snack } from "../snack";
6
+ import { Snack } from "../snack/Snack";
7
7
  export function NotificationsProvider({ children }) {
8
8
  const [notifications, setNotifications] = useState([]);
9
9
  const container = useRef(null);
@@ -1,6 +1,6 @@
1
1
  import { useCallback } from "react";
2
2
  import { fetchAPI } from "../../lib";
3
- import { useContextNotifications } from ".";
3
+ import { useContextNotifications } from "./useContextNotifications";
4
4
  export const useFetch = () => {
5
5
  // is it the good useContextNotifications ? from redux or not ??
6
6
  const notificationManager = useContextNotifications();
@@ -1,6 +1,6 @@
1
1
  import { ReactElement, ReactNode, Ref } from "react";
2
2
  import { Placement } from "@floating-ui/react";
3
- import { SelectSelectionProps } from ".";
3
+ import { SelectSelectionProps } from "./SelectSelection";
4
4
  import type { Option } from "./interface";
5
5
  export type SelectValue = number | string | null;
6
6
  type ChangeEventLike = {
@@ -2,12 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createElement as _createElement } from "react";
3
3
  import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
4
  import { FloatingFocusManager, FloatingList, FloatingPortal, autoUpdate, flip, offset, size, useClick, useDismiss, useFloating, useInteractions, useListNavigation, useMergeRefs, useRole, useTypeahead, } from "@floating-ui/react";
5
- import { SelectSelection, SelectContext } from ".";
5
+ import { SelectSelection } from "./SelectSelection";
6
+ import { SelectContext } from "./useSelectContext";
6
7
  import clsx from "clsx";
7
- import { Input } from "../input";
8
- import { Button } from "../button";
9
- import { useEventCallback } from "../../hooks";
10
- import { Dialog } from "../dialog";
8
+ import { Input } from "../input/Input";
9
+ import { Button } from "../button/Button";
10
+ import { useEventCallback } from "../../hooks/useEventCallback";
11
+ import { Dialog } from "../dialog/Dialog";
11
12
  function defaultGetSearchableValue(matchReg, option) {
12
13
  return matchReg.test(option.label.toLowerCase().trim());
13
14
  }
@@ -50,8 +51,7 @@ export const Select = forwardRef(({ variant = "normal", disabled = false, showAr
50
51
  Object.assign(elements.floating.style, {
51
52
  width: `${Math.max(floatingMinWidth, rects.reference.width)}px`,
52
53
  });
53
- const firstChild = elements.floating
54
- .firstElementChild;
54
+ const firstChild = elements.floating.firstElementChild;
55
55
  if (firstChild) {
56
56
  firstChild.style.maxHeight = `${Math.min(availableHeight, 300)}px`;
57
57
  }
@@ -85,7 +85,13 @@ export const Select = forwardRef(({ variant = "normal", disabled = false, showAr
85
85
  isTypingRef.current = isTyping;
86
86
  },
87
87
  });
88
- const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([listNav, typeahead, click, dismiss, role]);
88
+ const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
89
+ listNav,
90
+ typeahead,
91
+ click,
92
+ dismiss,
93
+ role,
94
+ ]);
89
95
  useEffect(() => {
90
96
  if (SelectOptionCustomComponent) {
91
97
  return;
@@ -126,9 +132,7 @@ export const Select = forwardRef(({ variant = "normal", disabled = false, showAr
126
132
  }, ...getFloatingProps(), children: _jsxs(Dialog, { placement: context.placement, className: "max-h-80 overflow-auto motion-safe:animate-fade-in-list", children: [searchable && (_jsx("div", { className: "p-2", children: _jsx(Input, { color: "gray", placeholder: "Search", tabIndex: selectedIndex === null ? 0 : -1, value: search, onChange: handleSearchChange, onFocus: () => setSearchHasFocus(true), onBlur: () => setSearchHasFocus(false) }) })), SelectOptionCustomComponent ? (_jsx(FloatingList, { elementsRef: listRef, labelsRef: labelsRef, children: filteredOptions.map((option) => (_createElement(SelectOptionCustomComponent, { ...option, key: option.value }))) })) : (filteredOptions.map((option, index) => {
127
133
  const isActive = activeIndex === index;
128
134
  const isSelected = selectedIndex === index;
129
- return (_jsx("button", { className: clsx("option", isSelected
130
- ? "bg-gray-2"
131
- : isActive && "bg-gray-1"), role: "option", "aria-selected": isActive && isSelected, tabIndex: isActive ? 0 : -1, ref: (node) => {
135
+ return (_jsx("button", { className: clsx("option", isSelected ? "bg-gray-2" : isActive && "bg-gray-1"), role: "option", "aria-selected": isActive && isSelected, tabIndex: isActive ? 0 : -1, ref: (node) => {
132
136
  listRef.current[index] = node;
133
137
  }, ...getItemProps({
134
138
  onClick: () => handleSelect(index),
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { isValidElement } from "react";
3
- import { Tooltip, TooltipContent, TooltipTrigger } from ".";
3
+ import { Tooltip } from "./Tooltip";
4
+ import { TooltipContent } from "./TooltipContent";
5
+ import { TooltipTrigger } from "./TooltipTrigger";
4
6
  export function SimpleTooltip({ content, children, contentClassName, ...options }) {
5
7
  return (_jsxs(Tooltip, { ...options, children: [_jsx(TooltipContent, { className: contentClassName, children: content }), _jsx(TooltipTrigger, { asChild: isValidElement(children), children: children })] }));
6
8
  }
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useTooltip, TooltipContext } from ".";
2
+ import { useTooltip } from "./useTooltip";
3
+ import { TooltipContext } from "./useTooltipContext";
3
4
  export function Tooltip({ children, ...options }) {
4
5
  const tooltip = useTooltip(options);
5
6
  return _jsx(TooltipContext.Provider, { value: tooltip, children: children });
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cleanup, fireEvent, render } from "@testing-library/react";
3
3
  import { afterEach, describe, expect, it } from "vitest";
4
- import { SimpleTooltip } from ".";
4
+ import { SimpleTooltip } from "./SimpleTooltip";
5
5
  afterEach(cleanup);
6
6
  describe("<Tooltip />", () => {
7
7
  it("show the popup", async () => {
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { useTooltipContext } from ".";
3
+ import { useTooltipContext } from "./useTooltipContext";
4
4
  import { FloatingPortal, useMergeRefs } from "@floating-ui/react";
5
5
  import clsx from "clsx";
6
6
  import { computeArrowStyle } from "../dialog/util";
7
- import { Dialog } from "../dialog";
7
+ import { Dialog } from "../dialog/Dialog";
8
8
  export const TooltipContent = forwardRef(({ style, children, className, ...props }, propRef) => {
9
9
  const context = useTooltipContext();
10
10
  const ref = useMergeRefs([context.refs.setFloating, propRef]);
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cloneElement, forwardRef, isValidElement } from "react";
3
- import { useTooltipContext } from ".";
3
+ import { useTooltipContext } from "./useTooltipContext";
4
4
  import { useMergeRefs } from "@floating-ui/react";
5
5
  export const TooltipTrigger = forwardRef(({ children, asChild = false, ...props }, propRef) => {
6
6
  const context = useTooltipContext();
@@ -1,4 +1,4 @@
1
- import { useTooltip } from ".";
1
+ import { useTooltip } from "./useTooltip";
2
2
  type ContextType = ReturnType<typeof useTooltip> | null;
3
3
  export declare const TooltipContext: import("react").Context<ContextType>;
4
4
  export declare function useTooltipContext(): {
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
- import { useDebounce } from ".";
3
+ import { useDebounce } from "./useDebounce";
4
4
  /**
5
5
  * This hook accepts a ref to any element and adds a click event handler that creates ripples when click
6
6
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentatrion-design",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "Hugues Tavernier",
package/tailwind/base.js CHANGED
@@ -57,4 +57,46 @@ export const base = {
57
57
  abbr: {
58
58
  "@apply cursor-help underline decoration-dashed": {},
59
59
  },
60
+ '[data-color="yellow"]': {
61
+ "--color-custom-1": "var(--color-yellow-1);",
62
+ "--color-custom-2": "var(--color-yellow-2);",
63
+ "--color-custom-3": "var(--color-yellow-3);",
64
+ "--color-custom-4": "var(--color-yellow-4);",
65
+ "--color-custom-5": "var(--color-yellow-5);",
66
+ },
67
+ '[data-color="gray"]': {
68
+ "--color-custom-1": "var(--color-gray-1);",
69
+ "--color-custom-2": "var(--color-gray-2);",
70
+ "--color-custom-3": "var(--color-gray-3);",
71
+ "--color-custom-4": "var(--color-gray-4);",
72
+ "--color-custom-5": "var(--color-gray-5);",
73
+ },
74
+ '[data-color="red"]': {
75
+ "--color-custom-1": "var(--color-red-1);",
76
+ "--color-custom-2": "var(--color-red-2);",
77
+ "--color-custom-3": "var(--color-red-3);",
78
+ "--color-custom-4": "var(--color-red-4);",
79
+ "--color-custom-5": "var(--color-red-5);",
80
+ },
81
+ '[data-color="orange"]': {
82
+ "--color-custom-1": "var(--color-orange-1);",
83
+ "--color-custom-2": "var(--color-orange-2);",
84
+ "--color-custom-3": "var(--color-orange-3);",
85
+ "--color-custom-4": "var(--color-orange-4);",
86
+ "--color-custom-5": "var(--color-orange-5);",
87
+ },
88
+ '[data-color="green"]': {
89
+ "--color-custom-1": "var(--color-green-1);",
90
+ "--color-custom-2": "var(--color-green-2);",
91
+ "--color-custom-3": "var(--color-green-3);",
92
+ "--color-custom-4": "var(--color-green-4);",
93
+ "--color-custom-5": "var(--color-green-5);",
94
+ },
95
+ '[data-color="blue"]': {
96
+ "--color-custom-1": "var(--color-blue-1);",
97
+ "--color-custom-2": "var(--color-blue-2);",
98
+ "--color-custom-3": "var(--color-blue-3);",
99
+ "--color-custom-4": "var(--color-blue-4);",
100
+ "--color-custom-5": "var(--color-blue-5);",
101
+ },
60
102
  };
@@ -186,46 +186,19 @@ export const componentsResizeArea = {
186
186
  };
187
187
  export const componentsInputOutline = {
188
188
  ":is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea)": {
189
- "@apply outline outline-1 focus-full:outline-2": {},
189
+ "@apply outline outline-1 outline-[rgb(var(--color-custom-2))] hover:outline-[rgb(var(--color-custom-3))] focus-full:outline-[rgb(var(--color-custom-4))]": {},
190
190
  },
191
191
  ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="yellow"])': {
192
- "@apply outline-gray-2 hover:outline-gray-3 focus-full:outline-yellow-4": {},
192
+ "@apply outline-gray-2 hover:outline-gray-3": {},
193
193
  },
194
- ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="gray"])': {
195
- "@apply outline-gray-2 hover:outline-gray-3 focus-full:outline-gray-4": {},
196
- },
197
- ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="red"])': {
198
- "@apply outline-red-2 hover:outline-red-3 focus-full:outline-red-4": {},
199
- },
200
- ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="orange"])': {
201
- "@apply outline-orange-2 hover:outline-orange-3 focus-full:outline-orange-4": {},
202
- },
203
- ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="blue"])': {
204
- "@apply outline-blue-2 hover:outline-blue-3 focus-full:outline-blue-4": {},
205
- },
206
- ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-color="green"])': {
207
- "@apply outline-green-2 hover:outline-green-3 focus-full:outline-green-4": {},
194
+ ":is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):not([readonly], .readonly)": {
195
+ "@apply focus-full:outline-2": {},
208
196
  },
209
197
  ':is(.p8n-input-checkbox, .p8n-input-radio, .p8n-input-text, .p8n-textarea):where([data-variant="ghost"])': {
210
198
  "@apply outline-transparent": {},
211
199
  },
212
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="yellow"])': {
213
- "@apply text-yellow-3": {},
214
- },
215
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="gray"])': {
216
- "@apply text-gray-3": {},
217
- },
218
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="red"])': {
219
- "@apply text-red-3": {},
220
- },
221
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="orange"])': {
222
- "@apply text-orange-3": {},
223
- },
224
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="blue"])': {
225
- "@apply text-blue-3": {},
226
- },
227
- ':is(.p8n-input-checkbox, .p8n-input-radio):where([data-color="green"])': {
228
- "@apply text-green-3": {},
200
+ ":is(.p8n-input-checkbox, .p8n-input-radio)": {
201
+ "@apply text-[rgb(var(--color-custom-3))]": {},
229
202
  },
230
203
  ":is(.p8n-input-checkbox, .p8n-input-radio):is(:checked, .checked, .indeterminate)": {
231
204
  "@apply bg-full bg-center bg-no-repeat outline-gray-1 bg-current": {},
@@ -257,6 +230,9 @@ export const components = {
257
230
  opacity: "0.5",
258
231
  },
259
232
  },
233
+ "input[readonly]": {
234
+ color: "rgb(var(--color-gray-6))",
235
+ },
260
236
  ".option": {
261
237
  "@apply flex w-full px-2 h-8 items-center text-left relative cursor-pointer first:rounded-t-2xl last:rounded-b-2xl hover:bg-gray-1 focus-full:text-gray-8 outline-none": {},
262
238
  "&[disabled]": { color: "rgb(var(--color-gray-6))", pointerEvents: "none" },
@@ -45,23 +45,14 @@ export const utilitiesDialog = {
45
45
  },
46
46
  '[data-placement="right-start"]': { transformOrigin: "top left" },
47
47
  '[data-placement="right-end"]': { transformOrigin: "bottom left" },
48
- '[data-placement][data-color="yellow"] .p8n-arrow': {
49
- "@apply text-gray-0": {},
48
+ ".p8n-arrow": {
49
+ "@apply text-[rgb(var(--color-custom-1))]": {},
50
50
  },
51
- '[data-placement][data-color="gray"] .p8n-arrow': {
51
+ '[data-color="yellow"] .p8n-arrow': {
52
52
  "@apply text-gray-0": {},
53
53
  },
54
- '[data-placement][data-color="red"] .p8n-arrow': {
55
- "@apply text-red-1": {},
56
- },
57
- '[data-placement][data-color="orange"] .p8n-arrow': {
58
- "@apply text-orange-1": {},
59
- },
60
- '[data-placement][data-color="blue"] .p8n-arrow': {
61
- "@apply text-blue-1": {},
62
- },
63
- '[data-placement][data-color="green"] .p8n-arrow': {
64
- "@apply text-green-1": {},
54
+ '[data-color="gray"] .p8n-arrow': {
55
+ "@apply text-gray-0": {},
65
56
  },
66
57
  ".option[data-nested][data-open]:not([data-focus-inside])": {
67
58
  "@apply bg-gray-2": {},