autocasting-ui-library-padimasso 1.6.7 → 1.6.9

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.
@@ -2,7 +2,8 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { clsx } from 'clsx';
3
3
 
4
4
  function ChoiceChip({ label, selected = false, className, type = 'button', ...rest }) {
5
- return (jsx("button", { type: type, className: clsx('px-4 py-1 rounded-full whitespace-nowrap cursor-pointer bg-transparent border-1', selected
5
+ const isDisabled = Boolean(rest.disabled);
6
+ return (jsx("button", { type: type, className: clsx('px-4 py-1 rounded-full whitespace-nowrap bg-transparent border-1', isDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', selected
6
7
  ? 'text-(--color-primary-purple) border-(--color-primary-purple)'
7
8
  : 'text-(--color-secondary-grey-fonts) border-(--color-secondary-outline)', className), "aria-pressed": selected, ...rest, children: label }));
8
9
  }
@@ -22,10 +22,10 @@ const TOAST_ICON_BY_TYPE = {
22
22
  warning: { name: 'warning', variant: 'default' },
23
23
  danger: { name: 'info', variant: 'danger' },
24
24
  };
25
- function Toast({ title, description, type = 'default', className, titleClassName, descriptionClassName, iconClassName, role, ...rest }) {
25
+ function Toast({ title, description, type = 'default', className, titleClassName, descriptionClassName, iconClassName, fullWidth = false, closable = false, onClose, role, ...rest }) {
26
26
  const styles = TYPE_STYLES[type];
27
27
  const icon = TOAST_ICON_BY_TYPE[type];
28
- return (jsxs("article", { "data-toast-type": type, "data-toast-part": "root", role: role ?? (type === 'danger' ? 'alert' : 'status'), className: clsx('flex w-full max-w-[330px] flex-row items-center gap-3 rounded-lg p-3 shadow-md', styles.container, className), ...rest, children: [jsx(Icon, { name: icon.name, variant: icon.variant, "aria-hidden": "true", className: clsx('cursor-default', iconClassName) }), jsxs("div", { "data-toast-part": "content", className: "flex-1", children: [jsx("p", { "data-toast-part": "title", className: clsx('text-sm font-semibold', titleClassName), children: title }), description ? (jsx("p", { "data-toast-part": "description", className: clsx('text-sm font-light text-(--color-secondary-gray)', descriptionClassName), children: description })) : null] })] }));
28
+ return (jsxs("article", { "data-toast-type": type, "data-toast-part": "root", role: role ?? (type === 'danger' ? 'alert' : 'status'), className: clsx('flex w-full flex-row items-center gap-3 rounded-lg p-3 shadow-md', fullWidth ? 'max-w-[650px]' : 'max-w-[330px]', styles.container, className), ...rest, children: [jsx(Icon, { name: icon.name, variant: icon.variant, "aria-hidden": "true", className: clsx('cursor-default', iconClassName) }), jsxs("div", { "data-toast-part": "content", className: `flex min-w-0 flex-1 flex-col gap-1`, children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx("p", { "data-toast-part": "title", className: clsx('text-sm font-semibold', titleClassName), children: title }), closable ? (jsx("button", { type: "button", "aria-label": "Close toast", className: "cursor-pointer", onClick: onClose, children: jsx(Icon, { name: "cross", variant: "default", "aria-hidden": "true", size: 10 }) })) : null] }), description ? (jsx("p", { "data-toast-part": "description", className: clsx('text-sm font-light text-(--color-secondary-gray)', descriptionClassName), children: description })) : null] })] }));
29
29
  }
30
30
 
31
31
  export { Toast as default };
@@ -53,11 +53,11 @@ function ToastViewportItem({ toast, position, toastClassName, onDismiss, }) {
53
53
  window.clearTimeout(timeoutId);
54
54
  };
55
55
  }, [onDismiss, toast.durationMs, toast.id]);
56
- return (jsx("div", { className: clsx('pointer-events-auto flex w-full', {
56
+ return (jsx("div", { className: clsx('pointer-events-none flex w-full', {
57
57
  'justify-start': position === 'top-left' || position === 'bottom-left',
58
58
  'justify-center': position === 'top-center' || position === 'bottom-center',
59
59
  'justify-end': position === 'top-right' || position === 'bottom-right',
60
- }), children: jsx(Toast, { title: toast.title, description: toast.description, type: toast.type, className: clsx(toastClassName, toast.className) }) }));
60
+ }), children: jsx("div", { className: "pointer-events-auto", children: jsx(Toast, { title: toast.title, description: toast.description, type: toast.type, className: clsx(toastClassName, toast.className), fullWidth: toast.fullWidth, closable: toast.closable, onClose: () => onDismiss(toast.id) }) }) }));
61
61
  }
62
62
  function showToast(options) {
63
63
  const toastId = options.id ?? nextToastId();
@@ -88,13 +88,15 @@ function ToastProvider({ children, defaultDurationMs = 2500, maxToasts = 5, view
88
88
  const clearToastsInternal = useCallback(() => {
89
89
  setToasts([]);
90
90
  }, []);
91
- const showToastInternal = useCallback(({ id, type = 'default', position = 'top-center', durationMs = defaultDurationMs, ...toastOptions }) => {
91
+ const showToastInternal = useCallback(({ id, type = 'default', position = 'top-center', durationMs = defaultDurationMs, fullWidth = false, closable = false, ...toastOptions }) => {
92
92
  const toastId = id ?? nextToastId();
93
93
  const nextToast = {
94
94
  id: toastId,
95
95
  type,
96
96
  position,
97
97
  durationMs,
98
+ fullWidth,
99
+ closable,
98
100
  ...toastOptions,
99
101
  };
100
102
  setToasts((currentToasts) => {
@@ -117,7 +119,7 @@ function ToastProvider({ children, defaultDurationMs = 2500, maxToasts = 5, view
117
119
  const positionedToasts = toasts.filter((toast) => toast.position === position);
118
120
  if (positionedToasts.length === 0)
119
121
  return null;
120
- return (jsx("div", { "aria-live": "polite", "aria-atomic": "false", "data-toast-position": position, "data-toast-part": "viewport", className: clsx('pointer-events-none fixed z-[1100] flex w-[calc(100%-2rem)] max-w-sm flex-col gap-3', VIEWPORT_POSITION_CLASSES[position], viewportClassName), children: positionedToasts.map((toast) => (jsx(ToastViewportItem, { toast: toast, position: position, toastClassName: toastClassName, onDismiss: dismissToastInternal }, toast.id))) }, position));
122
+ return (jsx("div", { "aria-live": "polite", "aria-atomic": "false", "data-toast-position": position, "data-toast-part": "viewport", className: clsx('pointer-events-none fixed z-[1100] flex w-[calc(100%-2rem)] max-w-[1400px] flex-col gap-3', VIEWPORT_POSITION_CLASSES[position], viewportClassName), children: positionedToasts.map((toast) => (jsx(ToastViewportItem, { toast: toast, position: position, toastClassName: toastClassName, onDismiss: dismissToastInternal }, toast.id))) }, position));
121
123
  }) }), document.body)
122
124
  : null] }));
123
125
  }
@@ -16,10 +16,10 @@ function WizardBody({ children, className }) {
16
16
  function WizardFooter({ children, className }) {
17
17
  return jsx("footer", { className: clsx('shrink-0', className), children: children });
18
18
  }
19
- function WizardActions({ primaryAction, secondaryAction, tertiaryAction, className, actionsClassName, }) {
20
- if (!primaryAction && !secondaryAction && !tertiaryAction)
19
+ function WizardActions({ primaryAction, secondaryAction, className }) {
20
+ if (!primaryAction && !secondaryAction)
21
21
  return null;
22
- return (jsxs("div", { className: clsx('flex w-full min-w-0 items-center justify-between gap-4', className), children: [jsx("div", { className: "min-w-0 shrink-0", children: tertiaryAction }), jsxs("div", { className: clsx('flex min-w-0 items-center gap-4', actionsClassName), children: [secondaryAction ? jsx("div", { className: "shrink-0", children: secondaryAction }) : null, primaryAction ? jsx("div", { className: "shrink-0", children: primaryAction }) : null] })] }));
22
+ return (jsxs("div", { className: clsx('flex flex-col gap-2 sm:flex-row items-center justify-between', className), children: [secondaryAction, primaryAction] }));
23
23
  }
24
24
 
25
25
  export { WizardActions, WizardBody, WizardFooter, WizardHeader, WizardLayout };
@@ -1,80 +1,200 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { useEffect } from 'react';
4
4
  import { DayPicker, formatCaption } from 'react-day-picker';
5
5
 
6
- const startOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
7
- const getTargetMonth = (range) => {
8
- if (range?.from)
9
- return startOfMonth(range.from);
10
- if (range?.to)
11
- return startOfMonth(range.to);
6
+ const startOfMonth = (date) => new Date(date.getFullYear(), date.getMonth(), 1);
7
+ const isSameDay = (left, right) => !!left &&
8
+ !!right &&
9
+ left.getFullYear() === right.getFullYear() &&
10
+ left.getMonth() === right.getMonth() &&
11
+ left.getDate() === right.getDate();
12
+ const isSingleProps = (props) => props.selectionMode === 'single';
13
+ const isRangeProps = (props) => props.selectionMode === 'range';
14
+ const getTargetMonth = (value) => {
15
+ if (!value)
16
+ return startOfMonth(new Date());
17
+ if (value instanceof Date)
18
+ return startOfMonth(value);
19
+ if (value?.from)
20
+ return startOfMonth(value.from);
21
+ if (value?.to)
22
+ return startOfMonth(value.to);
12
23
  return startOfMonth(new Date());
13
24
  };
14
- function RangeCalendar({ label, value, onChange, onCommit, weekStartsOn = 1, className, required = false, locale, language = 'en', weekdayLabels, }) {
25
+ function RangeCalendar(props) {
26
+ const { label, weekStartsOn = 1, className, required = false, locale, language = 'en', weekdayLabels, displayMode = 'inline', placeholder = 'Seleccionar', closeOnCommit = true, } = props;
15
27
  const minDate = React.useMemo(() => {
16
- const d = new Date();
17
- d.setHours(0, 0, 0, 0);
18
- return d;
28
+ const date = new Date();
29
+ date.setHours(0, 0, 0, 0);
30
+ return date;
19
31
  }, []);
20
32
  const maxDate = React.useMemo(() => {
21
- const d = new Date(minDate);
22
- d.setFullYear(d.getFullYear() + 2);
23
- return d;
33
+ const date = new Date(minDate);
34
+ date.setFullYear(date.getFullYear() + 2);
35
+ return date;
24
36
  }, [minDate]);
25
37
  const startMonthLimit = React.useMemo(() => startOfMonth(minDate), [minDate]);
26
38
  const endMonthLimit = React.useMemo(() => startOfMonth(maxDate), [maxDate]);
27
- const [month, setMonth] = React.useState(() => getTargetMonth(value));
39
+ const [month, setMonth] = React.useState(() => getTargetMonth(props.value));
40
+ const [isOpen, setIsOpen] = React.useState(false);
41
+ const rootRef = React.useRef(null);
42
+ const skipNextSingleSelectRef = React.useRef(false);
28
43
  useEffect(() => {
29
- const next = getTargetMonth(value);
44
+ const next = getTargetMonth(props.value);
30
45
  setMonth((prev) => {
31
46
  if (prev.getFullYear() === next.getFullYear() && prev.getMonth() === next.getMonth())
32
47
  return prev;
33
48
  return next;
34
49
  });
35
- }, [value?.from?.getTime(), value?.to?.getTime()]);
36
- const handleSelect = React.useCallback((next) => {
37
- onChange(next);
50
+ }, [props.value]);
51
+ useEffect(() => {
52
+ if (displayMode !== 'dropdown' || !isOpen)
53
+ return;
54
+ const handlePointerDown = (event) => {
55
+ const target = event.target;
56
+ if (!target)
57
+ return;
58
+ if (rootRef.current?.contains(target))
59
+ return;
60
+ setIsOpen(false);
61
+ };
62
+ document.addEventListener('mousedown', handlePointerDown);
63
+ document.addEventListener('touchstart', handlePointerDown);
64
+ return () => {
65
+ document.removeEventListener('mousedown', handlePointerDown);
66
+ document.removeEventListener('touchstart', handlePointerDown);
67
+ };
68
+ }, [displayMode, isOpen]);
69
+ const triggerLabel = React.useMemo(() => {
70
+ const formatter = new Intl.DateTimeFormat(language, {
71
+ day: '2-digit',
72
+ month: '2-digit',
73
+ year: 'numeric',
74
+ });
75
+ if (isSingleProps(props)) {
76
+ return props.value ? formatter.format(props.value) : placeholder;
77
+ }
78
+ const rangeValue = props.value;
79
+ if (!rangeValue?.from && !rangeValue?.to)
80
+ return placeholder;
81
+ if (rangeValue?.from && rangeValue?.to)
82
+ return `${formatter.format(rangeValue.from)} - ${formatter.format(rangeValue.to)}`;
83
+ if (rangeValue?.from)
84
+ return formatter.format(rangeValue.from);
85
+ if (rangeValue?.to)
86
+ return formatter.format(rangeValue.to);
87
+ return placeholder;
88
+ }, [language, placeholder, props]);
89
+ const sharedDayPickerProps = {
90
+ navLayout: 'around',
91
+ weekStartsOn,
92
+ month,
93
+ onMonthChange: setMonth,
94
+ locale,
95
+ startMonth: startMonthLimit,
96
+ endMonth: endMonthLimit,
97
+ disabled: [{ before: minDate }, { after: maxDate }],
98
+ formatters: {
99
+ formatWeekdayName: (date) => weekdayLabels?.[date.getDay()] ?? date.toLocaleDateString(language, { weekday: 'short' }),
100
+ formatCaption: (date, options, dateLib) => {
101
+ const text = formatCaption(date, options, dateLib);
102
+ return text ? text[0].toLocaleUpperCase(language) + text.slice(1) : text;
103
+ },
104
+ },
105
+ className: 'w-full p-2',
106
+ classNames: {
107
+ chevron: 'rdp-chevron fill-[var(--color-primary-black)]',
108
+ month_caption: 'rdp-month_caption text-sm font-semibold',
109
+ caption_label: 'rdp-caption_label text-sm font-semibold',
110
+ },
111
+ styles: {
112
+ root: { width: '100%' },
113
+ months: { width: '100%' },
114
+ month: { width: '100%' },
115
+ month_grid: { width: '100%', tableLayout: 'fixed' },
116
+ },
117
+ style: {
118
+ '--rdp-accent-color': 'var(--color-primary-purple)',
119
+ '--rdp-accent-background-color': 'var(--color-secondary-offwhite)',
120
+ },
121
+ };
122
+ const handleRangeSelect = React.useCallback((next) => {
123
+ if (!isRangeProps(props))
124
+ return;
125
+ const current = props.value;
126
+ const isClearingSameSingleAnchor = !!current?.from && !current?.to && !!next?.from && !next?.to && current.from.getTime() === next.from.getTime();
127
+ const isClearingFromCompletedRange = !!current?.from &&
128
+ !!current?.to &&
129
+ !!next?.from &&
130
+ !next?.to &&
131
+ (current.from.getTime() === next.from.getTime() || current.to.getTime() === next.from.getTime());
132
+ if (isClearingSameSingleAnchor || isClearingFromCompletedRange) {
133
+ props.onChange(undefined);
134
+ return;
135
+ }
136
+ props.onChange(next);
137
+ const target = getTargetMonth(next);
138
+ if (month.getFullYear() !== target.getFullYear() || month.getMonth() !== target.getMonth()) {
139
+ setMonth(target);
140
+ }
141
+ if (next?.from && next?.to) {
142
+ props.onCommit?.(next.from, next.to);
143
+ if (displayMode === 'dropdown' && closeOnCommit)
144
+ setIsOpen(false);
145
+ }
146
+ }, [closeOnCommit, displayMode, month, props]);
147
+ const handleSingleSelect = React.useCallback((next) => {
148
+ if (!isSingleProps(props))
149
+ return;
150
+ if (skipNextSingleSelectRef.current) {
151
+ skipNextSingleSelectRef.current = false;
152
+ return;
153
+ }
154
+ if (next && props.value && next.getTime() === props.value.getTime()) {
155
+ props.onChange(undefined);
156
+ return;
157
+ }
158
+ props.onChange(next);
38
159
  const target = getTargetMonth(next);
39
160
  if (month.getFullYear() !== target.getFullYear() || month.getMonth() !== target.getMonth()) {
40
161
  setMonth(target);
41
162
  }
42
- if (next?.from && next?.to)
43
- onCommit?.(next.from, next.to);
44
- }, [onChange, onCommit, month]);
45
- return (jsxs("div", { className: `${className ?? ''} flex flex-col w-full lg:max-w-[350px]`, children: [label ? (jsxs("div", { className: "mb-2 text-sm font-semibold", children: [label, required ? (jsx("span", { className: "text-red-500 ml-1", "aria-hidden": "true", children: "*" })) : null] })) : null, jsx("div", { className: "w-full bg-(--color-secondary-white) rounded-2xl border border-(--color-secondary-outline) overflow-hidden", children: jsx(DayPicker, { mode: "range", navLayout: "around", weekStartsOn: weekStartsOn, month: month, onMonthChange: setMonth, selected: value, onSelect: handleSelect, resetOnSelect: true, numberOfMonths: 1, locale: locale, startMonth: startMonthLimit, endMonth: endMonthLimit, disabled: [{ before: minDate }, { after: maxDate }], formatters: {
46
- formatWeekdayName: (date) => weekdayLabels?.[date.getDay()] ?? date.toLocaleDateString(language, { weekday: 'short' }),
47
- formatCaption: (date, options, dateLib) => {
48
- const s = formatCaption(date, options, dateLib);
49
- return s ? s[0].toLocaleUpperCase(language) + s.slice(1) : s;
50
- },
51
- }, className: "w-full p-2", classNames: {
52
- chevron: 'rdp-chevron fill-[var(--color-primary-black)]',
53
- month_caption: 'rdp-month_caption text-sm font-semibold',
54
- caption_label: 'rdp-caption_label text-sm font-semibold',
55
- }, styles: {
56
- root: { width: '100%' },
57
- months: { width: '100%' },
58
- month: { width: '100%' },
59
- month_grid: { width: '100%', tableLayout: 'fixed' },
60
- }, style: {
61
- '--rdp-accent-color': 'var(--color-primary-purple)',
62
- '--rdp-accent-background-color': 'var(--color-secondary-offwhite)',
63
- } }) })] }));
163
+ if (next) {
164
+ props.onCommit?.(next);
165
+ if (displayMode === 'dropdown' && closeOnCommit)
166
+ setIsOpen(false);
167
+ }
168
+ }, [closeOnCommit, displayMode, month, props]);
169
+ const calendar = (jsx("div", { className: "w-full overflow-hidden rounded-2xl border border-(--color-secondary-outline) bg-(--color-secondary-white)", children: isSingleProps(props) ? (jsx(DayPicker, { ...sharedDayPickerProps, mode: "single", selected: props.value, onSelect: handleSingleSelect, onDayClick: (day) => {
170
+ if (isSameDay(day, props.value)) {
171
+ skipNextSingleSelectRef.current = true;
172
+ props.onChange(undefined);
173
+ if (displayMode === 'dropdown' && closeOnCommit)
174
+ setIsOpen(false);
175
+ }
176
+ }, numberOfMonths: 1 })) : (jsx(DayPicker, { ...sharedDayPickerProps, mode: "range", selected: props.value, onSelect: handleRangeSelect, resetOnSelect: true, numberOfMonths: 1 })) }));
177
+ return (jsxs("div", { ref: rootRef, className: `${className ?? ''} flex w-full flex-col lg:max-w-[350px]`, children: [label ? (jsxs("div", { className: "mb-2 text-sm font-semibold", children: [label, required ? (jsx("span", { className: "ml-1 text-red-500", "aria-hidden": "true", children: "*" })) : null] })) : null, displayMode === 'dropdown' ? (jsxs("div", { className: "relative", children: [jsxs("button", { type: "button", onClick: () => setIsOpen((prev) => !prev), className: `relative h-12 w-full rounded-xl border border-(--color-secondary-outline) px-5 pr-10 text-left text-base transition-colors duration-100 ease-in-out focus:border-(--color-primary-purple) focus:outline-none focus:ring-0 ${isSingleProps(props)
178
+ ? !props.value
179
+ ? 'text-(--color-secondary-grey)'
180
+ : 'text-(--color-primary-black)'
181
+ : !props.value?.from && !props.value?.to
182
+ ? 'text-(--color-secondary-grey)'
183
+ : 'text-(--color-primary-black)'}`, "aria-expanded": isOpen, children: [triggerLabel, jsx("svg", { className: "pointer-events-none absolute right-4 top-1/2 h-5 w-5 -translate-y-1/2", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: jsx("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round" }) })] }), isOpen ? jsx("div", { className: "absolute left-0 right-0 top-[calc(100%+12px)] z-20", children: calendar }) : null] })) : (calendar)] }));
64
184
  }
65
- const toLocalISO = (d) => {
66
- const y = d.getFullYear();
67
- const m = String(d.getMonth() + 1).padStart(2, '0');
68
- const day = String(d.getDate()).padStart(2, '0');
69
- return `${y}-${m}-${day}`;
185
+ const toLocalISO = (date) => {
186
+ const year = date.getFullYear();
187
+ const month = String(date.getMonth() + 1).padStart(2, '0');
188
+ const day = String(date.getDate()).padStart(2, '0');
189
+ return `${year}-${month}-${day}`;
70
190
  };
71
191
  const parseLocalISODate = (iso) => {
72
192
  if (!iso)
73
193
  return undefined;
74
- const [y, m, d] = iso.split('-').map(Number);
75
- if (!y || !m || !d)
194
+ const [year, month, day] = iso.split('-').map(Number);
195
+ if (!year || !month || !day)
76
196
  return undefined;
77
- return new Date(y, m - 1, d);
197
+ return new Date(year, month - 1, day);
78
198
  };
79
199
 
80
200
  export { RangeCalendar as default, parseLocalISODate, toLocalISO };
@@ -3,11 +3,11 @@ import { useChromeBoxHeights } from '../../../hooks/useChromeBoxHeights.js';
3
3
  import { useMedia, LG_SCREEN_SIZE } from '../../../hooks/useMedia.js';
4
4
  import SectionCard from '../SectionCard/SectionCard.js';
5
5
 
6
- function MasterDetailShell({ menu, content, contentHeader, contentActions, menuContentRef, desktopPaneHeight, }) {
6
+ function MasterDetailShell({ menuHeader, menuContent, menuFooter, content, contentHeader, contentActions, menuContentRef, desktopPaneHeight, }) {
7
7
  const isDesktop = useMedia(LG_SCREEN_SIZE);
8
8
  const { header, footer } = useChromeBoxHeights();
9
9
  const desktopViewportHeight = desktopPaneHeight ?? `calc(var(--app-vh, 1vh) * 100 - ${header + footer}px)`;
10
- return (jsx("section", { className: "w-full h-full min-h-0 bg-transparent", children: jsx("div", { className: "flex h-full min-h-0 w-full flex-col", children: jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-4 lg:flex-row lg:items-stretch", style: isDesktop ? { height: desktopViewportHeight } : undefined, children: [jsx("aside", { className: "flex min-h-0 flex-col overflow-hidden rounded-none border-0 bg-transparent lg:w-[365px]", children: jsx("div", { ref: menuContentRef, className: "scrollbar-hide min-h-0 flex-1 overflow-y-auto", children: menu }) }), jsx(SectionCard, { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", withContentWrapper: false, children: jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: jsxs("div", { className: "flex min-h-full flex-col", children: [(contentHeader || contentActions) && (jsxs("header", { className: "sticky top-0 z-10 flex items-center justify-between gap-4 border-b border-(--color-secondary-outline) bg-(--color-primary-white) px-6 py-5", children: [contentHeader ? jsx("div", { className: "min-w-0", children: contentHeader }) : jsx("div", {}), contentActions ? jsx("div", { className: "shrink-0", children: contentActions }) : null] })), jsx("div", { className: "flex-1 p-6", children: content })] }) }) })] }) }) }));
10
+ return (jsx("section", { className: "w-full h-full min-h-0 bg-transparent", children: jsx("div", { className: "flex h-full min-h-0 w-full flex-col", children: jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-4 lg:flex-row lg:items-stretch", style: isDesktop ? { height: desktopViewportHeight } : undefined, children: [jsxs("aside", { className: "flex min-h-0 flex-col overflow-hidden rounded-none border-0 bg-transparent lg:w-[365px]", children: [menuHeader ? jsx("div", { className: "shrink-0", children: menuHeader }) : null, jsx("div", { ref: menuContentRef, className: "min-h-0 flex-1 overflow-y-auto", children: menuContent }), menuFooter ? jsx("div", { className: "shrink-0 pt-4", children: menuFooter }) : null] }), jsx(SectionCard, { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", withContentWrapper: false, children: jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: jsxs("div", { className: "flex min-h-full flex-col", children: [(contentHeader || contentActions) && (jsxs("header", { className: "sticky top-0 z-10 flex items-center justify-between gap-4 border-b border-(--color-secondary-outline) bg-(--color-primary-white) px-6 py-5", children: [contentHeader ? jsx("div", { className: "min-w-0", children: contentHeader }) : jsx("div", {}), contentActions ? jsx("div", { className: "shrink-0", children: contentActions }) : null] })), jsx("div", { className: "flex-1 p-6", children: content })] }) }) })] }) }) }));
11
11
  }
12
12
 
13
13
  export { MasterDetailShell as default };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ImgHTMLAttributes, ReactNode, Ref, ComponentPropsWithoutRef, ButtonHTMLAttributes, CSSProperties, HTMLAttributes, TextareaHTMLAttributes } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { DateRange, DayPicker } from 'react-day-picker';
4
+ import { DayPicker, DateRange } from 'react-day-picker';
5
5
 
6
6
  type PillKeyBase = string;
7
7
  type CountGetters<K extends PillKeyBase, D> = Partial<Record<K, (data: D) => number | undefined>>;
@@ -252,14 +252,16 @@ type DashboardShellContextValue = {
252
252
  declare function useDashboardShell(): DashboardShellContextValue;
253
253
 
254
254
  type MasterDetailShellProps = {
255
- menu: ReactNode;
255
+ menuHeader?: ReactNode;
256
+ menuContent: ReactNode;
257
+ menuFooter?: ReactNode;
256
258
  content: ReactNode;
257
259
  contentHeader?: ReactNode;
258
260
  contentActions?: ReactNode;
259
261
  menuContentRef?: Ref<HTMLDivElement>;
260
262
  desktopPaneHeight?: string;
261
263
  };
262
- declare function MasterDetailShell({ menu, content, contentHeader, contentActions, menuContentRef, desktopPaneHeight, }: MasterDetailShellProps): react_jsx_runtime.JSX.Element;
264
+ declare function MasterDetailShell({ menuHeader, menuContent, menuFooter, content, contentHeader, contentActions, menuContentRef, desktopPaneHeight, }: MasterDetailShellProps): react_jsx_runtime.JSX.Element;
263
265
 
264
266
  type MobileBottomBarProps = ComponentPropsWithoutRef<'div'> & {
265
267
  children: ReactNode;
@@ -462,6 +464,8 @@ type ShowToastOptions = ToastContent & {
462
464
  position?: ToastPosition;
463
465
  durationMs?: number;
464
466
  className?: string;
467
+ fullWidth?: boolean;
468
+ closable?: boolean;
465
469
  };
466
470
  type ToastRecord = ToastContent & {
467
471
  id: string;
@@ -469,6 +473,8 @@ type ToastRecord = ToastContent & {
469
473
  position: ToastPosition;
470
474
  durationMs: number;
471
475
  className?: string;
476
+ fullWidth: boolean;
477
+ closable: boolean;
472
478
  };
473
479
  type ToastContextValue = {
474
480
  showToast: (options: ShowToastOptions) => string;
@@ -483,8 +489,11 @@ type ToastProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
483
489
  titleClassName?: string;
484
490
  descriptionClassName?: string;
485
491
  iconClassName?: string;
492
+ fullWidth?: boolean;
493
+ closable?: boolean;
494
+ onClose?: () => void;
486
495
  };
487
- declare function Toast({ title, description, type, className, titleClassName, descriptionClassName, iconClassName, role, ...rest }: ToastProps): react_jsx_runtime.JSX.Element;
496
+ declare function Toast({ title, description, type, className, titleClassName, descriptionClassName, iconClassName, fullWidth, closable, onClose, role, ...rest }: ToastProps): react_jsx_runtime.JSX.Element;
488
497
 
489
498
  type ToastProviderProps = {
490
499
  children: ReactNode;
@@ -702,20 +711,33 @@ type SingleSelectProps = {
702
711
  type MultiSelectDropdownProps<T> = BaseProps<T> & (MultipleSelectProps | SingleSelectProps);
703
712
  declare function MultiSelectDropdown<T>({ title, options, getId, getLabel, maxPanelHeight, className, error, forwardScrollToRef, required, hideSelectAll, disableCloseOnClickOutside, selectAllLabel, selectionsLabel, ...rest }: MultiSelectDropdownProps<T>): react_jsx_runtime.JSX.Element;
704
713
 
705
- type RangeCalendarProps = {
714
+ type SharedProps = {
706
715
  label?: string;
707
- value: DateRange | undefined;
708
- onChange: (next: DateRange | undefined) => void;
709
- onCommit?: (from: Date, to: Date) => void;
710
716
  weekStartsOn?: 0 | 1;
711
717
  className?: string;
712
718
  required?: boolean;
713
719
  locale?: React$1.ComponentProps<typeof DayPicker>['locale'];
714
720
  language?: string;
715
721
  weekdayLabels?: string[];
722
+ displayMode?: 'inline' | 'dropdown';
723
+ placeholder?: string;
724
+ closeOnCommit?: boolean;
725
+ };
726
+ type SingleProps = SharedProps & {
727
+ selectionMode: 'single';
728
+ value: Date | undefined;
729
+ onChange: (next: Date | undefined) => void;
730
+ onCommit?: (date: Date) => void;
731
+ };
732
+ type RangeProps = SharedProps & {
733
+ selectionMode: 'range';
734
+ value: DateRange | undefined;
735
+ onChange: (next: DateRange | undefined) => void;
736
+ onCommit?: (from: Date, to: Date) => void;
716
737
  };
717
- declare function RangeCalendar({ label, value, onChange, onCommit, weekStartsOn, className, required, locale, language, weekdayLabels, }: RangeCalendarProps): react_jsx_runtime.JSX.Element;
718
- declare const toLocalISO: (d: Date) => string;
738
+ type RangeCalendarProps = SingleProps | RangeProps;
739
+ declare function RangeCalendar(props: RangeCalendarProps): react_jsx_runtime.JSX.Element;
740
+ declare const toLocalISO: (date: Date) => string;
719
741
  declare const parseLocalISODate: (iso?: string | null) => Date | undefined;
720
742
 
721
743
  type LooseChangeHandler = React.ChangeEventHandler<HTMLInputElement> | React.ChangeEventHandler<HTMLTextAreaElement>;
@@ -954,7 +976,7 @@ type WizardActionsProps = {
954
976
  className?: string;
955
977
  actionsClassName?: string;
956
978
  };
957
- declare function WizardActions({ primaryAction, secondaryAction, tertiaryAction, className, actionsClassName, }: WizardActionsProps): react_jsx_runtime.JSX.Element | null;
979
+ declare function WizardActions({ primaryAction, secondaryAction, className }: WizardActionsProps): react_jsx_runtime.JSX.Element | null;
958
980
 
959
981
  export { BooleanRadioGroup, Button, ButtonRow, CheckboxField, ChevronLeft, ChevronRight, ChevronUpDown, ChoiceChip, CurrencyInput, DashboardLoadingLabel, DashboardSection$1 as DashboardSection, DashboardShell, DataGrid, DetailsView, DocumentScrollLayoutShell, EmptyLayoutShell, FilterSection, FormCurrencyField, FormInputField, FormPasswordField, FormSelectField, FullscreenCenter, GoogleButton, HilighterSvg, Icon, IconViewSwitcher, ImageCarousel, InfoCarousel, InlineList, Input, LG_SCREEN_SIZE, Label, Logo, MasterDetailShell, MobileBottomBar, Modal, MultiRadioGroupField, MultiSelectDropdown, NavbarDropdown, NoNavigationLayoutShell, OverflowMenu, PageLoading, PasswordInput, PhotoZoomOverlay, Pills, RadioGroupField, RangeCalendar, ScrollToTop, SearchInput, SearchWithSuggestions, SectionCard, Select, Separator, Skeleton, Spinner, StatusChip, TagChip, TextDropdownTrigger, TextareaField, Toast, ToastProvider, Tooltip, UniversalVideoPlayer, UploadTile, VideoPreviewCard, Wizard, WizardActions, WizardBody, WizardFooter, WizardHeader, WizardLayout, WizardStep, XL_SCREEN_SIZE, clearToasts, dismissToast, parseLocalISODate, showToast, toLocalISO, useCarouselPills, useChromeBoxHeights, useCommittedNullableBooleanValue, useDashboardShell, useDebouncedValue, useMedia, usePendingAction, useScrollExitOnEdge, useToast, useViewportVhVar };
960
982
  export type { BooleanRadioGroupProps, ChoiceChipProps, CountGetters, DashboardSection as DashboardShellSection, DataGridActions, DataGridColumn, DataGridPagination, DataGridSelection, IconName, IconVariant, InlineListItem, MasterDetailShellProps, MenuItem, MultiSelectDropdownProps, OverflowMenuAlign, OverflowMenuItem, OverflowMenuProps, OverflowMenuSide, PillItem, PillKeyBase, RadioOption, RangeCalendarProps, ShowToastOptions, StatusChipProps, TagChipProps, TextareaFieldProps, ToastContent, ToastContextValue, ToastPosition, ToastProps, ToastRecord, ToastType, TooltipPosition, TooltipProps, UniversalVideoPlayerProps, VideoProvider, WizardStepProps };