@pallasoft/ps-input-components 2.0.0 → 2.2.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.
Files changed (58) hide show
  1. package/dist/components/ps-calendar-header.js +4 -7
  2. package/dist/components/ps-cascader-input.js +1 -1
  3. package/dist/components/ps-checkbox-matrix.d.ts +13 -0
  4. package/dist/components/ps-checkbox-matrix.js +24 -0
  5. package/dist/components/ps-color-picker.js +2 -2
  6. package/dist/components/ps-combobox-input.d.ts +5 -1
  7. package/dist/components/ps-combobox-input.js +2 -2
  8. package/dist/components/ps-date-input.js +1 -1
  9. package/dist/components/ps-date-preset-field.js +2 -2
  10. package/dist/components/ps-field-skeleton.js +1 -1
  11. package/dist/components/ps-file-picker.js +1 -1
  12. package/dist/components/ps-multi-select-input.js +2 -2
  13. package/dist/components/ps-phone-input.js +1 -1
  14. package/dist/components/ps-select-input.js +1 -1
  15. package/dist/components/ps-toggle.js +1 -1
  16. package/dist/components/ps-year-input.js +1 -1
  17. package/dist/constants/ps-calendar-header-classes.d.ts +6 -0
  18. package/dist/constants/ps-calendar-header-classes.js +9 -0
  19. package/dist/constants/ps-portable-text-editor-config.d.ts +2 -2
  20. package/dist/constants/ps-portable-text-editor-config.js +2 -2
  21. package/dist/esm/components/ps-calendar-header.js +4 -7
  22. package/dist/esm/components/ps-cascader-input.js +1 -1
  23. package/dist/esm/components/ps-checkbox-matrix.js +20 -0
  24. package/dist/esm/components/ps-color-picker.js +2 -2
  25. package/dist/esm/components/ps-combobox-input.js +2 -2
  26. package/dist/esm/components/ps-date-input.js +1 -1
  27. package/dist/esm/components/ps-date-preset-field.js +2 -2
  28. package/dist/esm/components/ps-field-skeleton.js +1 -1
  29. package/dist/esm/components/ps-file-picker.js +1 -1
  30. package/dist/esm/components/ps-multi-select-input.js +2 -2
  31. package/dist/esm/components/ps-phone-input.js +1 -1
  32. package/dist/esm/components/ps-select-input.js +1 -1
  33. package/dist/esm/components/ps-toggle.js +1 -1
  34. package/dist/esm/components/ps-year-input.js +1 -1
  35. package/dist/esm/constants/ps-calendar-header-classes.js +6 -0
  36. package/dist/esm/constants/ps-portable-text-editor-config.js +2 -2
  37. package/dist/esm/index.js +7 -0
  38. package/dist/esm/interfaces/ps-checkbox-matrix-cell.js +1 -0
  39. package/dist/esm/interfaces/ps-checkbox-matrix-column.js +1 -0
  40. package/dist/esm/interfaces/ps-checkbox-matrix-group.js +1 -0
  41. package/dist/esm/interfaces/ps-checkbox-matrix-labels.js +1 -0
  42. package/dist/esm/interfaces/ps-checkbox-matrix-row.js +1 -0
  43. package/dist/esm/services/ps-checkbox-matrix-service.js +28 -0
  44. package/dist/index.d.ts +7 -0
  45. package/dist/index.js +7 -0
  46. package/dist/interfaces/ps-checkbox-matrix-cell.d.ts +6 -0
  47. package/dist/interfaces/ps-checkbox-matrix-cell.js +2 -0
  48. package/dist/interfaces/ps-checkbox-matrix-column.d.ts +5 -0
  49. package/dist/interfaces/ps-checkbox-matrix-column.js +2 -0
  50. package/dist/interfaces/ps-checkbox-matrix-group.d.ts +6 -0
  51. package/dist/interfaces/ps-checkbox-matrix-group.js +2 -0
  52. package/dist/interfaces/ps-checkbox-matrix-labels.d.ts +9 -0
  53. package/dist/interfaces/ps-checkbox-matrix-labels.js +2 -0
  54. package/dist/interfaces/ps-checkbox-matrix-row.d.ts +6 -0
  55. package/dist/interfaces/ps-checkbox-matrix-row.js +2 -0
  56. package/dist/services/ps-checkbox-matrix-service.d.ts +9 -0
  57. package/dist/services/ps-checkbox-matrix-service.js +32 -0
  58. package/package.json +2 -2
@@ -5,13 +5,10 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
7
7
  const ps_icons_1 = require("@pallasoft/ps-icons");
8
+ const ps_calendar_header_classes_1 = require("../constants/ps-calendar-header-classes");
8
9
  const ps_calendar_view_1 = require("../constants/ps-calendar-view");
9
10
  const ps_date_input_config_1 = require("../constants/ps-date-input-config");
10
11
  const ps_date_input_service_1 = require("../services/ps-date-input-service");
11
- const navigationButtonClassName = 'ps-focus-ring flex h-8 w-8 items-center justify-center rounded-lg text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30';
12
- const titleButtonClassName = 'ps-focus-ring flex items-center gap-1 rounded-lg px-2 py-1 text-sm font-semibold text-ink transition-colors hover:bg-primary/10';
13
- const cellClassName = 'ps-focus-ring flex h-10 items-center justify-center rounded-[0.625rem] text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent';
14
- const selectedCellClassName = 'bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary';
15
12
  const PsCalendarHeader = ({ changeMonth, changeYear, decreaseMonth, increaseMonth, maxDate, minDate, monthDate, nextMonthButtonDisabled, onViewChange, onYearPick, prevMonthButtonDisabled, selectedYear, view, }) => {
16
13
  const year = selectedYear === undefined ? monthDate.getFullYear() : selectedYear;
17
14
  const [pageYear, setPageYear] = (0, react_1.useState)(year);
@@ -51,13 +48,13 @@ const PsCalendarHeader = ({ changeMonth, changeYear, decreaseMonth, increaseMont
51
48
  titleView: ps_calendar_view_1.PsCalendarView.day,
52
49
  },
53
50
  }[view];
54
- return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-2', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex items-center justify-between gap-2 px-1', children: [(0, jsx_runtime_1.jsx)("button", { "aria-label": navigation.previousLabel, className: navigationButtonClassName, disabled: navigation.isPreviousDisabled, onClick: navigation.previous, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-180', iconKey: ps_icons_1.PsIconKey.ChevronRight }) }), onYearPick === undefined ? ((0, jsx_runtime_1.jsxs)("button", { "aria-label": navigation.titleLabel, "aria-live": 'polite', className: titleButtonClassName, onClick: () => {
51
+ return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-2', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex items-center justify-between gap-2 px-1', children: [(0, jsx_runtime_1.jsx)("button", { "aria-label": navigation.previousLabel, className: ps_calendar_header_classes_1.PsCalendarHeaderClasses.navigationButton, disabled: navigation.isPreviousDisabled, onClick: navigation.previous, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-180', iconKey: ps_icons_1.PsIconKey.ChevronRight }) }), onYearPick === undefined ? ((0, jsx_runtime_1.jsxs)("button", { "aria-label": navigation.titleLabel, "aria-live": 'polite', className: ps_calendar_header_classes_1.PsCalendarHeaderClasses.titleButton, onClick: () => {
55
52
  setPageYear(year);
56
53
  onViewChange(navigation.titleView);
57
- }, type: 'button', children: [navigation.title, (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 rotate-90 text-ink/50', iconKey: ps_icons_1.PsIconKey.ChevronRight })] })) : ((0, jsx_runtime_1.jsx)("p", { "aria-live": 'polite', className: 'text-sm font-semibold text-ink', children: navigation.title })), (0, jsx_runtime_1.jsx)("button", { "aria-label": navigation.nextLabel, className: navigationButtonClassName, disabled: navigation.isNextDisabled, onClick: navigation.next, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: ps_icons_1.PsIconKey.ChevronRight }) })] }), view === ps_calendar_view_1.PsCalendarView.month ? ((0, jsx_runtime_1.jsx)("div", { className: 'grid grid-cols-3 gap-1', children: ps_date_input_service_1.PsDateInputService.monthNames().map((name, month) => ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(cellClassName, month === monthDate.getMonth() ? selectedCellClassName : undefined), disabled: ps_date_input_service_1.PsDateInputService.isMonthOutOfRange(year, month, minDate, maxDate), onClick: () => {
54
+ }, type: 'button', children: [navigation.title, (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 rotate-90 text-ink/50', iconKey: ps_icons_1.PsIconKey.ChevronRight })] })) : ((0, jsx_runtime_1.jsx)("p", { "aria-live": 'polite', className: 'text-sm font-semibold text-ink', children: navigation.title })), (0, jsx_runtime_1.jsx)("button", { "aria-label": navigation.nextLabel, className: ps_calendar_header_classes_1.PsCalendarHeaderClasses.navigationButton, disabled: navigation.isNextDisabled, onClick: navigation.next, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: ps_icons_1.PsIconKey.ChevronRight }) })] }), view === ps_calendar_view_1.PsCalendarView.month ? ((0, jsx_runtime_1.jsx)("div", { className: 'grid grid-cols-3 gap-1', children: ps_date_input_service_1.PsDateInputService.monthNames().map((name, month) => ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_calendar_header_classes_1.PsCalendarHeaderClasses.cell, month === monthDate.getMonth() ? ps_calendar_header_classes_1.PsCalendarHeaderClasses.selectedCell : undefined), disabled: ps_date_input_service_1.PsDateInputService.isMonthOutOfRange(year, month, minDate, maxDate), onClick: () => {
58
55
  changeMonth(month);
59
56
  onViewChange(ps_calendar_view_1.PsCalendarView.day);
60
- }, type: 'button', children: name }, name))) })) : null, view === ps_calendar_view_1.PsCalendarView.year ? ((0, jsx_runtime_1.jsx)("div", { className: 'grid grid-cols-3 gap-1', children: years.map((candidate) => ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(cellClassName, candidate === year ? selectedCellClassName : undefined), disabled: ps_date_input_service_1.PsDateInputService.isYearOutOfRange(candidate, minDate, maxDate), onClick: () => {
57
+ }, type: 'button', children: name }, name))) })) : null, view === ps_calendar_view_1.PsCalendarView.year ? ((0, jsx_runtime_1.jsx)("div", { className: 'grid grid-cols-3 gap-1', children: years.map((candidate) => ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_calendar_header_classes_1.PsCalendarHeaderClasses.cell, candidate === year ? ps_calendar_header_classes_1.PsCalendarHeaderClasses.selectedCell : undefined), disabled: ps_date_input_service_1.PsDateInputService.isYearOutOfRange(candidate, minDate, maxDate), onClick: () => {
61
58
  if (onYearPick !== undefined) {
62
59
  onYearPick(candidate);
63
60
  return;
@@ -51,7 +51,7 @@ const PsCascaderInput = ({ className, disabled, groups, helperText, hideLabel, i
51
51
  : option.value === value
52
52
  ? 'bg-primary/10 text-ink'
53
53
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), disabled: option.isDisabled, 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 break-words', children: option.label }), groupLabel ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-0.5 block break-words text-xs font-normal text-ink/50', children: groupLabel })) : null, option.description ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-0.5 block break-words text-xs font-normal text-ink/55', children: option.description })) : null] })] }, option.value));
54
- 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
54
+ 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 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-control-compact ps-focus-ring 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
55
55
  ? 'bg-mist text-ink'
56
56
  : '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
57
57
  ? activeGroup.options.map((option) => renderOption(option, null, close))
@@ -0,0 +1,13 @@
1
+ import type { PsCheckboxMatrixColumn } from '../interfaces/ps-checkbox-matrix-column';
2
+ import type { PsCheckboxMatrixGroup } from '../interfaces/ps-checkbox-matrix-group';
3
+ import type { PsCheckboxMatrixLabels } from '../interfaces/ps-checkbox-matrix-labels';
4
+ export interface PsCheckboxMatrixProps {
5
+ columns: PsCheckboxMatrixColumn[];
6
+ defaultOpenGroupId?: string | null;
7
+ groups: PsCheckboxMatrixGroup[];
8
+ isReadOnly?: boolean;
9
+ labels: PsCheckboxMatrixLabels;
10
+ onChange: (value: string[]) => void;
11
+ value: string[];
12
+ }
13
+ export declare const PsCheckboxMatrix: ({ columns, defaultOpenGroupId, groups, isReadOnly, labels, onChange, value, }: PsCheckboxMatrixProps) => import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsCheckboxMatrix = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const ps_core_components_1 = require("@pallasoft/ps-core-components");
7
+ const ps_checkbox_matrix_service_1 = require("../services/ps-checkbox-matrix-service");
8
+ const ps_checkbox_1 = require("./ps-checkbox");
9
+ const PsCheckboxMatrix = ({ columns, defaultOpenGroupId = null, groups, isReadOnly = false, labels, onChange, value, }) => {
10
+ const [openGroupId, setOpenGroupId] = (0, react_1.useState)(defaultOpenGroupId);
11
+ return ((0, jsx_runtime_1.jsx)("div", { className: 'flex flex-col gap-2', children: groups.map((group) => {
12
+ const total = ps_checkbox_matrix_service_1.PsCheckboxMatrixService.values(group).length;
13
+ const selected = ps_checkbox_matrix_service_1.PsCheckboxMatrixService.selectedCount(group, value);
14
+ const usedColumns = columns.filter((column) => group.rows.some((row) => row.cells.some((cell) => cell.columnId === column.id)));
15
+ const isComplete = ps_checkbox_matrix_service_1.PsCheckboxMatrixService.isGroupComplete(group, value);
16
+ return ((0, jsx_runtime_1.jsx)(ps_core_components_1.PsAccordion, { isOpen: openGroupId === group.id, label: group.label, onToggle: () => setOpenGroupId(openGroupId === group.id ? null : group.id), trailing: (0, jsx_runtime_1.jsx)("span", { className: 'text-xs font-normal text-ink/55', children: labels.count(selected, total) }), children: (0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-3 px-4 pb-4', children: [(0, jsx_runtime_1.jsx)(ps_checkbox_1.PsCheckbox, { isDisabled: isReadOnly || ps_checkbox_matrix_service_1.PsCheckboxMatrixService.enabledValues(group).length === 0, isIndeterminate: selected > 0 && !isComplete, isSelected: isComplete, label: labels.selectGroup(group), onChange: (isSelected) => onChange(ps_checkbox_matrix_service_1.PsCheckboxMatrixService.toggleGroup(value, group, isSelected)), children: (0, jsx_runtime_1.jsx)("span", { className: 'text-sm font-medium text-ink', children: labels.selectGroup(group) }) }), (0, jsx_runtime_1.jsx)("div", { className: 'overflow-x-auto', children: (0, jsx_runtime_1.jsxs)("table", { className: 'w-full border-collapse text-sm', children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { className: 'text-xs text-ink/55', children: [(0, jsx_runtime_1.jsx)("th", { className: 'py-1.5 pr-3 text-left font-medium', scope: 'col', children: labels.rowHeading }), usedColumns.map((column) => ((0, jsx_runtime_1.jsx)("th", { className: 'w-14 px-1 py-1.5 text-center font-medium', scope: 'col', title: column.hint === null ? undefined : column.hint, children: column.label }, column.id)))] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: group.rows.map((row) => ((0, jsx_runtime_1.jsxs)("tr", { className: 'border-t border-line/70', children: [(0, jsx_runtime_1.jsx)("th", { className: 'py-2 pr-3 text-left font-normal text-ink', scope: 'row', children: row.label }), usedColumns.map((column) => {
17
+ const cell = row.cells.find((item) => item.columnId === column.id);
18
+ return ((0, jsx_runtime_1.jsx)("td", { className: 'px-1 py-2 text-center', children: cell === undefined ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'inline-flex', title: cell.reason === null ? undefined : cell.reason, children: (0, jsx_runtime_1.jsx)(ps_checkbox_1.PsCheckbox, { isDisabled: isReadOnly || cell.isDisabled, isSelected: value.includes(cell.value), label: cell.reason === null
19
+ ? labels.cell(row, column)
20
+ : `${labels.cell(row, column)}. ${cell.reason}`, onChange: (isSelected) => onChange(ps_checkbox_matrix_service_1.PsCheckboxMatrixService.toggle(value, cell.value, isSelected)) }) })) }, column.id));
21
+ })] }, row.id))) })] }) })] }) }, group.id));
22
+ }) }));
23
+ };
24
+ exports.PsCheckboxMatrix = PsCheckboxMatrix;
@@ -38,7 +38,7 @@ const PsColorPicker = ({ className, disabled, helperText, hideLabel, label, onCh
38
38
  saturation: Math.round((x / bounds.width) * 100),
39
39
  }));
40
40
  };
41
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-label block', children: label }), (0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex min-h-11 w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [(0, jsx_runtime_1.jsx)("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), (0, jsx_runtime_1.jsx)("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 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),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsxs)(react_aria_components_1.Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [(0, jsx_runtime_1.jsx)("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
41
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-label block', children: label }), (0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [(0, jsx_runtime_1.jsx)("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), (0, jsx_runtime_1.jsx)("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 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),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsxs)(react_aria_components_1.Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [(0, jsx_runtime_1.jsx)("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
42
42
  event.currentTarget.setPointerCapture(event.pointerId);
43
43
  pickFromArea(event);
44
44
  }, onPointerMove: (event) => {
@@ -52,7 +52,7 @@ const PsColorPicker = ({ className, disabled, helperText, hideLabel, label, onCh
52
52
  backgroundColor: swatchColor ? swatchColor : 'transparent',
53
53
  } }) }), (0, jsx_runtime_1.jsxs)("label", { className: 'flex flex-col gap-1', children: [(0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper', children: "Hue" }), (0, jsx_runtime_1.jsx)("input", { className: 'ps-focus-ring h-3 w-full cursor-pointer appearance-none rounded-full', max: 360, min: 0, onChange: (event) => onChange(ps_color_service_1.PsColorService.toHex({ ...hsv, hue: Number(event.target.value) })), step: 1, style: {
54
54
  background: 'linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000)',
55
- }, type: 'range', value: hsv.hue })] }), (0, jsx_runtime_1.jsx)("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-focus-ring h-10 w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
55
+ }, type: 'range', value: hsv.hue })] }), (0, jsx_runtime_1.jsx)("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-control-compact ps-focus-ring w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
56
56
  if (event.key !== 'Enter')
57
57
  return;
58
58
  event.preventDefault();
@@ -1,8 +1,11 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export interface PsComboboxInputProps<T> {
3
3
  className?: string;
4
+ emptyText?: string;
4
5
  getItemKey: (item: T) => string;
5
6
  getItemLabel: (item: T) => string;
7
+ hideLabel?: boolean;
8
+ inputValue?: string;
6
9
  isLoading?: boolean;
7
10
  items: T[];
8
11
  label?: string;
@@ -11,5 +14,6 @@ export interface PsComboboxInputProps<T> {
11
14
  placeholder?: string;
12
15
  renderItem?: (item: T) => ReactNode;
13
16
  required?: boolean;
17
+ selectedKey?: string | null;
14
18
  }
15
- export declare const PsComboboxInput: <T>({ className, getItemKey, getItemLabel, isLoading, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, }: PsComboboxInputProps<T>) => import("react").JSX.Element;
19
+ export declare const PsComboboxInput: <T>({ className, emptyText, getItemKey, getItemLabel, hideLabel, inputValue, isLoading, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }: PsComboboxInputProps<T>) => import("react").JSX.Element;
@@ -7,8 +7,8 @@ const ps_design_system_1 = require("@pallasoft/ps-design-system");
7
7
  const react_aria_components_1 = require("react-aria-components");
8
8
  const ps_combobox_input_service_1 = require("../services/ps-combobox-input-service");
9
9
  const ps_required_mark_1 = require("./ps-required-mark");
10
- const PsComboboxInput = ({ className, getItemKey, getItemLabel, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, }) => {
10
+ const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
11
11
  const itemsByKey = new Map(items.map((item) => [getItemKey(item), item]));
12
- return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.ComboBox, { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), defaultFilter: () => true, items: items, onInputChange: onInputChange, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : ps_combobox_input_service_1.PsComboboxInputService.getItem(itemsByKey, key)), children: [label ? ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { className: 'ps-input-label', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })) : null, (0, jsx_runtime_1.jsx)("span", { className: 'relative mt-2 block', children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Input, { className: 'ps-input-control ps-focus-ring min-h-11 w-full text-sm font-semibold', placeholder: placeholder }) }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex items-center justify-center py-4', children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsSpinner, { label: 'Loading results', size: 'small' }) })) : ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, children: (item) => ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-xl px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
12
+ return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : ps_combobox_input_service_1.PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { className: 'ps-input-label', children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] })) : null, (0, jsx_runtime_1.jsx)("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: (0, jsx_runtime_1.jsx)(react_aria_components_1.Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex items-center justify-center py-4', children: (0, jsx_runtime_1.jsx)(ps_core_components_1.PsSpinner, { label: 'Loading results', size: 'small' }) })) : ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? (0, jsx_runtime_1.jsx)("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => ((0, jsx_runtime_1.jsx)(react_aria_components_1.ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
13
13
  };
14
14
  exports.PsComboboxInput = PsComboboxInput;
@@ -44,6 +44,6 @@ const PsDateInput = ({ className, defaultValue, disabled, helperText, hideLabel,
44
44
  setUncontrolledValue(nextValue);
45
45
  onChange?.(nextValue);
46
46
  };
47
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [(0, jsx_runtime_1.jsx)(react_datepicker_1.default, { autoComplete: 'off', calendarClassName: ps_design_system_1.PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === ps_calendar_view_1.PsCalendarView.day ? undefined : ps_date_input_config_1.PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: [...ps_date_input_config_1.PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(ps_calendar_view_1.PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => ((0, jsx_runtime_1.jsx)(ps_calendar_header_1.PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: ps_date_input_service_1.PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: ps_icons_1.PsIconKey.Calendar }), name ? (0, jsx_runtime_1.jsx)("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper', children: helperText }) : null] }));
47
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [(0, jsx_runtime_1.jsx)(react_datepicker_1.default, { autoComplete: 'off', calendarClassName: ps_design_system_1.PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === ps_calendar_view_1.PsCalendarView.day ? undefined : ps_date_input_config_1.PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: [...ps_date_input_config_1.PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(ps_calendar_view_1.PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => ((0, jsx_runtime_1.jsx)(ps_calendar_header_1.PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: ps_date_input_service_1.PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: ps_icons_1.PsIconKey.Calendar }), name ? (0, jsx_runtime_1.jsx)("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper', children: helperText }) : null] }));
48
48
  };
49
49
  exports.PsDateInput = PsDateInput;
@@ -5,6 +5,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_date_input_1 = require("./ps-date-input");
6
6
  const ps_form_control_1 = require("./ps-form-control");
7
7
  const PsDatePresetField = ({ errorText, hideLabel, label, onChange, presets, presetsDisabled = false, presetsLabel, required, value, }) => ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-2', children: [(0, jsx_runtime_1.jsx)(ps_form_control_1.PsFormControl, { errorText: errorText, children: (0, jsx_runtime_1.jsx)(ps_date_input_1.PsDateInput, { hideLabel: hideLabel, label: label, onChange: onChange, required: required, value: value }) }), (0, jsx_runtime_1.jsx)("div", { "aria-label": presetsLabel, className: 'flex flex-wrap gap-1.5', role: 'group', children: presets.map((preset) => ((0, jsx_runtime_1.jsx)("button", { "aria-pressed": preset.date !== '' && preset.date === value, className: preset.date !== '' && preset.date === value
8
- ? 'ps-focus-ring rounded-full bg-primary px-2.5 py-1 text-xs font-semibold text-white'
9
- : 'ps-focus-ring rounded-full border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
8
+ ? 'ps-focus-ring rounded-ps-control bg-primary px-2.5 py-1 text-xs font-semibold text-white'
9
+ : 'ps-focus-ring rounded-ps-control border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
10
10
  exports.PsDatePresetField = PsDatePresetField;
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsFieldSkeleton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
- const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => ((0, jsx_runtime_1.jsxs)("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: label }), hideLabel ? null : (0, jsx_runtime_1.jsx)("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-11', className) })] }));
6
+ const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => ((0, jsx_runtime_1.jsxs)("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: label }), hideLabel ? null : (0, jsx_runtime_1.jsx)("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-ps-control', className) })] }));
7
7
  exports.PsFieldSkeleton = PsFieldSkeleton;
@@ -28,6 +28,6 @@ const PsFilePicker = ({ accept, acceptLabel, className, disabled, dropLabel, isL
28
28
  }
29
29
  onFileLoad(newFile);
30
30
  };
31
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-lg border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col items-center gap-3 text-center', children: [(0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), (0, jsx_runtime_1.jsx)("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? (0, jsx_runtime_1.jsx)("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, (0, jsx_runtime_1.jsxs)("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), (0, jsx_runtime_1.jsx)("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
31
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-ps-control border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col items-center gap-3 text-center', children: [(0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), (0, jsx_runtime_1.jsx)("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? (0, jsx_runtime_1.jsx)("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, (0, jsx_runtime_1.jsxs)("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), (0, jsx_runtime_1.jsx)("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
32
32
  };
33
33
  exports.PsFilePicker = PsFilePicker;
@@ -23,8 +23,8 @@ const PsMultiSelectInput = ({ className, defaultValue, disabled, helperText, hid
23
23
  setUncontrolledValue(nextValue);
24
24
  onChange?.(nextValue);
25
25
  };
26
- return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Select, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { 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.Button, { className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [(0, jsx_runtime_1.jsx)(react_aria_components_1.SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
26
+ return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Select, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { 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.Button, { className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [(0, jsx_runtime_1.jsx)(react_aria_components_1.SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
27
27
  .filter((selected) => labelByValue.has(selected))
28
- .map((selected) => ((0, jsx_runtime_1.jsx)("span", { className: 'inline-flex max-w-full items-center rounded-full bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: (0, jsx_runtime_1.jsx)("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), helperText ? ((0, jsx_runtime_1.jsx)(react_aria_components_1.Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => (0, jsx_runtime_1.jsx)(ps_select_option_item_1.PsSelectOptionItem, { option: option }) }) })] }));
28
+ .map((selected) => ((0, jsx_runtime_1.jsx)("span", { className: 'inline-flex max-w-full items-center rounded-ps-control bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: (0, jsx_runtime_1.jsx)("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), helperText ? ((0, jsx_runtime_1.jsx)(react_aria_components_1.Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => (0, jsx_runtime_1.jsx)(ps_select_option_item_1.PsSelectOptionItem, { option: option }) }) })] }));
29
29
  };
30
30
  exports.PsMultiSelectInput = PsMultiSelectInput;
@@ -37,7 +37,7 @@ const PsPhoneInput = ({ className, defaultCountry = ps_phone_input_config_1.PsPh
37
37
  emit(national, code);
38
38
  document.getElementById(inputId)?.focus();
39
39
  };
40
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control flex min-h-11 items-stretch overflow-hidden p-0 focus-within:border-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.countryLabel, className: 'ps-focus-ring flex shrink-0 items-center gap-1.5 border-r border-line px-3 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: ps_icons_1.PsIconKey.Chevron })] }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsxs)(react_aria_components_1.Dialog, { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [(0, jsx_runtime_1.jsx)("div", { className: 'border-b border-line p-2', children: (0, jsx_runtime_1.jsx)("input", { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: ps_phone_input_config_1.PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), (0, jsx_runtime_1.jsx)("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? ((0, jsx_runtime_1.jsx)("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: ps_phone_input_config_1.PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => ((0, jsx_runtime_1.jsx)("li", { role: 'none', children: (0, jsx_runtime_1.jsxs)("button", { "aria-selected": option.code === country, className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
40
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control flex items-stretch overflow-hidden p-0 focus-within:border-primary has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [(0, jsx_runtime_1.jsxs)(react_aria_components_1.Button, { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.countryLabel, className: 'flex shrink-0 items-center gap-1.5 border-r border-line px-3 outline-none focus-visible:bg-primary/10 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: ps_icons_1.PsIconKey.Chevron })] }), (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsxs)(react_aria_components_1.Dialog, { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [(0, jsx_runtime_1.jsx)("div", { className: 'border-b border-line p-2', children: (0, jsx_runtime_1.jsx)("input", { "aria-label": ps_phone_input_config_1.PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-control-compact ps-focus-ring w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: ps_phone_input_config_1.PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), (0, jsx_runtime_1.jsx)("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? ((0, jsx_runtime_1.jsx)("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: ps_phone_input_config_1.PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => ((0, jsx_runtime_1.jsx)("li", { role: 'none', children: (0, jsx_runtime_1.jsxs)("button", { "aria-selected": option.code === country, className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
41
41
  ? 'bg-primary/10 text-ink'
42
42
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), onClick: () => choose(option.code), role: 'option', type: 'button', children: [(0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 truncate', children: ps_phone_input_service_1.PsPhoneInputService.highlight(option.label, query).map((part, index) => part.isMatch ? ((0, jsx_runtime_1.jsx)("strong", { className: 'font-semibold text-ink', children: part.text }, index)) : ((0, jsx_runtime_1.jsx)("span", { children: part.text }, index))) }), (0, jsx_runtime_1.jsxs)("span", { className: 'shrink-0 text-xs text-ink/50', children: ["+", option.callingCode] })] }) }, option.code)))) })] }) })] }), (0, jsx_runtime_1.jsxs)("span", { "aria-hidden": 'true', className: 'flex items-center pl-3 text-sm text-ink/45', children: [ps_phone_input_config_1.PsPhoneInputConfig.plus, ps_phone_input_service_1.PsPhoneInputService.callingCode(country)] }), (0, jsx_runtime_1.jsx)("input", { "aria-invalid": isInvalid, autoComplete: 'tel-national', className: 'min-w-0 flex-1 bg-transparent px-2 text-sm text-ink outline-none', disabled: disabled, id: inputId, inputMode: 'tel', name: name, onBlur: () => {
43
43
  setIsTouched(true);
@@ -24,6 +24,6 @@ const PsSelectInput = ({ className, defaultValue, disabled, helperText, hideLabe
24
24
  setUncontrolledValue(nextValue);
25
25
  onChange?.(nextValue);
26
26
  };
27
- return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Select, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { 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.Button, { 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'), children: [(0, jsx_runtime_1.jsx)(react_aria_components_1.SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), helperText ? ((0, jsx_runtime_1.jsx)(react_aria_components_1.Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => (0, jsx_runtime_1.jsx)(ps_select_option_item_1.PsSelectOptionItem, { option: option }) }) })] }));
27
+ return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Select, { "aria-label": hideLabel ? label : undefined, className: ps_design_system_1.PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Label, { 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.Button, { className: ps_design_system_1.PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [(0, jsx_runtime_1.jsx)(react_aria_components_1.SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? ((0, jsx_runtime_1.jsx)("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: ps_icons_1.PsIconKey.Chevron })] }), helperText ? ((0, jsx_runtime_1.jsx)(react_aria_components_1.Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, (0, jsx_runtime_1.jsx)(react_aria_components_1.Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: (0, jsx_runtime_1.jsx)(react_aria_components_1.ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => (0, jsx_runtime_1.jsx)(ps_select_option_item_1.PsSelectOptionItem, { option: option }) }) })] }));
28
28
  };
29
29
  exports.PsSelectInput = PsSelectInput;
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsToggle = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
- const PsToggle = ({ description, isChecked, label, name, onChange }) => ((0, jsx_runtime_1.jsxs)("label", { className: 'ps-focus-ring flex cursor-pointer items-center justify-between gap-4 rounded-2xl border border-line bg-white/78 px-4 py-3 text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [(0, jsx_runtime_1.jsxs)("span", { children: [(0, jsx_runtime_1.jsx)("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), (0, jsx_runtime_1.jsx)("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
6
+ const PsToggle = ({ description, isChecked, label, name, onChange }) => ((0, jsx_runtime_1.jsxs)("label", { className: 'ps-control flex cursor-pointer items-center justify-between gap-4 rounded-ps-control border border-line bg-white/78 px-4 py-3 has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [(0, jsx_runtime_1.jsxs)("span", { children: [(0, jsx_runtime_1.jsx)("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? ((0, jsx_runtime_1.jsx)("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), (0, jsx_runtime_1.jsx)("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
7
7
  exports.PsToggle = PsToggle;
@@ -46,7 +46,7 @@ const PsYearInput = ({ className, defaultValue, disabled, helperText, hideLabel,
46
46
  setUncontrolledValue(nextValue);
47
47
  onChange?.(nextValue);
48
48
  };
49
- return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [(0, jsx_runtime_1.jsx)(react_datepicker_1.default, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${ps_date_input_config_1.PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: ps_year_input_config_1.PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => ((0, jsx_runtime_1.jsx)(ps_calendar_header_1.PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
49
+ return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('block', className), children: [(0, jsx_runtime_1.jsxs)("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, (0, jsx_runtime_1.jsx)(ps_required_mark_1.PsRequiredMark, { isRequired: required })] }), (0, jsx_runtime_1.jsxs)("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [(0, jsx_runtime_1.jsx)(react_datepicker_1.default, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${ps_date_input_config_1.PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: ps_year_input_config_1.PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => ((0, jsx_runtime_1.jsx)(ps_calendar_header_1.PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
50
50
  handleChange(ps_year_input_service_1.PsYearInputService.startOfYear(year));
51
51
  pickerRef.current?.setOpen(false);
52
52
  }, selectedYear: selected === null ? undefined : selected.getFullYear(), view: ps_calendar_view_1.PsCalendarView.year })), required: required, selected: selected, showPopperArrow: false, wrapperClassName: 'block w-full' }), (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-ink/50', iconKey: ps_icons_1.PsIconKey.Calendar }), name ? (0, jsx_runtime_1.jsx)("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-input-helper', children: helperText }) : null] }));
@@ -0,0 +1,6 @@
1
+ export declare const PsCalendarHeaderClasses: {
2
+ readonly navigationButton: "ps-focus-ring ps-control-square ps-control-compact flex items-center justify-center rounded-ps-control text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30";
3
+ readonly titleButton: "ps-focus-ring ps-control-compact ps-control-padding-compact flex items-center gap-1 rounded-ps-control text-sm font-semibold text-ink transition-colors hover:bg-primary/10";
4
+ readonly cell: "ps-focus-ring ps-control flex items-center justify-center rounded-ps-control text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent";
5
+ readonly selectedCell: "bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary";
6
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsCalendarHeaderClasses = void 0;
4
+ exports.PsCalendarHeaderClasses = {
5
+ navigationButton: 'ps-focus-ring ps-control-square ps-control-compact flex items-center justify-center rounded-ps-control text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30',
6
+ titleButton: 'ps-focus-ring ps-control-compact ps-control-padding-compact flex items-center gap-1 rounded-ps-control text-sm font-semibold text-ink transition-colors hover:bg-primary/10',
7
+ cell: 'ps-focus-ring ps-control flex items-center justify-center rounded-ps-control text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent',
8
+ selectedCell: 'bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary',
9
+ };
@@ -2,8 +2,8 @@ export declare const PsPortableTextEditorConfig: {
2
2
  readonly classNames: {
3
3
  readonly editable: "ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none";
4
4
  readonly root: "block";
5
- readonly toolbar: "flex flex-wrap items-center gap-1 rounded-t-xl border border-line bg-white p-1 dark:bg-transparent";
6
- readonly button: "ps-focus-ring inline-flex h-9 min-w-9 items-center justify-center rounded-lg px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40";
5
+ readonly toolbar: "flex flex-wrap items-center gap-1 rounded-t-ps-control border border-line bg-white p-1 dark:bg-transparent";
6
+ readonly button: "ps-focus-ring ps-control-compact inline-flex min-w-ps-control-compact items-center justify-center rounded-ps-control px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40";
7
7
  readonly buttonActive: "bg-primary text-white hover:bg-primary hover:text-white";
8
8
  readonly separator: "mx-1 h-5 w-px bg-line";
9
9
  };
@@ -5,8 +5,8 @@ exports.PsPortableTextEditorConfig = {
5
5
  classNames: {
6
6
  editable: 'ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none',
7
7
  root: 'block',
8
- toolbar: 'flex flex-wrap items-center gap-1 rounded-t-xl border border-line bg-white p-1 dark:bg-transparent',
9
- button: 'ps-focus-ring inline-flex h-9 min-w-9 items-center justify-center rounded-lg px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
8
+ toolbar: 'flex flex-wrap items-center gap-1 rounded-t-ps-control border border-line bg-white p-1 dark:bg-transparent',
9
+ button: 'ps-focus-ring ps-control-compact inline-flex min-w-ps-control-compact items-center justify-center rounded-ps-control px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
10
10
  buttonActive: 'bg-primary text-white hover:bg-primary hover:text-white',
11
11
  separator: 'mx-1 h-5 w-px bg-line',
12
12
  },
@@ -2,13 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
4
4
  import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
5
+ import { PsCalendarHeaderClasses } from '../constants/ps-calendar-header-classes';
5
6
  import { PsCalendarView } from '../constants/ps-calendar-view';
6
7
  import { PsDateInputConfig } from '../constants/ps-date-input-config';
7
8
  import { PsDateInputService } from '../services/ps-date-input-service';
8
- const navigationButtonClassName = 'ps-focus-ring flex h-8 w-8 items-center justify-center rounded-lg text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30';
9
- const titleButtonClassName = 'ps-focus-ring flex items-center gap-1 rounded-lg px-2 py-1 text-sm font-semibold text-ink transition-colors hover:bg-primary/10';
10
- const cellClassName = 'ps-focus-ring flex h-10 items-center justify-center rounded-[0.625rem] text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent';
11
- const selectedCellClassName = 'bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary';
12
9
  export const PsCalendarHeader = ({ changeMonth, changeYear, decreaseMonth, increaseMonth, maxDate, minDate, monthDate, nextMonthButtonDisabled, onViewChange, onYearPick, prevMonthButtonDisabled, selectedYear, view, }) => {
13
10
  const year = selectedYear === undefined ? monthDate.getFullYear() : selectedYear;
14
11
  const [pageYear, setPageYear] = useState(year);
@@ -48,13 +45,13 @@ export const PsCalendarHeader = ({ changeMonth, changeYear, decreaseMonth, incre
48
45
  titleView: PsCalendarView.day,
49
46
  },
50
47
  }[view];
51
- return (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsxs("div", { className: 'flex items-center justify-between gap-2 px-1', children: [_jsx("button", { "aria-label": navigation.previousLabel, className: navigationButtonClassName, disabled: navigation.isPreviousDisabled, onClick: navigation.previous, type: 'button', children: _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-180', iconKey: PsIconKey.ChevronRight }) }), onYearPick === undefined ? (_jsxs("button", { "aria-label": navigation.titleLabel, "aria-live": 'polite', className: titleButtonClassName, onClick: () => {
48
+ return (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsxs("div", { className: 'flex items-center justify-between gap-2 px-1', children: [_jsx("button", { "aria-label": navigation.previousLabel, className: PsCalendarHeaderClasses.navigationButton, disabled: navigation.isPreviousDisabled, onClick: navigation.previous, type: 'button', children: _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4 rotate-180', iconKey: PsIconKey.ChevronRight }) }), onYearPick === undefined ? (_jsxs("button", { "aria-label": navigation.titleLabel, "aria-live": 'polite', className: PsCalendarHeaderClasses.titleButton, onClick: () => {
52
49
  setPageYear(year);
53
50
  onViewChange(navigation.titleView);
54
- }, type: 'button', children: [navigation.title, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 rotate-90 text-ink/50', iconKey: PsIconKey.ChevronRight })] })) : (_jsx("p", { "aria-live": 'polite', className: 'text-sm font-semibold text-ink', children: navigation.title })), _jsx("button", { "aria-label": navigation.nextLabel, className: navigationButtonClassName, disabled: navigation.isNextDisabled, onClick: navigation.next, type: 'button', children: _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: PsIconKey.ChevronRight }) })] }), view === PsCalendarView.month ? (_jsx("div", { className: 'grid grid-cols-3 gap-1', children: PsDateInputService.monthNames().map((name, month) => (_jsx("button", { className: PallasoftClassNameService.merge(cellClassName, month === monthDate.getMonth() ? selectedCellClassName : undefined), disabled: PsDateInputService.isMonthOutOfRange(year, month, minDate, maxDate), onClick: () => {
51
+ }, type: 'button', children: [navigation.title, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 rotate-90 text-ink/50', iconKey: PsIconKey.ChevronRight })] })) : (_jsx("p", { "aria-live": 'polite', className: 'text-sm font-semibold text-ink', children: navigation.title })), _jsx("button", { "aria-label": navigation.nextLabel, className: PsCalendarHeaderClasses.navigationButton, disabled: navigation.isNextDisabled, onClick: navigation.next, type: 'button', children: _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-4 w-4', iconKey: PsIconKey.ChevronRight }) })] }), view === PsCalendarView.month ? (_jsx("div", { className: 'grid grid-cols-3 gap-1', children: PsDateInputService.monthNames().map((name, month) => (_jsx("button", { className: PallasoftClassNameService.merge(PsCalendarHeaderClasses.cell, month === monthDate.getMonth() ? PsCalendarHeaderClasses.selectedCell : undefined), disabled: PsDateInputService.isMonthOutOfRange(year, month, minDate, maxDate), onClick: () => {
55
52
  changeMonth(month);
56
53
  onViewChange(PsCalendarView.day);
57
- }, type: 'button', children: name }, name))) })) : null, view === PsCalendarView.year ? (_jsx("div", { className: 'grid grid-cols-3 gap-1', children: years.map((candidate) => (_jsx("button", { className: PallasoftClassNameService.merge(cellClassName, candidate === year ? selectedCellClassName : undefined), disabled: PsDateInputService.isYearOutOfRange(candidate, minDate, maxDate), onClick: () => {
54
+ }, type: 'button', children: name }, name))) })) : null, view === PsCalendarView.year ? (_jsx("div", { className: 'grid grid-cols-3 gap-1', children: years.map((candidate) => (_jsx("button", { className: PallasoftClassNameService.merge(PsCalendarHeaderClasses.cell, candidate === year ? PsCalendarHeaderClasses.selectedCell : undefined), disabled: PsDateInputService.isYearOutOfRange(candidate, minDate, maxDate), onClick: () => {
58
55
  if (onYearPick !== undefined) {
59
56
  onYearPick(candidate);
60
57
  return;
@@ -48,7 +48,7 @@ export const PsCascaderInput = ({ className, disabled, groups, helperText, hideL
48
48
  : option.value === value
49
49
  ? 'bg-primary/10 text-ink'
50
50
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), disabled: option.isDisabled, 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 break-words', children: option.label }), groupLabel ? (_jsx("span", { className: 'mt-0.5 block break-words text-xs font-normal text-ink/50', children: groupLabel })) : null, option.description ? (_jsx("span", { className: 'mt-0.5 block break-words text-xs font-normal text-ink/55', children: option.description })) : null] })] }, option.value));
51
- 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
51
+ 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 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-control-compact ps-focus-ring 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
52
52
  ? 'bg-mist text-ink'
53
53
  : '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
54
54
  ? activeGroup.options.map((option) => renderOption(option, null, close))
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { PsAccordion } from '@pallasoft/ps-core-components';
4
+ import { PsCheckboxMatrixService } from '../services/ps-checkbox-matrix-service';
5
+ import { PsCheckbox } from './ps-checkbox';
6
+ export const PsCheckboxMatrix = ({ columns, defaultOpenGroupId = null, groups, isReadOnly = false, labels, onChange, value, }) => {
7
+ const [openGroupId, setOpenGroupId] = useState(defaultOpenGroupId);
8
+ return (_jsx("div", { className: 'flex flex-col gap-2', children: groups.map((group) => {
9
+ const total = PsCheckboxMatrixService.values(group).length;
10
+ const selected = PsCheckboxMatrixService.selectedCount(group, value);
11
+ const usedColumns = columns.filter((column) => group.rows.some((row) => row.cells.some((cell) => cell.columnId === column.id)));
12
+ const isComplete = PsCheckboxMatrixService.isGroupComplete(group, value);
13
+ return (_jsx(PsAccordion, { isOpen: openGroupId === group.id, label: group.label, onToggle: () => setOpenGroupId(openGroupId === group.id ? null : group.id), trailing: _jsx("span", { className: 'text-xs font-normal text-ink/55', children: labels.count(selected, total) }), children: _jsxs("div", { className: 'flex flex-col gap-3 px-4 pb-4', children: [_jsx(PsCheckbox, { isDisabled: isReadOnly || PsCheckboxMatrixService.enabledValues(group).length === 0, isIndeterminate: selected > 0 && !isComplete, isSelected: isComplete, label: labels.selectGroup(group), onChange: (isSelected) => onChange(PsCheckboxMatrixService.toggleGroup(value, group, isSelected)), children: _jsx("span", { className: 'text-sm font-medium text-ink', children: labels.selectGroup(group) }) }), _jsx("div", { className: 'overflow-x-auto', children: _jsxs("table", { className: 'w-full border-collapse text-sm', children: [_jsx("thead", { children: _jsxs("tr", { className: 'text-xs text-ink/55', children: [_jsx("th", { className: 'py-1.5 pr-3 text-left font-medium', scope: 'col', children: labels.rowHeading }), usedColumns.map((column) => (_jsx("th", { className: 'w-14 px-1 py-1.5 text-center font-medium', scope: 'col', title: column.hint === null ? undefined : column.hint, children: column.label }, column.id)))] }) }), _jsx("tbody", { children: group.rows.map((row) => (_jsxs("tr", { className: 'border-t border-line/70', children: [_jsx("th", { className: 'py-2 pr-3 text-left font-normal text-ink', scope: 'row', children: row.label }), usedColumns.map((column) => {
14
+ const cell = row.cells.find((item) => item.columnId === column.id);
15
+ return (_jsx("td", { className: 'px-1 py-2 text-center', children: cell === undefined ? null : (_jsx("span", { className: 'inline-flex', title: cell.reason === null ? undefined : cell.reason, children: _jsx(PsCheckbox, { isDisabled: isReadOnly || cell.isDisabled, isSelected: value.includes(cell.value), label: cell.reason === null
16
+ ? labels.cell(row, column)
17
+ : `${labels.cell(row, column)}. ${cell.reason}`, onChange: (isSelected) => onChange(PsCheckboxMatrixService.toggle(value, cell.value, isSelected)) }) })) }, column.id));
18
+ })] }, row.id))) })] }) })] }) }, group.id));
19
+ }) }));
20
+ };
@@ -35,7 +35,7 @@ export const PsColorPicker = ({ className, disabled, helperText, hideLabel, labe
35
35
  saturation: Math.round((x / bounds.width) * 100),
36
36
  }));
37
37
  };
38
- return (_jsxs("div", { className: PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : _jsx("span", { className: 'ps-input-label block', children: label }), _jsxs(DialogTrigger, { children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex min-h-11 w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [_jsx("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), _jsx("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [_jsx("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
38
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('flex flex-col gap-2', className), children: [hideLabel ? null : _jsx("span", { className: 'ps-input-label block', children: label }), _jsxs(DialogTrigger, { children: [_jsxs(Button, { "aria-label": hideLabel ? label : undefined, className: 'ps-input-control ps-focus-ring flex w-full items-center gap-3 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', isDisabled: disabled, children: [_jsx("span", { className: 'h-6 w-6 shrink-0 rounded-md border border-line', style: { backgroundColor: swatchColor ? swatchColor : 'transparent' } }), _jsx("span", { className: 'font-mono text-sm uppercase', children: swatchColor ? swatchColor : 'Pick a colour' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'ml-auto block h-4 w-4 shrink-0 text-primary', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-[min(calc(100vw-2rem),18rem)] outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": label, className: 'flex flex-col gap-3 p-3 outline-none', children: [_jsx("div", { className: 'relative h-36 w-full cursor-crosshair rounded-ps-control', onPointerDown: (event) => {
39
39
  event.currentTarget.setPointerCapture(event.pointerId);
40
40
  pickFromArea(event);
41
41
  }, onPointerMove: (event) => {
@@ -49,7 +49,7 @@ export const PsColorPicker = ({ className, disabled, helperText, hideLabel, labe
49
49
  backgroundColor: swatchColor ? swatchColor : 'transparent',
50
50
  } }) }), _jsxs("label", { className: 'flex flex-col gap-1', children: [_jsx("span", { className: 'ps-input-helper', children: "Hue" }), _jsx("input", { className: 'ps-focus-ring h-3 w-full cursor-pointer appearance-none rounded-full', max: 360, min: 0, onChange: (event) => onChange(PsColorService.toHex({ ...hsv, hue: Number(event.target.value) })), step: 1, style: {
51
51
  background: 'linear-gradient(to right, #FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000)',
52
- }, type: 'range', value: hsv.hue })] }), _jsx("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-focus-ring h-10 w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
52
+ }, type: 'range', value: hsv.hue })] }), _jsx("input", { "aria-label": `${label} hex`, className: 'ps-input-control ps-control-compact ps-focus-ring w-full font-mono text-sm uppercase', maxLength: 7, onBlur: (event) => commitHex(event.target.value), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
53
53
  if (event.key !== 'Enter')
54
54
  return;
55
55
  event.preventDefault();
@@ -4,7 +4,7 @@ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
4
4
  import { ComboBox, Input, Label, ListBox, ListBoxItem, Popover } from 'react-aria-components';
5
5
  import { PsComboboxInputService } from '../services/ps-combobox-input-service';
6
6
  import { PsRequiredMark } from './ps-required-mark';
7
- export const PsComboboxInput = ({ className, getItemKey, getItemLabel, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, }) => {
7
+ export const PsComboboxInput = ({ className, emptyText, getItemKey, getItemLabel, hideLabel = false, inputValue, isLoading = false, items, label, onInputChange, onSelectionChange, placeholder, renderItem, required, selectedKey, }) => {
8
8
  const itemsByKey = new Map(items.map((item) => [getItemKey(item), item]));
9
- return (_jsxs(ComboBox, { className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, items: items, onInputChange: onInputChange, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring min-h-11 w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-xl px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
9
+ return (_jsxs(ComboBox, { allowsEmptyCollection: true, "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), defaultFilter: () => true, inputValue: inputValue, items: items, onInputChange: onInputChange, selectedKey: selectedKey, onSelectionChange: (key) => onSelectionChange?.(key === null ? null : PsComboboxInputService.getItem(itemsByKey, key)), children: [label && !hideLabel ? (_jsxs(Label, { className: 'ps-input-label', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })) : null, _jsx("span", { className: hideLabel || !label ? 'relative block' : 'relative mt-2 block', children: _jsx(Input, { className: 'ps-input-control ps-focus-ring w-full text-sm font-semibold', placeholder: placeholder }) }), _jsx(Popover, { className: 'w-[--trigger-width] rounded-2xl border border-line bg-white/95 p-1.5 shadow-lg dark:border-white/10 dark:bg-slate-900/95', children: isLoading ? (_jsx("div", { className: 'flex items-center justify-center py-4', children: _jsx(PsSpinner, { label: 'Loading results', size: 'small' }) })) : (_jsx(ListBox, { className: 'max-h-72 overflow-y-auto outline-none', items: items, renderEmptyState: () => emptyText ? _jsx("div", { className: 'px-3 py-2 text-sm text-ink/55', children: emptyText }) : null, children: (item) => (_jsx(ListBoxItem, { className: 'ps-focus-ring cursor-pointer rounded-ps-control px-3 py-2 text-sm font-semibold text-ink selected:bg-primary-soft selected:text-primary hover:bg-slate-50 dark:hover:bg-white/6', id: getItemKey(item), textValue: getItemLabel(item), children: renderItem ? renderItem(item) : getItemLabel(item) })) })) })] }));
10
10
  };
@@ -38,5 +38,5 @@ export const PsDateInput = ({ className, defaultValue, disabled, helperText, hid
38
38
  setUncontrolledValue(nextValue);
39
39
  onChange?.(nextValue);
40
40
  };
41
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === PsCalendarView.day ? undefined : PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: [...PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
41
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: PallasoftClassNameService.merge('ps-floating-panel ps-datepicker', view === PsCalendarView.day ? undefined : PsDateInputConfig.pickingClassName), className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: [...PsDateInputConfig.inputFormats], disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onCalendarClose: () => setView(PsCalendarView.day), onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: setView, view: view })), required: required, selected: PsDateInputService.parse(currentValue), showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
42
42
  };
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PsDateInput } from './ps-date-input';
3
3
  import { PsFormControl } from './ps-form-control';
4
4
  export const PsDatePresetField = ({ errorText, hideLabel, label, onChange, presets, presetsDisabled = false, presetsLabel, required, value, }) => (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsx(PsFormControl, { errorText: errorText, children: _jsx(PsDateInput, { hideLabel: hideLabel, label: label, onChange: onChange, required: required, value: value }) }), _jsx("div", { "aria-label": presetsLabel, className: 'flex flex-wrap gap-1.5', role: 'group', children: presets.map((preset) => (_jsx("button", { "aria-pressed": preset.date !== '' && preset.date === value, className: preset.date !== '' && preset.date === value
5
- ? 'ps-focus-ring rounded-full bg-primary px-2.5 py-1 text-xs font-semibold text-white'
6
- : 'ps-focus-ring rounded-full border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
5
+ ? 'ps-focus-ring rounded-ps-control bg-primary px-2.5 py-1 text-xs font-semibold text-white'
6
+ : 'ps-focus-ring rounded-ps-control border border-line px-2.5 py-1 text-xs font-medium text-ink/70 hover:border-primary/40 hover:text-ink disabled:opacity-40', disabled: presetsDisabled, onClick: () => onChange(preset.date), type: 'button', children: preset.label }, preset.label))) })] }));
@@ -1,3 +1,3 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
- export const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => (_jsxs("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), hideLabel ? null : _jsx("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), _jsx("span", { className: PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-11', className) })] }));
3
+ export const PsFieldSkeleton = ({ className, hideLabel, label, rows = 1, }) => (_jsxs("div", { "aria-busy": 'true', className: 'block', role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), hideLabel ? null : _jsx("span", { className: 'ps-skeleton mb-2 block h-2.5 w-24 rounded-full' }), _jsx("span", { className: PallasoftClassNameService.merge('ps-skeleton block w-full rounded-ps-control', rows > 1 ? 'min-h-24' : 'min-h-ps-control', className) })] }));
@@ -25,5 +25,5 @@ export const PsFilePicker = ({ accept, acceptLabel, className, disabled, dropLab
25
25
  }
26
26
  onFileLoad(newFile);
27
27
  };
28
- return (_jsxs("div", { className: PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-lg border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [_jsxs("div", { className: 'flex flex-col items-center gap-3 text-center', children: [_jsx(PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), _jsxs("div", { children: [_jsx("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), _jsx("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? _jsx("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, _jsxs("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), _jsx("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
28
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('relative flex h-48 w-full flex-col items-center justify-center rounded-ps-control border-2 border-dashed border-line p-4 transition-all hover:border-primary/50 hover:bg-primary/5 sm:h-64', className), children: [_jsxs("div", { className: 'flex flex-col items-center gap-3 text-center', children: [_jsx(PsIcon, { iconKey: 'upload', className: 'h-8 w-8 text-primary' }), _jsxs("div", { children: [_jsx("p", { className: 'text-body-2 font-medium text-ink sm:text-body-1', children: dropLabel }), _jsx("p", { className: 'mt-1 text-body-3 text-ink/60 sm:text-body-2', children: "or click to browse your files" }), maxSizeLabel ? _jsx("p", { className: 'mt-3 text-body-3 text-ink/60', children: maxSizeLabel }) : null, _jsxs("p", { className: 'text-body-3 text-ink/60', children: ["Accepted formats: ", acceptLabel] })] })] }), _jsx("input", { type: 'file', accept: acceptAttr, className: 'absolute inset-0 h-full w-full cursor-pointer opacity-0', "aria-label": 'File upload', onChange: onFileChange, disabled: disabled, "aria-disabled": disabled })] }));
29
29
  };
@@ -20,7 +20,7 @@ export const PsMultiSelectInput = ({ className, defaultValue, disabled, helperTe
20
20
  setUncontrolledValue(nextValue);
21
21
  onChange?.(nextValue);
22
22
  };
23
- return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex min-h-11 w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
23
+ return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, selectionMode: 'multiple', value: currentValue.filter((selected) => labelByValue.has(selected)), children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center py-1.5 pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'flex min-w-0 flex-1 flex-wrap gap-1.5', children: ({ isPlaceholder }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (currentValue
24
24
  .filter((selected) => labelByValue.has(selected))
25
- .map((selected) => (_jsx("span", { className: 'inline-flex max-w-full items-center rounded-full bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: _jsx("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
25
+ .map((selected) => (_jsx("span", { className: 'inline-flex max-w-full items-center rounded-ps-control bg-primary/12 px-2.5 py-0.5 text-xs font-semibold text-ink', children: _jsx("span", { className: 'truncate', children: labelByValue.get(selected) }) }, selected)))) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
26
26
  };
@@ -34,7 +34,7 @@ export const PsPhoneInput = ({ className, defaultCountry = PsPhoneInputConfig.de
34
34
  emit(national, code);
35
35
  document.getElementById(inputId)?.focus();
36
36
  };
37
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-input-control flex min-h-11 items-stretch overflow-hidden p-0 focus-within:border-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [_jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [_jsxs(Button, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'ps-focus-ring flex shrink-0 items-center gap-1.5 border-r border-line px-3 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-focus-ring h-10 w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), _jsx("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => (_jsx("li", { role: 'none', children: _jsxs("button", { "aria-selected": option.code === country, className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
37
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: PallasoftClassNameService.merge('ps-input-control flex items-stretch overflow-hidden p-0 focus-within:border-primary has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary', hideLabel ? '' : 'mt-2', isInvalid ? 'border-danger bg-danger/5' : '', disabled ? 'opacity-60' : ''), children: [_jsxs(DialogTrigger, { isOpen: isOpen, onOpenChange: setIsOpen, children: [_jsxs(Button, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex shrink-0 items-center gap-1.5 border-r border-line px-3 outline-none focus-visible:bg-primary/10 text-sm font-semibold text-ink', isDisabled: disabled, children: [country, _jsx(PsIcon, { "aria-hidden": 'true', className: 'block h-3.5 w-3.5 text-ink/45', iconKey: PsIconKey.Chevron })] }), _jsx(Popover, { className: 'ps-floating-panel w-72 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsxs(Dialog, { "aria-label": PsPhoneInputConfig.countryLabel, className: 'flex flex-col outline-none', children: [_jsx("div", { className: 'border-b border-line p-2', children: _jsx("input", { "aria-label": PsPhoneInputConfig.searchPlaceholder, autoFocus: true, className: 'ps-input-control ps-control-compact ps-focus-ring w-full text-sm', onChange: (event) => setQuery(event.target.value), placeholder: PsPhoneInputConfig.searchPlaceholder, type: 'search', value: query }) }), _jsx("ul", { className: 'ps-scrollbar-hidden max-h-64 overflow-y-auto p-1.5', role: 'listbox', children: matches.length === 0 ? (_jsx("li", { className: 'px-3 py-2.5 text-sm text-ink/50', children: PsPhoneInputConfig.emptyMessage })) : (matches.map((option) => (_jsx("li", { role: 'none', children: _jsxs("button", { "aria-selected": option.code === country, className: PallasoftClassNameService.merge('ps-focus-ring flex w-full items-center justify-between gap-3 rounded-ps-control px-3 py-2.5 text-left text-sm', option.code === country
38
38
  ? 'bg-primary/10 text-ink'
39
39
  : 'text-ink/80 hover:bg-mist/60 hover:text-ink'), onClick: () => choose(option.code), role: 'option', type: 'button', children: [_jsx("span", { className: 'min-w-0 truncate', children: PsPhoneInputService.highlight(option.label, query).map((part, index) => part.isMatch ? (_jsx("strong", { className: 'font-semibold text-ink', children: part.text }, index)) : (_jsx("span", { children: part.text }, index))) }), _jsxs("span", { className: 'shrink-0 text-xs text-ink/50', children: ["+", option.callingCode] })] }) }, option.code)))) })] }) })] }), _jsxs("span", { "aria-hidden": 'true', className: 'flex items-center pl-3 text-sm text-ink/45', children: [PsPhoneInputConfig.plus, PsPhoneInputService.callingCode(country)] }), _jsx("input", { "aria-invalid": isInvalid, autoComplete: 'tel-national', className: 'min-w-0 flex-1 bg-transparent px-2 text-sm text-ink outline-none', disabled: disabled, id: inputId, inputMode: 'tel', name: name, onBlur: () => {
40
40
  setIsTouched(true);
@@ -21,5 +21,5 @@ export const PsSelectInput = ({ className, defaultValue, disabled, helperText, h
21
21
  setUncontrolledValue(nextValue);
22
22
  onChange?.(nextValue);
23
23
  };
24
- return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { 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'), children: [_jsx(SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
24
+ return (_jsxs(Select, { "aria-label": hideLabel ? label : undefined, className: PallasoftClassNameService.merge('block', className), isDisabled: disabled, isRequired: required, name: name, onChange: handleChange, placeholder: placeholder, value: hasOption ? currentValue : null, children: [hideLabel ? null : (_jsxs(Label, { className: 'ps-input-label block', children: [label, _jsx(PsRequiredMark, { isRequired: required })] })), _jsxs(Button, { className: PallasoftClassNameService.merge('ps-input-control ps-focus-ring relative flex w-full items-center pr-10 text-left text-sm font-semibold disabled:cursor-not-allowed disabled:opacity-60', hideLabel ? '' : 'mt-2'), children: [_jsx(SelectValue, { className: 'min-w-0 flex-1 truncate', children: ({ isPlaceholder, selectedText }) => isPlaceholder ? (_jsx("span", { className: 'font-medium text-ink/45', children: placeholder })) : (selectedText) }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary', iconKey: PsIconKey.Chevron })] }), helperText ? (_jsx(Text, { className: 'ps-input-helper', slot: 'description', children: helperText })) : null, _jsx(Popover, { className: 'ps-floating-panel ps-scrollbar-hidden max-h-72 min-w-[var(--trigger-width)] overflow-y-auto p-1.5 outline-none', offset: 6, placement: 'bottom start', style: { zIndex }, children: _jsx(ListBox, { className: 'outline-none', items: options.map((option) => ({ ...option, id: option.value })), children: (option) => _jsx(PsSelectOptionItem, { option: option }) }) })] }));
25
25
  };
@@ -1,3 +1,3 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
- export const PsToggle = ({ description, isChecked, label, name, onChange }) => (_jsxs("label", { className: 'ps-focus-ring flex cursor-pointer items-center justify-between gap-4 rounded-2xl border border-line bg-white/78 px-4 py-3 text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [_jsxs("span", { children: [_jsx("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? (_jsx("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), _jsx("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), _jsx("span", { className: PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: _jsx("span", { className: PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
3
+ export const PsToggle = ({ description, isChecked, label, name, onChange }) => (_jsxs("label", { className: 'ps-control flex cursor-pointer items-center justify-between gap-4 rounded-ps-control border border-line bg-white/78 px-4 py-3 has-[:focus-visible]:outline has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-primary text-ink transition-colors hover:border-primary/35 dark:border-white/10 dark:bg-white/6 dark:text-white', children: [_jsxs("span", { children: [_jsx("span", { className: 'block text-sm font-semibold text-current', children: label }), description ? (_jsx("span", { className: 'mt-1 block text-xs leading-5 text-slate-500 dark:text-slate-400', children: description })) : null] }), _jsx("input", { checked: isChecked, className: 'sr-only', name: name, onChange: (event) => onChange?.(event.target.checked), type: 'checkbox' }), _jsx("span", { className: PallasoftClassNameService.merge('flex h-7 w-12 items-center rounded-full p-1 transition', isChecked ? 'bg-primary' : 'bg-slate-200 dark:bg-slate-700'), children: _jsx("span", { className: PallasoftClassNameService.merge('h-5 w-5 rounded-full bg-white ring-1 ring-black/5 transition dark:ring-white/10', isChecked && 'translate-x-5') }) })] }));
@@ -40,7 +40,7 @@ export const PsYearInput = ({ className, defaultValue, disabled, helperText, hid
40
40
  setUncontrolledValue(nextValue);
41
41
  onChange?.(nextValue);
42
42
  };
43
- return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring min-h-11 w-full pr-10 text-sm font-semibold', dateFormat: PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
43
+ return (_jsxs("div", { className: PallasoftClassNameService.merge('block', className), children: [_jsxs("label", { className: hideLabel ? 'sr-only' : 'ps-input-label block', htmlFor: inputId, children: [label, _jsx(PsRequiredMark, { isRequired: required })] }), _jsxs("div", { className: hideLabel ? 'relative' : 'relative mt-2', children: [_jsx(DatePicker, { autoComplete: 'off', calendarClassName: `ps-floating-panel ps-datepicker ${PsDateInputConfig.pickingClassName}`, className: 'ps-input-control ps-focus-ring w-full pr-10 text-sm font-semibold', dateFormat: PsYearInputConfig.format, disabled: disabled, id: inputId, maxDate: maxDate, minDate: minDate, onChange: handleChange, placeholderText: placeholder, popperClassName: 'ps-datepicker-popper', popperPlacement: 'bottom-start', popperProps: { strategy: 'fixed' }, portalId: portalId, ref: pickerRef, renderCustomHeader: (headerProps) => (_jsx(PsCalendarHeader, { ...headerProps, maxDate: maxDate, minDate: minDate, onViewChange: () => undefined, onYearPick: (year) => {
44
44
  handleChange(PsYearInputService.startOfYear(year));
45
45
  pickerRef.current?.setOpen(false);
46
46
  }, selectedYear: selected === null ? undefined : selected.getFullYear(), view: PsCalendarView.year })), required: required, selected: selected, showPopperArrow: false, wrapperClassName: 'block w-full' }), _jsx(PsIcon, { "aria-hidden": 'true', className: 'pointer-events-none absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2 text-ink/50', iconKey: PsIconKey.Calendar }), name ? _jsx("input", { name: name, type: 'hidden', value: currentValue }) : null] }), helperText ? _jsx("span", { className: 'ps-input-helper', children: helperText }) : null] }));
@@ -0,0 +1,6 @@
1
+ export const PsCalendarHeaderClasses = {
2
+ navigationButton: 'ps-focus-ring ps-control-square ps-control-compact flex items-center justify-center rounded-ps-control text-ink/60 transition-colors hover:bg-primary/10 hover:text-ink disabled:cursor-not-allowed disabled:opacity-30',
3
+ titleButton: 'ps-focus-ring ps-control-compact ps-control-padding-compact flex items-center gap-1 rounded-ps-control text-sm font-semibold text-ink transition-colors hover:bg-primary/10',
4
+ cell: 'ps-focus-ring ps-control flex items-center justify-center rounded-ps-control text-sm font-medium text-ink transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent',
5
+ selectedCell: 'bg-primary font-bold text-[var(--ps-color-primary-contrast)] hover:bg-primary',
6
+ };
@@ -2,8 +2,8 @@ export const PsPortableTextEditorConfig = {
2
2
  classNames: {
3
3
  editable: 'ps-input-control w-full resize-none overflow-y-auto rounded-t-none border-t-0 leading-6 outline-none',
4
4
  root: 'block',
5
- toolbar: 'flex flex-wrap items-center gap-1 rounded-t-xl border border-line bg-white p-1 dark:bg-transparent',
6
- button: 'ps-focus-ring inline-flex h-9 min-w-9 items-center justify-center rounded-lg px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
5
+ toolbar: 'flex flex-wrap items-center gap-1 rounded-t-ps-control border border-line bg-white p-1 dark:bg-transparent',
6
+ button: 'ps-focus-ring ps-control-compact inline-flex min-w-ps-control-compact items-center justify-center rounded-ps-control px-2 text-sm text-ink/70 transition-colors hover:bg-ink/5 hover:text-ink disabled:cursor-not-allowed disabled:opacity-40',
7
7
  buttonActive: 'bg-primary text-white hover:bg-primary hover:text-white',
8
8
  separator: 'mx-1 h-5 w-px bg-line',
9
9
  },
package/dist/esm/index.js CHANGED
@@ -47,3 +47,10 @@ export * from './constants/ps-select-with-create-config';
47
47
  export * from './interfaces/ps-date-preset-data';
48
48
  export * from './components/ps-option-card-group';
49
49
  export * from './interfaces/ps-option-card-data';
50
+ export * from './components/ps-checkbox-matrix';
51
+ export * from './interfaces/ps-checkbox-matrix-cell';
52
+ export * from './interfaces/ps-checkbox-matrix-column';
53
+ export * from './interfaces/ps-checkbox-matrix-group';
54
+ export * from './interfaces/ps-checkbox-matrix-labels';
55
+ export * from './interfaces/ps-checkbox-matrix-row';
56
+ export * from './services/ps-checkbox-matrix-service';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ export class PsCheckboxMatrixService {
2
+ static values(group) {
3
+ return group.rows.flatMap((row) => row.cells.map((cell) => cell.value));
4
+ }
5
+ static enabledValues(group) {
6
+ return group.rows.flatMap((row) => row.cells.filter((cell) => !cell.isDisabled).map((cell) => cell.value));
7
+ }
8
+ static selectedCount(group, value) {
9
+ return PsCheckboxMatrixService.values(group).filter((item) => value.includes(item)).length;
10
+ }
11
+ static toggle(value, item, isSelected) {
12
+ return isSelected
13
+ ? value.includes(item)
14
+ ? value
15
+ : [...value, item]
16
+ : value.filter((existing) => existing !== item);
17
+ }
18
+ static toggleGroup(value, group, isSelected) {
19
+ const enabled = PsCheckboxMatrixService.enabledValues(group);
20
+ return isSelected
21
+ ? [...value, ...enabled.filter((item) => !value.includes(item))]
22
+ : value.filter((item) => !enabled.includes(item));
23
+ }
24
+ static isGroupComplete(group, value) {
25
+ const enabled = PsCheckboxMatrixService.enabledValues(group);
26
+ return enabled.length > 0 && enabled.every((item) => value.includes(item));
27
+ }
28
+ }
package/dist/index.d.ts CHANGED
@@ -47,3 +47,10 @@ export * from './constants/ps-select-with-create-config';
47
47
  export * from './interfaces/ps-date-preset-data';
48
48
  export * from './components/ps-option-card-group';
49
49
  export * from './interfaces/ps-option-card-data';
50
+ export * from './components/ps-checkbox-matrix';
51
+ export * from './interfaces/ps-checkbox-matrix-cell';
52
+ export * from './interfaces/ps-checkbox-matrix-column';
53
+ export * from './interfaces/ps-checkbox-matrix-group';
54
+ export * from './interfaces/ps-checkbox-matrix-labels';
55
+ export * from './interfaces/ps-checkbox-matrix-row';
56
+ export * from './services/ps-checkbox-matrix-service';
package/dist/index.js CHANGED
@@ -63,3 +63,10 @@ __exportStar(require("./constants/ps-select-with-create-config"), exports);
63
63
  __exportStar(require("./interfaces/ps-date-preset-data"), exports);
64
64
  __exportStar(require("./components/ps-option-card-group"), exports);
65
65
  __exportStar(require("./interfaces/ps-option-card-data"), exports);
66
+ __exportStar(require("./components/ps-checkbox-matrix"), exports);
67
+ __exportStar(require("./interfaces/ps-checkbox-matrix-cell"), exports);
68
+ __exportStar(require("./interfaces/ps-checkbox-matrix-column"), exports);
69
+ __exportStar(require("./interfaces/ps-checkbox-matrix-group"), exports);
70
+ __exportStar(require("./interfaces/ps-checkbox-matrix-labels"), exports);
71
+ __exportStar(require("./interfaces/ps-checkbox-matrix-row"), exports);
72
+ __exportStar(require("./services/ps-checkbox-matrix-service"), exports);
@@ -0,0 +1,6 @@
1
+ export interface PsCheckboxMatrixCell {
2
+ columnId: string;
3
+ isDisabled: boolean;
4
+ reason: string | null;
5
+ value: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export interface PsCheckboxMatrixColumn {
2
+ hint: string | null;
3
+ id: string;
4
+ label: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import type { PsCheckboxMatrixRow } from './ps-checkbox-matrix-row';
2
+ export interface PsCheckboxMatrixGroup {
3
+ id: string;
4
+ label: string;
5
+ rows: PsCheckboxMatrixRow[];
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import type { PsCheckboxMatrixColumn } from './ps-checkbox-matrix-column';
2
+ import type { PsCheckboxMatrixGroup } from './ps-checkbox-matrix-group';
3
+ import type { PsCheckboxMatrixRow } from './ps-checkbox-matrix-row';
4
+ export interface PsCheckboxMatrixLabels {
5
+ cell: (row: PsCheckboxMatrixRow, column: PsCheckboxMatrixColumn) => string;
6
+ count: (selected: number, total: number) => string;
7
+ rowHeading: string;
8
+ selectGroup: (group: PsCheckboxMatrixGroup) => string;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import type { PsCheckboxMatrixCell } from './ps-checkbox-matrix-cell';
2
+ export interface PsCheckboxMatrixRow {
3
+ cells: PsCheckboxMatrixCell[];
4
+ id: string;
5
+ label: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import type { PsCheckboxMatrixGroup } from '../interfaces/ps-checkbox-matrix-group';
2
+ export declare class PsCheckboxMatrixService {
3
+ static values(group: PsCheckboxMatrixGroup): string[];
4
+ static enabledValues(group: PsCheckboxMatrixGroup): string[];
5
+ static selectedCount(group: PsCheckboxMatrixGroup, value: string[]): number;
6
+ static toggle(value: string[], item: string, isSelected: boolean): string[];
7
+ static toggleGroup(value: string[], group: PsCheckboxMatrixGroup, isSelected: boolean): string[];
8
+ static isGroupComplete(group: PsCheckboxMatrixGroup, value: string[]): boolean;
9
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsCheckboxMatrixService = void 0;
4
+ class PsCheckboxMatrixService {
5
+ static values(group) {
6
+ return group.rows.flatMap((row) => row.cells.map((cell) => cell.value));
7
+ }
8
+ static enabledValues(group) {
9
+ return group.rows.flatMap((row) => row.cells.filter((cell) => !cell.isDisabled).map((cell) => cell.value));
10
+ }
11
+ static selectedCount(group, value) {
12
+ return PsCheckboxMatrixService.values(group).filter((item) => value.includes(item)).length;
13
+ }
14
+ static toggle(value, item, isSelected) {
15
+ return isSelected
16
+ ? value.includes(item)
17
+ ? value
18
+ : [...value, item]
19
+ : value.filter((existing) => existing !== item);
20
+ }
21
+ static toggleGroup(value, group, isSelected) {
22
+ const enabled = PsCheckboxMatrixService.enabledValues(group);
23
+ return isSelected
24
+ ? [...value, ...enabled.filter((item) => !value.includes(item))]
25
+ : value.filter((item) => !enabled.includes(item));
26
+ }
27
+ static isGroupComplete(group, value) {
28
+ const enabled = PsCheckboxMatrixService.enabledValues(group);
29
+ return enabled.length > 0 && enabled.every((item) => value.includes(item));
30
+ }
31
+ }
32
+ exports.PsCheckboxMatrixService = PsCheckboxMatrixService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-input-components",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -52,7 +52,6 @@
52
52
  "dependencies": {
53
53
  "@internationalized/date": "^3.12.2",
54
54
  "@pallasoft/ps-core-components": "^2.10.0",
55
- "@pallasoft/ps-design-system": "^1.5.0",
56
55
  "@pallasoft/ps-icons": "^1.5.4",
57
56
  "@pallasoft/ps-models": "^1.4.0",
58
57
  "@pallasoft/ps-popovers": "^1.7.0",
@@ -74,6 +73,7 @@
74
73
  "@commitlint/config-conventional": "^20.0.0",
75
74
  "@eslint/compat": "^2.0.0",
76
75
  "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
76
+ "@pallasoft/ps-design-system": "^1.14.0",
77
77
  "@semantic-release/changelog": "^6.0.3",
78
78
  "@semantic-release/commit-analyzer": "^13.0.0",
79
79
  "@semantic-release/git": "^10.0.1",