@pagamio/frontend-commons-lib 0.8.333 → 0.8.335

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/api/swr.d.ts CHANGED
@@ -42,5 +42,5 @@ export declare function useApiSWRWithMutation<ResponseData>(endpoint: Key, confi
42
42
  data: ResponseData | undefined;
43
43
  error: ApiErrorResponse | undefined;
44
44
  isValidating: boolean;
45
- isLoading: import("swr/dist/_internal").IsLoadingResponse<Data, Config>;
45
+ isLoading: import("swr/_internal").IsLoadingResponse<Data, Config>;
46
46
  };
@@ -1,5 +1,5 @@
1
1
  import * as LabelPrimitive from '@radix-ui/react-label';
2
2
  import { type VariantProps } from 'class-variance-authority';
3
3
  import * as React from 'react';
4
- declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string> & React.RefAttributes<HTMLLabelElement>>;
4
+ declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: import("class-variance-authority/types").ClassProp | undefined) => string> & React.RefAttributes<HTMLLabelElement>>;
5
5
  export default Label;
@@ -16,6 +16,8 @@ export interface PagamioSearchableComboboxProps<T extends {
16
16
  selectedOption?: T | null;
17
17
  /** Trigger placeholder when nothing is selected. */
18
18
  placeholder?: string;
19
+ /** Search-input placeholder inside the dropdown. */
20
+ searchPlaceholder?: string;
19
21
  /** Shown in dropdown when no results match. */
20
22
  emptyMessage?: string;
21
23
  /** Shown at the bottom of the list when the server returned a full page. */
@@ -25,8 +27,6 @@ export interface PagamioSearchableComboboxProps<T extends {
25
27
  disabled?: boolean;
26
28
  required?: boolean;
27
29
  name?: string;
28
- /** Allow clearing the selected value via an inline ✕. Default true. */
29
- clearable?: boolean;
30
30
  /** How to render an option as a string label. Default: `o.name` (must exist). */
31
31
  getLabel?: (option: T) => string;
32
32
  /** Optional custom row renderer inside the dropdown. */
@@ -39,4 +39,4 @@ export interface PagamioSearchableComboboxProps<T extends {
39
39
  }
40
40
  export declare function PagamioSearchableCombobox<T extends {
41
41
  id: string;
42
- }>({ combobox, value, onChange, selectedOption, placeholder, emptyMessage, cappedMessage, loadingMessage, disabled, required, name, clearable, getLabel, renderOption, renderSelected, className, triggerClassName, contentClassName, }: PagamioSearchableComboboxProps<T>): import("react/jsx-runtime").JSX.Element;
42
+ }>({ combobox, value, onChange, selectedOption, placeholder, searchPlaceholder, emptyMessage, cappedMessage, loadingMessage, disabled, required, name, getLabel, renderOption, renderSelected, className, triggerClassName, contentClassName, }: PagamioSearchableComboboxProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -2,24 +2,34 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  /**
3
3
  * PagamioSearchableCombobox — server-driven, debounced, single-select combobox.
4
4
  *
5
- * Built on top of the existing Command (cmdk) primitive + Popover.
5
+ * Visual contract: matches the look & feel of `Select` + `SelectContent` with
6
+ * the embedded search input (the "Authentication Method" picker in the
7
+ * employees form is the reference). Trigger styling, dropdown shadow/border,
8
+ * and selected-item highlight all mirror `Select`.
9
+ *
6
10
  * State is owned by `usePagamioCombobox` (created by the caller).
7
11
  *
8
12
  * See .agent/conventions/lookup-endpoints.md (backend) for the contract.
9
13
  */
10
- import { CheckIcon, ChevronDownIcon, Cross2Icon } from '@radix-ui/react-icons';
14
+ import { CheckIcon, ChevronDownIcon } from '@radix-ui/react-icons';
11
15
  import * as React from 'react';
12
16
  import { cn } from '../../helpers';
13
- import { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from './Command';
14
17
  import { Popover, PopoverContent, PopoverTrigger } from './Popover';
15
18
  function defaultGetLabel(option) {
16
- // Assumes `name` exists. Override via `getLabel` for resources that use
17
- // a different display field.
18
19
  const o = option;
19
20
  return o.name ?? option.id;
20
21
  }
21
- export function PagamioSearchableCombobox({ combobox, value, onChange, selectedOption, placeholder = 'Select…', emptyMessage = 'No results.', cappedMessage = 'Showing top results — refine your search.', loadingMessage = 'Loading…', disabled, required, name, clearable = true, getLabel = defaultGetLabel, renderOption, renderSelected, className, triggerClassName, contentClassName, }) {
22
+ export function PagamioSearchableCombobox({ combobox, value, onChange, selectedOption, placeholder = 'Select…', searchPlaceholder = 'Search...', emptyMessage = 'No options found', cappedMessage = 'Showing top results — refine your search.', loadingMessage = 'Loading…', disabled, required, name, getLabel = defaultGetLabel, renderOption, renderSelected, className, triggerClassName, contentClassName, }) {
22
23
  const [open, setOpen] = React.useState(false);
24
+ const inputRef = React.useRef(null);
25
+ // Focus the search input when the popover opens — matches the Select's
26
+ // built-in behavior where the search field is immediately ready.
27
+ React.useEffect(() => {
28
+ if (open) {
29
+ const id = window.setTimeout(() => inputRef.current?.focus(), 0);
30
+ return () => window.clearTimeout(id);
31
+ }
32
+ }, [open]);
23
33
  // Resolve the option object for the current value: caller-supplied wins,
24
34
  // then the hook's options (top-N), then restored.
25
35
  const resolvedSelected = React.useMemo(() => {
@@ -33,16 +43,20 @@ export function PagamioSearchableCombobox({ combobox, value, onChange, selectedO
33
43
  onChange(id === value ? null : id);
34
44
  setOpen(false);
35
45
  };
36
- const handleClear = (e) => {
37
- e.stopPropagation();
38
- onChange(null);
39
- };
40
- return (_jsxs("div", { className: cn('w-full', className), children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-required": required, disabled: disabled, name: name, className: cn('flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border bg-background text-foreground px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground', 'focus:outline-none focus:ring-1 focus:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50', triggerClassName), children: [_jsx("span", { className: cn('line-clamp-1 text-left flex-1', !resolvedSelected && 'text-muted-foreground'), children: resolvedSelected
46
+ return (_jsxs("div", { className: cn('w-full', className), children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-required": required, disabled: disabled, name: name, className: cn(
47
+ // Mirrors SelectTrigger styling exactly.
48
+ 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border bg-background text-foreground px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground', 'focus:outline-none focus:ring-1 focus:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50', '[&>span]:line-clamp-1', triggerClassName), children: [_jsx("span", { className: cn('line-clamp-1 text-left flex-1', !resolvedSelected && 'text-muted-foreground'), children: resolvedSelected
41
49
  ? renderSelected
42
50
  ? renderSelected(resolvedSelected)
43
51
  : getLabel(resolvedSelected)
44
- : placeholder }), clearable && resolvedSelected && !disabled ? (_jsx("span", { role: "button", tabIndex: -1, "aria-label": "Clear selection", onClick: handleClear, onMouseDown: (e) => e.preventDefault(), className: "ml-2 inline-flex h-4 w-4 items-center justify-center rounded-sm opacity-60 hover:opacity-100", children: _jsx(Cross2Icon, { className: "h-3 w-3" }) })) : (_jsx(ChevronDownIcon, { className: "ml-2 h-4 w-4 opacity-50 shrink-0" }))] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 4, className: cn('p-0 w-[var(--radix-popover-trigger-width)] min-w-[240px]', contentClassName), children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: placeholder, value: combobox.search, onValueChange: combobox.setSearch }), _jsx(CommandList, { children: combobox.isLoading && combobox.options.length === 0 ? (_jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: loadingMessage })) : combobox.error ? (_jsx("div", { className: "py-6 text-center text-sm text-destructive", children: combobox.error.message || 'Failed to load options.' })) : combobox.options.length === 0 ? (_jsx(CommandEmpty, { children: emptyMessage })) : (_jsxs(_Fragment, { children: [combobox.options.map((option) => {
45
- const isSelected = option.id === value;
46
- return (_jsx(CommandItem, { value: option.id, onSelect: () => handleSelect(option.id), children: renderOption ? (renderOption(option, isSelected)) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 line-clamp-1", children: getLabel(option) }), isSelected ? _jsx(CheckIcon, { className: "ml-2 h-4 w-4 opacity-100" }) : null] })) }, option.id));
47
- }), combobox.isCapped ? (_jsx("div", { className: "border-t px-3 py-2 text-xs text-muted-foreground", children: cappedMessage })) : null] })) })] }) })] }), name ? _jsx("input", { type: "hidden", name: name, value: value ?? '' }) : null] }));
52
+ : placeholder }), _jsx(ChevronDownIcon, { className: "ml-2 h-4 w-4 opacity-50 shrink-0" })] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 4,
53
+ // Mirrors SelectContent: same shadow + animation classes, popover
54
+ // background, popover-foreground text. Width matches trigger.
55
+ className: cn('p-0 w-[var(--radix-popover-trigger-width)] min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md', contentClassName), children: [_jsx("div", { className: "p-2 border-b border-border", children: _jsx("input", { ref: inputRef, type: "text", placeholder: searchPlaceholder, value: combobox.search, onChange: (e) => combobox.setSearch(e.target.value), onKeyDown: (e) => e.stopPropagation(), className: "w-full px-2 py-1 text-sm border border-input rounded bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring" }) }), _jsx("div", { className: "p-1 max-h-[200px] overflow-y-auto", children: combobox.isLoading && combobox.options.length === 0 ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: loadingMessage })) : combobox.error ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-destructive", children: combobox.error.message || 'Failed to load options.' })) : combobox.options.length === 0 ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: emptyMessage })) : (_jsxs(_Fragment, { children: [combobox.options.map((option) => {
56
+ const isSelected = option.id === value;
57
+ return (_jsx("button", { type: "button", role: "option", "aria-selected": isSelected, onClick: () => handleSelect(option.id), className: cn(
58
+ // Mirrors SelectItem styling: padding, hover via
59
+ // focus:bg-muted, selected via bg-accent.
60
+ 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none text-left', 'hover:bg-muted focus:bg-muted focus:text-foreground', isSelected && 'bg-accent text-foreground'), children: renderOption ? (renderOption(option, isSelected)) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "line-clamp-1", children: getLabel(option) }), isSelected ? (_jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(CheckIcon, { className: "h-4 w-4" }) })) : null] })) }, option.id));
61
+ }), combobox.isCapped ? (_jsx("div", { className: "mt-1 border-t px-2 py-1.5 text-xs text-muted-foreground", children: cappedMessage })) : null] })) })] })] }), name ? _jsx("input", { type: "hidden", name: name, value: value ?? '' }) : null] }));
48
62
  }
@@ -13,6 +13,7 @@ export interface PagamioSearchableMultiComboboxProps<T extends {
13
13
  */
14
14
  selectedOptions?: readonly T[];
15
15
  placeholder?: string;
16
+ searchPlaceholder?: string;
16
17
  emptyMessage?: string;
17
18
  cappedMessage?: string;
18
19
  loadingMessage?: string;
@@ -28,4 +29,4 @@ export interface PagamioSearchableMultiComboboxProps<T extends {
28
29
  }
29
30
  export declare function PagamioSearchableMultiCombobox<T extends {
30
31
  id: string;
31
- }>({ combobox, value, onChange, selectedOptions, placeholder, emptyMessage, cappedMessage, loadingMessage, disabled, required, name, getLabel, renderOption, renderChip, className, triggerClassName, contentClassName, }: PagamioSearchableMultiComboboxProps<T>): import("react/jsx-runtime").JSX.Element;
32
+ }>({ combobox, value, onChange, selectedOptions, placeholder, searchPlaceholder, emptyMessage, cappedMessage, loadingMessage, disabled, required, name, getLabel, renderOption, renderChip, className, triggerClassName, contentClassName, }: PagamioSearchableMultiComboboxProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -2,6 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  /**
3
3
  * PagamioSearchableMultiCombobox — server-driven, debounced, multi-select combobox.
4
4
  *
5
+ * Visual contract: matches the look & feel of `Select` + `SelectContent`
6
+ * (the "Authentication Method" reference). Trigger styling is identical
7
+ * except for chip rendering. Dropdown shadow/border, embedded search,
8
+ * and item highlight all mirror `Select` / `PagamioSearchableCombobox`.
9
+ *
5
10
  * Sibling of PagamioSearchableCombobox. Differences:
6
11
  * - `value` is `string[]`, `onChange` toggles ids.
7
12
  * - The trigger shows chips for each selected option (resolved via the
@@ -13,14 +18,20 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
13
18
  import { ChevronDownIcon, Cross2Icon } from '@radix-ui/react-icons';
14
19
  import * as React from 'react';
15
20
  import { cn } from '../../helpers';
16
- import { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from './Command';
17
21
  import { Popover, PopoverContent, PopoverTrigger } from './Popover';
18
22
  function defaultGetLabel(option) {
19
23
  const o = option;
20
24
  return o.name ?? option.id;
21
25
  }
22
- export function PagamioSearchableMultiCombobox({ combobox, value, onChange, selectedOptions, placeholder = 'Select…', emptyMessage = 'No results.', cappedMessage = 'Showing top results — refine your search.', loadingMessage = 'Loading…', disabled, required, name, getLabel = defaultGetLabel, renderOption, renderChip, className, triggerClassName, contentClassName, }) {
26
+ export function PagamioSearchableMultiCombobox({ combobox, value, onChange, selectedOptions, placeholder = 'Select…', searchPlaceholder = 'Search...', emptyMessage = 'No options found', cappedMessage = 'Showing top results — refine your search.', loadingMessage = 'Loading…', disabled, required, name, getLabel = defaultGetLabel, renderOption, renderChip, className, triggerClassName, contentClassName, }) {
23
27
  const [open, setOpen] = React.useState(false);
28
+ const inputRef = React.useRef(null);
29
+ React.useEffect(() => {
30
+ if (open) {
31
+ const id = window.setTimeout(() => inputRef.current?.focus(), 0);
32
+ return () => window.clearTimeout(id);
33
+ }
34
+ }, [open]);
24
35
  // Resolve labels for currently-selected ids. Caller's `selectedOptions`
25
36
  // wins; otherwise look in the hook's options + restoredOptions.
26
37
  const selectedById = React.useMemo(() => {
@@ -35,25 +46,23 @@ export function PagamioSearchableMultiCombobox({ combobox, value, onChange, sele
35
46
  return map;
36
47
  }, [selectedOptions, combobox.options, combobox.restoredOptions]);
37
48
  const chips = React.useMemo(() => value.map((id) => selectedById.get(id)).filter((o) => o !== undefined), [value, selectedById]);
38
- // Ids in `value` that we couldn't resolve to a label — render as raw id.
39
49
  const unresolvedIds = React.useMemo(() => value.filter((id) => !selectedById.has(id)), [value, selectedById]);
40
50
  const toggle = (id) => {
41
51
  onChange(value.includes(id) ? value.filter((v) => v !== id) : [...value, id]);
42
52
  };
43
53
  const remove = (id) => onChange(value.filter((v) => v !== id));
44
- const clearAll = (e) => {
45
- e.stopPropagation();
46
- onChange([]);
47
- };
48
54
  const hasSelection = value.length > 0;
49
- return (_jsxs("div", { className: cn('w-full', className), children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-required": required, disabled: disabled, className: cn('flex min-h-9 w-full items-center justify-between whitespace-normal rounded-md border bg-background text-foreground px-2 py-1 text-sm shadow-sm ring-offset-background', 'focus:outline-none focus:ring-1 focus:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50', triggerClassName), children: [_jsx("div", { className: "flex flex-wrap gap-1 items-center flex-1 min-w-0", children: hasSelection ? (_jsxs(_Fragment, { children: [chips.map((option) => renderChip ? (_jsx(React.Fragment, { children: renderChip(option, () => remove(option.id)) }, option.id)) : (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-sm bg-muted px-1.5 py-0.5 text-xs text-foreground", children: [_jsx("span", { className: "line-clamp-1 max-w-[160px]", children: getLabel(option) }), _jsx("span", { role: "button", tabIndex: -1, "aria-label": `Remove ${getLabel(option)}`, onClick: (e) => {
55
+ return (_jsxs("div", { className: cn('w-full', className), children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-required": required, disabled: disabled, className: cn(
56
+ // Mirrors SelectTrigger styling. Slightly taller min-height so
57
+ // chips fit comfortably.
58
+ 'flex min-h-9 w-full items-center justify-between rounded-md border bg-background text-foreground px-3 py-1.5 text-sm shadow-sm ring-offset-background', 'focus:outline-none focus:ring-1 focus:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50', triggerClassName), children: [_jsx("div", { className: "flex flex-wrap gap-1 items-center flex-1 min-w-0", children: hasSelection ? (_jsxs(_Fragment, { children: [chips.map((option) => renderChip ? (_jsx(React.Fragment, { children: renderChip(option, () => remove(option.id)) }, option.id)) : (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-sm bg-muted px-1.5 py-0.5 text-xs text-foreground", children: [_jsx("span", { className: "line-clamp-1 max-w-[160px]", children: getLabel(option) }), _jsx("span", { role: "button", tabIndex: -1, "aria-label": `Remove ${getLabel(option)}`, onClick: (e) => {
50
59
  e.stopPropagation();
51
60
  remove(option.id);
52
61
  }, onMouseDown: (e) => e.preventDefault(), className: "inline-flex h-3 w-3 items-center justify-center opacity-60 hover:opacity-100", children: _jsx(Cross2Icon, { className: "h-3 w-3" }) })] }, option.id))), unresolvedIds.map((id) => (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-sm bg-muted px-1.5 py-0.5 text-xs text-muted-foreground italic", children: [_jsx("span", { className: "line-clamp-1 max-w-[140px]", children: id }), _jsx("span", { role: "button", tabIndex: -1, "aria-label": "Remove", onClick: (e) => {
53
62
  e.stopPropagation();
54
63
  remove(id);
55
- }, onMouseDown: (e) => e.preventDefault(), className: "inline-flex h-3 w-3 items-center justify-center opacity-60 hover:opacity-100", children: _jsx(Cross2Icon, { className: "h-3 w-3" }) })] }, id)))] })) : (_jsx("span", { className: "text-muted-foreground px-1", children: placeholder })) }), _jsxs("div", { className: "flex items-center", children: [hasSelection && !disabled ? (_jsx("span", { role: "button", tabIndex: -1, "aria-label": "Clear all", onClick: clearAll, onMouseDown: (e) => e.preventDefault(), className: "ml-2 inline-flex h-4 w-4 items-center justify-center rounded-sm opacity-60 hover:opacity-100", children: _jsx(Cross2Icon, { className: "h-3 w-3" }) })) : null, _jsx(ChevronDownIcon, { className: "ml-2 h-4 w-4 opacity-50 shrink-0" })] })] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 4, className: cn('p-0 w-[var(--radix-popover-trigger-width)] min-w-[240px]', contentClassName), children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: placeholder, value: combobox.search, onValueChange: combobox.setSearch }), _jsx(CommandList, { children: combobox.isLoading && combobox.options.length === 0 ? (_jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: loadingMessage })) : combobox.error ? (_jsx("div", { className: "py-6 text-center text-sm text-destructive", children: combobox.error.message || 'Failed to load options.' })) : combobox.options.length === 0 ? (_jsx(CommandEmpty, { children: emptyMessage })) : (_jsxs(_Fragment, { children: [combobox.options.map((option) => {
56
- const isSelected = value.includes(option.id);
57
- return (_jsx(CommandItem, { value: option.id, onSelect: () => toggle(option.id), children: renderOption ? (renderOption(option, isSelected)) : (_jsxs(_Fragment, { children: [_jsx("span", { className: cn('mr-2 inline-flex h-4 w-4 items-center justify-center rounded-sm border', isSelected ? 'bg-primary text-primary-foreground border-primary' : 'border-input'), children: isSelected ? '✓' : null }), _jsx("span", { className: "flex-1 line-clamp-1", children: getLabel(option) })] })) }, option.id));
58
- }), combobox.isCapped ? (_jsx("div", { className: "border-t px-3 py-2 text-xs text-muted-foreground", children: cappedMessage })) : null] })) })] }) })] }), name ? value.map((id) => _jsx("input", { type: "hidden", name: name, value: id }, id)) : null] }));
64
+ }, onMouseDown: (e) => e.preventDefault(), className: "inline-flex h-3 w-3 items-center justify-center opacity-60 hover:opacity-100", children: _jsx(Cross2Icon, { className: "h-3 w-3" }) })] }, id)))] })) : (_jsx("span", { className: "text-muted-foreground", children: placeholder })) }), _jsx(ChevronDownIcon, { className: "ml-2 h-4 w-4 opacity-50 shrink-0" })] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 4, className: cn('p-0 w-[var(--radix-popover-trigger-width)] min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md', contentClassName), children: [_jsx("div", { className: "p-2 border-b border-border", children: _jsx("input", { ref: inputRef, type: "text", placeholder: searchPlaceholder, value: combobox.search, onChange: (e) => combobox.setSearch(e.target.value), onKeyDown: (e) => e.stopPropagation(), className: "w-full px-2 py-1 text-sm border border-input rounded bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring" }) }), _jsx("div", { className: "p-1 max-h-[200px] overflow-y-auto", children: combobox.isLoading && combobox.options.length === 0 ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: loadingMessage })) : combobox.error ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-destructive", children: combobox.error.message || 'Failed to load options.' })) : combobox.options.length === 0 ? (_jsx("div", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: emptyMessage })) : (_jsxs(_Fragment, { children: [combobox.options.map((option) => {
65
+ const isSelected = value.includes(option.id);
66
+ return (_jsx("button", { type: "button", role: "option", "aria-selected": isSelected, onClick: () => toggle(option.id), className: cn('relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none text-left', 'hover:bg-muted focus:bg-muted focus:text-foreground', isSelected && 'bg-accent text-foreground'), children: renderOption ? (renderOption(option, isSelected)) : (_jsxs(_Fragment, { children: [_jsx("span", { className: cn('mr-2 inline-flex h-4 w-4 items-center justify-center rounded-sm border', isSelected ? 'bg-primary text-primary-foreground border-primary' : 'border-input'), children: isSelected ? '✓' : null }), _jsx("span", { className: "line-clamp-1", children: getLabel(option) })] })) }, option.id));
67
+ }), combobox.isCapped ? (_jsx("div", { className: "mt-1 border-t px-2 py-1.5 text-xs text-muted-foreground", children: cappedMessage })) : null] })) })] })] }), name ? value.map((id) => _jsx("input", { type: "hidden", name: name, value: id }, id)) : null] }));
59
68
  }
@@ -9,7 +9,7 @@ declare const SheetPortal: React.FC<SheetPrimitive.DialogPortalProps>;
9
9
  declare const SheetOverlay: React.ForwardRefExoticComponent<Omit<SheetPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
10
10
  declare const sheetVariants: (props?: ({
11
11
  side?: "left" | "right" | "bottom" | "top" | null | undefined;
12
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
12
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
13
  interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, VariantProps<typeof sheetVariants> {
14
14
  }
15
15
  declare const SheetContent: React.ForwardRefExoticComponent<SheetContentProps & React.RefAttributes<HTMLDivElement>>;
@@ -3,15 +3,15 @@ import * as React from 'react';
3
3
  declare const statCardVariants: (props?: ({
4
4
  variant?: "green" | "orange" | "teal" | "dark" | "light" | "primary" | "light-orange" | "light-teal" | "light-green" | null | undefined;
5
5
  size?: "sm" | "md" | "lg" | null | undefined;
6
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  declare const iconContainerVariants: (props?: ({
8
8
  variant?: "green" | "orange" | "teal" | "dark" | "light" | "primary" | "light-orange" | "light-teal" | "light-green" | null | undefined;
9
9
  size?: "sm" | "md" | "lg" | null | undefined;
10
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
10
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
11
  declare const changeIndicatorVariants: (props?: ({
12
12
  direction?: "up" | "down" | "neutral" | null | undefined;
13
13
  onSolid?: boolean | null | undefined;
14
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
15
  export interface StatCardChange {
16
16
  /** Percentage value (e.g., 22 for 22%) */
17
17
  value: number;
@@ -7,7 +7,7 @@ import type { MetricData } from '../types';
7
7
  */
8
8
  export declare const useChartData: <T = MetricData[], TransformReturnType = T>(url: string, query: QueryProps, transform?: (data: T) => TransformReturnType) => {
9
9
  data: T | TransformReturnType | undefined;
10
- error: import("../../api").ApiErrorResponse | undefined;
10
+ error: import("../..").ApiErrorResponse | undefined;
11
11
  loading: boolean;
12
12
  isEmpty: boolean;
13
13
  refresh: () => Promise<any>;
@@ -227,6 +227,7 @@ export const formatDate = (date, options) => {
227
227
  day: '2-digit',
228
228
  hour: '2-digit',
229
229
  minute: '2-digit',
230
+ hour12: false,
230
231
  ...(includeSeconds && { second: '2-digit' }),
231
232
  });
232
233
  }
@@ -57,6 +57,7 @@ const formatDateValue = (value) => {
57
57
  day: 'numeric',
58
58
  hour: '2-digit',
59
59
  minute: '2-digit',
60
+ hour12: false,
60
61
  });
61
62
  }
62
63
  // Handle ISO date strings - more comprehensive regex
@@ -72,6 +73,7 @@ const formatDateValue = (value) => {
72
73
  day: 'numeric',
73
74
  hour: '2-digit',
74
75
  minute: '2-digit',
76
+ hour12: false,
75
77
  });
76
78
  }
77
79
  }
@@ -246,6 +248,7 @@ export const exportToCsv = (data, columns, options = {}) => {
246
248
  day: 'numeric',
247
249
  hour: '2-digit',
248
250
  minute: '2-digit',
251
+ hour12: false,
249
252
  })}`;
250
253
  csvRows.push(`# ${timestamp}`);
251
254
  }
@@ -330,6 +333,7 @@ const createWorksheetData = (title, subtitle, includeTimestamp, headers, formatt
330
333
  day: 'numeric',
331
334
  hour: '2-digit',
332
335
  minute: '2-digit',
336
+ hour12: false,
333
337
  })}`;
334
338
  worksheetData.push([timestamp]);
335
339
  currentRow++;
@@ -582,6 +586,7 @@ export const exportToPdf = async (data, columns, options = {}) => {
582
586
  day: 'numeric',
583
587
  hour: '2-digit',
584
588
  minute: '2-digit',
589
+ hour12: false,
585
590
  })}`, colors, logo, } = options;
586
591
  // Create PDF document with better settings
587
592
  const doc = new jsPDF({
@@ -14,6 +14,7 @@ export const createPdfExportOptions = (config, title) => {
14
14
  day: 'numeric',
15
15
  hour: '2-digit',
16
16
  minute: '2-digit',
17
+ hour12: false,
17
18
  })}`,
18
19
  colors: {
19
20
  primary: config.theme.colors.primary,
@@ -42,6 +43,7 @@ export const createXlsxExportOptions = (config, title, sheetName) => {
42
43
  day: 'numeric',
43
44
  hour: '2-digit',
44
45
  minute: '2-digit',
46
+ hour12: false,
45
47
  })}`,
46
48
  colors: {
47
49
  primary: config.theme.colors.primary,
@@ -67,6 +69,7 @@ export const createDefaultXlsxExportOptions = (title, sheetName) => {
67
69
  day: 'numeric',
68
70
  hour: '2-digit',
69
71
  minute: '2-digit',
72
+ hour12: false,
70
73
  })}`,
71
74
  colors: {
72
75
  primary: {
package/lib/styles.css CHANGED
@@ -1488,9 +1488,6 @@ video {
1488
1488
  .min-w-\[20px\] {
1489
1489
  min-width: 20px;
1490
1490
  }
1491
- .min-w-\[240px\] {
1492
- min-width: 240px;
1493
- }
1494
1491
  .min-w-\[52px\] {
1495
1492
  min-width: 52px;
1496
1493
  }
@@ -1990,9 +1987,6 @@ video {
1990
1987
  text-overflow: ellipsis;
1991
1988
  white-space: nowrap;
1992
1989
  }
1993
- .whitespace-normal {
1994
- white-space: normal;
1995
- }
1996
1990
  .whitespace-nowrap {
1997
1991
  white-space: nowrap;
1998
1992
  }
@@ -2851,10 +2845,6 @@ video {
2851
2845
  padding-left: 0px;
2852
2846
  padding-right: 0px;
2853
2847
  }
2854
- .px-1 {
2855
- padding-left: 0.25rem;
2856
- padding-right: 0.25rem;
2857
- }
2858
2848
  .px-1\.5 {
2859
2849
  padding-left: 0.375rem;
2860
2850
  padding-right: 0.375rem;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagamio/frontend-commons-lib",
3
3
  "description": "Pagamio library for Frontend reusable components like the form engine and table container",
4
- "version": "0.8.333",
4
+ "version": "0.8.335",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "provenance": false
@@ -83,7 +83,7 @@
83
83
  "build:watch": "tsc --watch",
84
84
  "build": "rm -rf lib && tsc && yarn build:css && yarn copy-locale-files",
85
85
  "build:css": "postcss src/index.css -o lib/styles.css",
86
- "lint": "eslint 'src/**/*.{ts,tsx}'",
86
+ "lint": "eslint src --ext .ts,.tsx",
87
87
  "lint:fix": "eslint . --fix",
88
88
  "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss}\"",
89
89
  "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,json,css,scss}\"",