@pallasoft/ps-input-components 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,8 +18,9 @@ export interface PsCascaderInputProps {
18
18
  label: string;
19
19
  onChange: (value: string) => void;
20
20
  placeholder?: string;
21
+ preferredGroupKey?: string;
21
22
  required?: boolean;
22
23
  searchPlaceholder?: string;
23
24
  value: string;
24
25
  }
25
- export declare const PsCascaderInput: ({ className, disabled, groups, helperText, hideLabel, isLoading, label, onChange, placeholder, required, searchPlaceholder, value, }: PsCascaderInputProps) => import("react").JSX.Element;
26
+ export declare const PsCascaderInput: ({ className, disabled, groups, helperText, hideLabel, isLoading, label, onChange, placeholder, preferredGroupKey, required, searchPlaceholder, value, }: PsCascaderInputProps) => import("react").JSX.Element;
@@ -7,10 +7,11 @@ const ps_core_components_1 = require("@pallasoft/ps-core-components");
7
7
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
8
8
  const ps_icons_1 = require("@pallasoft/ps-icons");
9
9
  const react_aria_components_1 = require("react-aria-components");
10
+ const ps_cascader_config_1 = require("../constants/ps-cascader-config");
10
11
  const ps_cascader_service_1 = require("../services/ps-cascader-service");
11
12
  const ps_field_skeleton_1 = require("./ps-field-skeleton");
12
13
  const ps_required_mark_1 = require("./ps-required-mark");
13
- const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, isLoading = false, label, onChange, placeholder = 'Select an option', required, searchPlaceholder = 'Search', value, }) => {
14
+ const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, isLoading = false, label, onChange, placeholder = 'Select an option', preferredGroupKey, required, searchPlaceholder = 'Search', value, }) => {
14
15
  if (isLoading)
15
16
  return (0, jsx_runtime_1.jsx)(ps_field_skeleton_1.PsFieldSkeleton, { className: className, hideLabel: hideLabel, label: label });
16
17
  const zIndex = (0, ps_core_components_1.usePsLayerZIndex)(ps_design_system_1.PallasoftZIndex.Dropdown);
@@ -20,15 +21,20 @@ const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, i
20
21
  const selected = (0, react_1.useMemo)(() => ps_cascader_service_1.PsCascaderService.findSelected(groups, value), [groups, value]);
21
22
  const matches = (0, react_1.useMemo)(() => ps_cascader_service_1.PsCascaderService.search(groups, query), [groups, query]);
22
23
  const activeGroup = (0, react_1.useMemo)(() => {
24
+ const preferred = preferredGroupKey !== undefined && groups.some((group) => group.key === preferredGroupKey)
25
+ ? preferredGroupKey
26
+ : null;
23
27
  const key = activeGroupKey
24
28
  ? activeGroupKey
25
- : selected
26
- ? selected.group.key
27
- : groups.length > 0
28
- ? groups[0].key
29
- : null;
29
+ : preferred !== null
30
+ ? preferred
31
+ : selected
32
+ ? selected.group.key
33
+ : groups.length > 0
34
+ ? groups[0].key
35
+ : null;
30
36
  return groups.find((group) => group.key === key) ?? null;
31
- }, [activeGroupKey, groups, selected]);
37
+ }, [activeGroupKey, groups, preferredGroupKey, selected]);
32
38
  const open = (nextOpen) => {
33
39
  setIsOpen(nextOpen);
34
40
  if (!nextOpen)
@@ -43,10 +49,10 @@ const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, i
43
49
  const renderOption = (option, groupLabel, close) => ((0, jsx_runtime_1.jsxs)("button", { "aria-selected": option.value === value, className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex w-full items-start gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-medium transition-colors', option.value === value
44
50
  ? 'bg-primary/10 text-ink'
45
51
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), onClick: () => select(option.value, close), role: 'option', type: 'button', children: [(0, jsx_runtime_1.jsx)("span", { className: 'flex h-5 w-4 shrink-0 items-center justify-center text-primary', children: option.value === value ? ((0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: ps_icons_1.PsIconKey.Check })) : null }), (0, jsx_runtime_1.jsxs)("span", { className: 'min-w-0 flex-1', children: [(0, jsx_runtime_1.jsx)("span", { className: 'block truncate', children: option.label }), groupLabel ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-0.5 block truncate text-xs font-normal text-ink/50', children: groupLabel })) : null, option.description ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-0.5 block truncate text-xs font-normal text-ink/55', children: option.description })) : null] })] }, option.value));
46
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)("span", { className: 'ps-input-label block', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })), (0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { isOpen: isOpen, onOpenChange: open, children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), isDisabled: disabled, children: [(0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 flex-1 truncate', children: selected ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: 'truncate', children: selected.option.label }), (0, jsx_runtime_1.jsx)("span", { className: 'ml-2 text-xs font-medium text-ink/45', children: selected.group.label })] })) : ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),32rem)] min-w-[var(--trigger-width)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Dialog, { "aria-label": label, className: 'flex flex-col outline-none', children: ({ close }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: 'border-b border-line p-2', children: (0, jsx_runtime_1.jsx)("input", { "aria-label": searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, type: 'search', value: query }) }), query.trim() === '' ? ((0, jsx_runtime_1.jsxs)("div", { className: 'grid grid-cols-1 sm:grid-cols-[minmax(0,11rem)_minmax(0,1fr)]', children: [(0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5 sm:border-r sm:border-line', activeGroupKey && groups.length > 1 ? 'hidden sm:block' : ''), children: groups.map((group) => ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-semibold transition-colors', activeGroup?.key === group.key
47
- ? 'bg-mist text-ink'
48
- : 'text-ink/70 hover:bg-mist/60 hover:text-ink'), onClick: () => setActiveGroupKey(group.key), type: 'button', children: [(0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 flex-1 truncate', children: group.label }), (0, jsx_runtime_1.jsx)("span", { className: 'text-xs font-medium text-ink/45', children: group.options.length }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 shrink-0 -rotate-90 text-ink/35', iconKey: ps_icons_1.PsIconKey.Chevron })] }, group.key))) }), (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', activeGroupKey && groups.length > 1 ? '' : 'hidden sm:block'), role: 'listbox', children: [groups.length > 1 ? ((0, jsx_runtime_1.jsxs)("button", { className: 'ps-focus-ring mb-1 flex w-full items-center gap-2 rounded-ps-control px-3 py-2 text-left text-xs font-semibold text-ink/60 hover:text-ink sm:hidden', onClick: () => setActiveGroupKey(null), type: 'button', children: [(0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-90', iconKey: ps_icons_1.PsIconKey.Chevron }), "All groups"] })) : null, activeGroup
49
- ? activeGroup.options.map((option) => renderOption(option, null, close))
50
- : null] })] })) : ((0, jsx_runtime_1.jsx)("div", { className: 'ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: 'px-3 py-6 text-center text-sm text-ink/55', children: "No matches." })) : (matches.map((match) => renderOption(match.option, match.group.label, close))) }))] })) }) })] }), helperText ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper mt-2 block', children: helperText }) : null] }));
52
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)("span", { className: 'ps-input-label block', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })), (0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { isOpen: isOpen, onOpenChange: open, children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), isDisabled: disabled, children: [(0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 flex-1 truncate', children: selected ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: 'truncate', children: selected.option.label }), (0, jsx_runtime_1.jsx)("span", { className: 'ml-2 text-xs font-medium text-ink/45', children: selected.group.label })] })) : ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),32rem)] min-w-[var(--trigger-width)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Dialog, { "aria-label": label, className: 'flex flex-col outline-none', children: ({ close }) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: groups.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-1 px-4 py-8 text-center', children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-sm font-semibold text-ink', children: ps_cascader_config_1.PsCascaderConfig.emptyLabel }), (0, jsx_runtime_1.jsx)("p", { className: 'text-xs text-ink/55', children: ps_cascader_config_1.PsCascaderConfig.emptyDescription })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: 'border-b border-line p-2', children: (0, jsx_runtime_1.jsx)("input", { "aria-label": searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, type: 'search', value: query }) }), query.trim() === '' ? ((0, jsx_runtime_1.jsxs)("div", { className: 'grid grid-cols-1 sm:grid-cols-[minmax(0,11rem)_minmax(0,1fr)]', children: [(0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5 sm:border-r sm:border-line', activeGroupKey && groups.length > 1 ? 'hidden sm:block' : ''), children: groups.map((group) => ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-semibold transition-colors', activeGroup?.key === group.key
53
+ ? 'bg-mist text-ink'
54
+ : 'text-ink/70 hover:bg-mist/60 hover:text-ink'), onClick: () => setActiveGroupKey(group.key), type: 'button', children: [(0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 flex-1 truncate', children: group.label }), (0, jsx_runtime_1.jsx)("span", { className: 'text-xs font-medium text-ink/45', children: group.options.length }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 shrink-0 -rotate-90 text-ink/35', iconKey: ps_icons_1.PsIconKey.Chevron })] }, group.key))) }), (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', activeGroupKey && groups.length > 1 ? '' : 'hidden sm:block'), role: 'listbox', children: [groups.length > 1 ? ((0, jsx_runtime_1.jsxs)("button", { className: 'ps-focus-ring mb-1 flex w-full items-center gap-2 rounded-ps-control px-3 py-2 text-left text-xs font-semibold text-ink/60 hover:text-ink sm:hidden', onClick: () => setActiveGroupKey(null), type: 'button', children: [(0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-90', iconKey: ps_icons_1.PsIconKey.Chevron }), "All groups"] })) : null, activeGroup
55
+ ? activeGroup.options.map((option) => renderOption(option, null, close))
56
+ : null] })] })) : ((0, jsx_runtime_1.jsx)("div", { className: 'ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: 'px-3 py-6 text-center text-sm text-ink/55', children: ps_cascader_config_1.PsCascaderConfig.noMatchesLabel })) : (matches.map((match) => renderOption(match.option, match.group.label, close))) }))] })) })) }) })] }), helperText ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper mt-2 block', children: helperText }) : null] }));
51
57
  };
52
58
  exports.PsCascaderInput = PsCascaderInput;
@@ -0,0 +1,5 @@
1
+ export declare const PsCascaderConfig: {
2
+ readonly emptyDescription: "Add one first and it will show up here.";
3
+ readonly emptyLabel: "Nothing to choose from yet";
4
+ readonly noMatchesLabel: "No matches.";
5
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsCascaderConfig = void 0;
4
+ exports.PsCascaderConfig = {
5
+ emptyDescription: 'Add one first and it will show up here.',
6
+ emptyLabel: 'Nothing to choose from yet',
7
+ noMatchesLabel: 'No matches.',
8
+ };
@@ -4,10 +4,11 @@ import { usePsLayerZIndex } from '@pallasoft/ps-core-components';
4
4
  import { PallasoftClassNameService, PallasoftZIndex } from '@pallasoft/ps-design-system';
5
5
  import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
6
6
  import { Button, Dialog, DialogTrigger, Popover } from 'react-aria-components';
7
+ import { PsCascaderConfig } from '../constants/ps-cascader-config';
7
8
  import { PsCascaderService } from '../services/ps-cascader-service';
8
9
  import { PsFieldSkeleton } from './ps-field-skeleton';
9
10
  import { PsRequiredMark } from './ps-required-mark';
10
- export const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, isLoading = false, label, onChange, placeholder = 'Select an option', required, searchPlaceholder = 'Search', value, }) => {
11
+ export const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, isLoading = false, label, onChange, placeholder = 'Select an option', preferredGroupKey, required, searchPlaceholder = 'Search', value, }) => {
11
12
  if (isLoading)
12
13
  return _jsx(PsFieldSkeleton, { className: className, hideLabel: hideLabel, label: label });
13
14
  const zIndex = usePsLayerZIndex(PallasoftZIndex.Dropdown);
@@ -17,15 +18,20 @@ export const PsCascaderInput = ({ className, disabled, groups, helperText, hideL
17
18
  const selected = useMemo(() => PsCascaderService.findSelected(groups, value), [groups, value]);
18
19
  const matches = useMemo(() => PsCascaderService.search(groups, query), [groups, query]);
19
20
  const activeGroup = useMemo(() => {
21
+ const preferred = preferredGroupKey !== undefined && groups.some((group) => group.key === preferredGroupKey)
22
+ ? preferredGroupKey
23
+ : null;
20
24
  const key = activeGroupKey
21
25
  ? activeGroupKey
22
- : selected
23
- ? selected.group.key
24
- : groups.length > 0
25
- ? groups[0].key
26
- : null;
26
+ : preferred !== null
27
+ ? preferred
28
+ : selected
29
+ ? selected.group.key
30
+ : groups.length > 0
31
+ ? groups[0].key
32
+ : null;
27
33
  return groups.find((group) => group.key === key) ?? null;
28
- }, [activeGroupKey, groups, selected]);
34
+ }, [activeGroupKey, groups, preferredGroupKey, selected]);
29
35
  const open = (nextOpen) => {
30
36
  setIsOpen(nextOpen);
31
37
  if (!nextOpen)
@@ -40,9 +46,9 @@ export const PsCascaderInput = ({ className, disabled, groups, helperText, hideL
40
46
  const renderOption = (option, groupLabel, close) => (_jsxs("button", { "aria-selected": option.value === value, className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-start gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-medium transition-colors', option.value === value
41
47
  ? 'bg-primary/10 text-ink'
42
48
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), onClick: () => select(option.value, close), role: 'option', type: 'button', children: [_jsx("span", { className: 'flex h-5 w-4 shrink-0 items-center justify-center text-primary', children: option.value === value ? (_jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: PsIconKey.Check })) : null }), _jsxs("span", { className: 'min-w-0 flex-1', children: [_jsx("span", { className: 'block truncate', children: option.label }), groupLabel ? (_jsx("span", { className: 'mt-0.5 block truncate text-xs font-normal text-ink/50', children: groupLabel })) : null, option.description ? (_jsx("span", { className: 'mt-0.5 block truncate text-xs font-normal text-ink/55', children: option.description })) : null] })] }, option.value));
43
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [hideLabel ? null : (_jsxs("span", { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: open, children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), isDisabled: disabled, children: [_jsx("span", { className: 'min-w-0 flex-1 truncate', children: selected ? (_jsxs(_Fragment, { children: [_jsx("span", { className: 'truncate', children: selected.option.label }), _jsx("span", { className: 'ml-2 text-xs font-medium text-ink/45', children: selected.group.label })] })) : (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),32rem)] min-w-[var(--trigger-width)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(Dialog, { "aria-label": label, className: 'flex flex-col outline-none', children: ({ close }) => (_jsxs(_Fragment, { children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, type: 'search', value: query }) }), query.trim() === '' ? (_jsxs("div", { className: 'grid grid-cols-1 sm:grid-cols-[minmax(0,11rem)_minmax(0,1fr)]', children: [_jsx("div", { className: PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5 sm:border-r sm:border-line', activeGroupKey && groups.length > 1 ? 'hidden sm:block' : ''), children: groups.map((group) => (_jsxs("button", { className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-semibold transition-colors', activeGroup?.key === group.key
44
- ? 'bg-mist text-ink'
45
- : 'text-ink/70 hover:bg-mist/60 hover:text-ink'), onClick: () => setActiveGroupKey(group.key), type: 'button', children: [_jsx("span", { className: 'min-w-0 flex-1 truncate', children: group.label }), _jsx("span", { className: 'text-xs font-medium text-ink/45', children: group.options.length }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 shrink-0 -rotate-90 text-ink/35', iconKey: PsIconKey.Chevron })] }, group.key))) }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', activeGroupKey && groups.length > 1 ? '' : 'hidden sm:block'), role: 'listbox', children: [groups.length > 1 ? (_jsxs("button", { className: 'ps-focus-ring mb-1 flex w-full items-center gap-2 rounded-ps-control px-3 py-2 text-left text-xs font-semibold text-ink/60 hover:text-ink sm:hidden', onClick: () => setActiveGroupKey(null), type: 'button', children: [_jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-90', iconKey: PsIconKey.Chevron }), "All groups"] })) : null, activeGroup
46
- ? activeGroup.options.map((option) => renderOption(option, null, close))
47
- : null] })] })) : (_jsx("div", { className: 'ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("p", { className: 'px-3 py-6 text-center text-sm text-ink/55', children: "No matches." })) : (matches.map((match) => renderOption(match.option, match.group.label, close))) }))] })) }) })] }), helperText ? _jsx("span", { className: 'ps-input-helper mt-2 block', children: helperText }) : null] }));
49
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [hideLabel ? null : (_jsxs("span", { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: open, children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), isDisabled: disabled, children: [_jsx("span", { className: 'min-w-0 flex-1 truncate', children: selected ? (_jsxs(_Fragment, { children: [_jsx("span", { className: 'truncate', children: selected.option.label }), _jsx("span", { className: 'ml-2 text-xs font-medium text-ink/45', children: selected.group.label })] })) : (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),32rem)] min-w-[var(--trigger-width)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(Dialog, { "aria-label": label, className: 'flex flex-col outline-none', children: ({ close }) => (_jsx(_Fragment, { children: groups.length === 0 ? (_jsxs("div", { className: 'flex flex-col gap-1 px-4 py-8 text-center', children: [_jsx("p", { className: 'text-sm font-semibold text-ink', children: PsCascaderConfig.emptyLabel }), _jsx("p", { className: 'text-xs text-ink/55', children: PsCascaderConfig.emptyDescription })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, type: 'search', value: query }) }), query.trim() === '' ? (_jsxs("div", { className: 'grid grid-cols-1 sm:grid-cols-[minmax(0,11rem)_minmax(0,1fr)]', children: [_jsx("div", { className: PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5 sm:border-r sm:border-line', activeGroupKey && groups.length > 1 ? 'hidden sm:block' : ''), children: groups.map((group) => (_jsxs("button", { className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center gap-2 rounded-ps-control px-3 py-2.5 text-left text-sm font-semibold transition-colors', activeGroup?.key === group.key
50
+ ? 'bg-mist text-ink'
51
+ : 'text-ink/70 hover:bg-mist/60 hover:text-ink'), onClick: () => setActiveGroupKey(group.key), type: 'button', children: [_jsx("span", { className: 'min-w-0 flex-1 truncate', children: group.label }), _jsx("span", { className: 'text-xs font-medium text-ink/45', children: group.options.length }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 shrink-0 -rotate-90 text-ink/35', iconKey: PsIconKey.Chevron })] }, group.key))) }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', activeGroupKey && groups.length > 1 ? '' : 'hidden sm:block'), role: 'listbox', children: [groups.length > 1 ? (_jsxs("button", { className: 'ps-focus-ring mb-1 flex w-full items-center gap-2 rounded-ps-control px-3 py-2 text-left text-xs font-semibold text-ink/60 hover:text-ink sm:hidden', onClick: () => setActiveGroupKey(null), type: 'button', children: [_jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-90', iconKey: PsIconKey.Chevron }), "All groups"] })) : null, activeGroup
52
+ ? activeGroup.options.map((option) => renderOption(option, null, close))
53
+ : null] })] })) : (_jsx("div", { className: 'ps-scrollbar-hidden max-h-72 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("p", { className: 'px-3 py-6 text-center text-sm text-ink/55', children: PsCascaderConfig.noMatchesLabel })) : (matches.map((match) => renderOption(match.option, match.group.label, close))) }))] })) })) }) })] }), helperText ? _jsx("span", { className: 'ps-input-helper mt-2 block', children: helperText }) : null] }));
48
54
  };
@@ -0,0 +1,5 @@
1
+ export const PsCascaderConfig = {
2
+ emptyDescription: 'Add one first and it will show up here.',
3
+ emptyLabel: 'Nothing to choose from yet',
4
+ noMatchesLabel: 'No matches.',
5
+ };
package/dist/esm/index.js CHANGED
@@ -36,3 +36,4 @@ export * from './components/ps-required-mark';
36
36
  export * from './components/ps-year-input';
37
37
  export * from './constants/ps-year-input-config';
38
38
  export * from './services/ps-year-input-service';
39
+ export * from './constants/ps-cascader-config';
package/dist/index.d.ts CHANGED
@@ -36,3 +36,4 @@ export * from './components/ps-required-mark';
36
36
  export * from './components/ps-year-input';
37
37
  export * from './constants/ps-year-input-config';
38
38
  export * from './services/ps-year-input-service';
39
+ export * from './constants/ps-cascader-config';
package/dist/index.js CHANGED
@@ -52,3 +52,4 @@ __exportStar(require("./components/ps-required-mark"), exports);
52
52
  __exportStar(require("./components/ps-year-input"), exports);
53
53
  __exportStar(require("./constants/ps-year-input-config"), exports);
54
54
  __exportStar(require("./services/ps-year-input-service"), exports);
55
+ __exportStar(require("./constants/ps-cascader-config"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-input-components",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -32,10 +32,10 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@internationalized/date": "^3.12.2",
35
- "@pallasoft/ps-core-components": "^2.3.1",
36
- "@pallasoft/ps-design-system": "^1.3.0",
37
- "@pallasoft/ps-icons": "^1.2.0",
38
- "@pallasoft/ps-utilities": "^2.0.0",
35
+ "@pallasoft/ps-core-components": "^2.10.0",
36
+ "@pallasoft/ps-design-system": "^1.5.0",
37
+ "@pallasoft/ps-icons": "^1.5.4",
38
+ "@pallasoft/ps-utilities": "^2.2.0",
39
39
  "libphonenumber-js": "^1.13.13",
40
40
  "react-aria-components": "^1.19.0",
41
41
  "react-datepicker": "^9.1.0"