@mieweb/ui 0.6.0 → 0.6.1-dev.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +68 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -2
- package/dist/index.d.ts +39 -2
- package/dist/index.js +68 -17
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1760,6 +1760,28 @@ interface CommandPaletteProps {
|
|
|
1760
1760
|
isLoading?: boolean;
|
|
1761
1761
|
/** Called when an item is selected */
|
|
1762
1762
|
onSelect?: (item: CommandPaletteItem) => void;
|
|
1763
|
+
/**
|
|
1764
|
+
* Fires whenever the search query changes. Consumers should debounce
|
|
1765
|
+
* inside this callback if they're hitting a network. Provider's `items`
|
|
1766
|
+
* is still the source of truth for what renders.
|
|
1767
|
+
*/
|
|
1768
|
+
onQueryChange?: (query: string) => void;
|
|
1769
|
+
/**
|
|
1770
|
+
* Items always shown at the top, regardless of query. Use for smart
|
|
1771
|
+
* actions ("Call John", "Ask AI: …") or other affordances that should
|
|
1772
|
+
* remain reachable while typing. Filtered out when a category filter
|
|
1773
|
+
* is active so the category view stays scoped.
|
|
1774
|
+
*/
|
|
1775
|
+
pinnedItems?: CommandPaletteItem[];
|
|
1776
|
+
/** Group label rendered above pinned items. Defaults to "Actions". */
|
|
1777
|
+
pinnedCategoryLabel?: string;
|
|
1778
|
+
/**
|
|
1779
|
+
* Items shown only when the query is empty and there are no provider
|
|
1780
|
+
* items to display. Use for recent searches / recently opened records.
|
|
1781
|
+
*/
|
|
1782
|
+
recentItems?: CommandPaletteItem[];
|
|
1783
|
+
/** Group label rendered above recent items. Defaults to "Recent". */
|
|
1784
|
+
recentCategoryLabel?: string;
|
|
1763
1785
|
/** Custom empty state content */
|
|
1764
1786
|
emptyState?: React__default.ReactNode;
|
|
1765
1787
|
/** Custom render function for items */
|
|
@@ -1773,8 +1795,14 @@ interface CommandPaletteProps {
|
|
|
1773
1795
|
className?: string;
|
|
1774
1796
|
/** Test ID for testing */
|
|
1775
1797
|
'data-testid'?: string;
|
|
1798
|
+
/**
|
|
1799
|
+
* Skip the built-in client-side query filter. Use when `items` are
|
|
1800
|
+
* already filtered server-side (e.g. semantic search) and labels
|
|
1801
|
+
* won't necessarily contain the query as a substring.
|
|
1802
|
+
*/
|
|
1803
|
+
serverFiltered?: boolean;
|
|
1776
1804
|
}
|
|
1777
|
-
declare function CommandPalette({ placeholder, isLoading, onSelect, emptyState, renderItem, footer, className, 'data-testid': testId, }: CommandPaletteProps): React__default.JSX.Element | null;
|
|
1805
|
+
declare function CommandPalette({ placeholder, isLoading, onSelect, onQueryChange, pinnedItems, pinnedCategoryLabel, recentItems, recentCategoryLabel, emptyState, renderItem, footer, className, 'data-testid': testId, serverFiltered, }: CommandPaletteProps): React__default.JSX.Element | null;
|
|
1778
1806
|
interface CommandPaletteTriggerProps {
|
|
1779
1807
|
/** Button content (default shows search icon and keyboard hint) */
|
|
1780
1808
|
children?: React__default.ReactNode;
|
|
@@ -2410,6 +2438,15 @@ interface DateRangePickerProps {
|
|
|
2410
2438
|
placeholder?: string;
|
|
2411
2439
|
/** Custom className */
|
|
2412
2440
|
className?: string;
|
|
2441
|
+
/**
|
|
2442
|
+
* Horizontal alignment of the desktop popup relative to the trigger.
|
|
2443
|
+
* - `'start'` (default historical behavior): popup left edge aligns with trigger left edge.
|
|
2444
|
+
* - `'end'`: popup right edge aligns with trigger right edge.
|
|
2445
|
+
* - `'auto'`: starts as `'start'`, then automatically flips to `'end'` if the popup
|
|
2446
|
+
* would overflow the right edge of the viewport. Recommended for triggers placed
|
|
2447
|
+
* in the right side of a layout (e.g. page header action slots).
|
|
2448
|
+
*/
|
|
2449
|
+
align?: 'start' | 'end' | 'auto';
|
|
2413
2450
|
/** Whether to show the preset sidebar in the calendar popup (default: true) */
|
|
2414
2451
|
showPresets?: boolean;
|
|
2415
2452
|
/** Display variant: desktop (default), mobile (bottom sheet), or responsive (auto-adapts at md breakpoint) */
|
|
@@ -2471,7 +2508,7 @@ declare function calculateDateRange(presetKey: string): DateRange$1;
|
|
|
2471
2508
|
* />
|
|
2472
2509
|
* ```
|
|
2473
2510
|
*/
|
|
2474
|
-
declare function DateRangePicker({ value, onChange, presets, activePreset, placeholder, className, showPresets, variant, labels, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
|
|
2511
|
+
declare function DateRangePicker({ value, onChange, presets, activePreset, placeholder, className, align, showPresets, variant, labels, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
|
|
2475
2512
|
interface DateRangeFilterProps {
|
|
2476
2513
|
/** Current date range value */
|
|
2477
2514
|
value?: DateRange$1;
|
package/dist/index.d.ts
CHANGED
|
@@ -1760,6 +1760,28 @@ interface CommandPaletteProps {
|
|
|
1760
1760
|
isLoading?: boolean;
|
|
1761
1761
|
/** Called when an item is selected */
|
|
1762
1762
|
onSelect?: (item: CommandPaletteItem) => void;
|
|
1763
|
+
/**
|
|
1764
|
+
* Fires whenever the search query changes. Consumers should debounce
|
|
1765
|
+
* inside this callback if they're hitting a network. Provider's `items`
|
|
1766
|
+
* is still the source of truth for what renders.
|
|
1767
|
+
*/
|
|
1768
|
+
onQueryChange?: (query: string) => void;
|
|
1769
|
+
/**
|
|
1770
|
+
* Items always shown at the top, regardless of query. Use for smart
|
|
1771
|
+
* actions ("Call John", "Ask AI: …") or other affordances that should
|
|
1772
|
+
* remain reachable while typing. Filtered out when a category filter
|
|
1773
|
+
* is active so the category view stays scoped.
|
|
1774
|
+
*/
|
|
1775
|
+
pinnedItems?: CommandPaletteItem[];
|
|
1776
|
+
/** Group label rendered above pinned items. Defaults to "Actions". */
|
|
1777
|
+
pinnedCategoryLabel?: string;
|
|
1778
|
+
/**
|
|
1779
|
+
* Items shown only when the query is empty and there are no provider
|
|
1780
|
+
* items to display. Use for recent searches / recently opened records.
|
|
1781
|
+
*/
|
|
1782
|
+
recentItems?: CommandPaletteItem[];
|
|
1783
|
+
/** Group label rendered above recent items. Defaults to "Recent". */
|
|
1784
|
+
recentCategoryLabel?: string;
|
|
1763
1785
|
/** Custom empty state content */
|
|
1764
1786
|
emptyState?: React__default.ReactNode;
|
|
1765
1787
|
/** Custom render function for items */
|
|
@@ -1773,8 +1795,14 @@ interface CommandPaletteProps {
|
|
|
1773
1795
|
className?: string;
|
|
1774
1796
|
/** Test ID for testing */
|
|
1775
1797
|
'data-testid'?: string;
|
|
1798
|
+
/**
|
|
1799
|
+
* Skip the built-in client-side query filter. Use when `items` are
|
|
1800
|
+
* already filtered server-side (e.g. semantic search) and labels
|
|
1801
|
+
* won't necessarily contain the query as a substring.
|
|
1802
|
+
*/
|
|
1803
|
+
serverFiltered?: boolean;
|
|
1776
1804
|
}
|
|
1777
|
-
declare function CommandPalette({ placeholder, isLoading, onSelect, emptyState, renderItem, footer, className, 'data-testid': testId, }: CommandPaletteProps): React__default.JSX.Element | null;
|
|
1805
|
+
declare function CommandPalette({ placeholder, isLoading, onSelect, onQueryChange, pinnedItems, pinnedCategoryLabel, recentItems, recentCategoryLabel, emptyState, renderItem, footer, className, 'data-testid': testId, serverFiltered, }: CommandPaletteProps): React__default.JSX.Element | null;
|
|
1778
1806
|
interface CommandPaletteTriggerProps {
|
|
1779
1807
|
/** Button content (default shows search icon and keyboard hint) */
|
|
1780
1808
|
children?: React__default.ReactNode;
|
|
@@ -2410,6 +2438,15 @@ interface DateRangePickerProps {
|
|
|
2410
2438
|
placeholder?: string;
|
|
2411
2439
|
/** Custom className */
|
|
2412
2440
|
className?: string;
|
|
2441
|
+
/**
|
|
2442
|
+
* Horizontal alignment of the desktop popup relative to the trigger.
|
|
2443
|
+
* - `'start'` (default historical behavior): popup left edge aligns with trigger left edge.
|
|
2444
|
+
* - `'end'`: popup right edge aligns with trigger right edge.
|
|
2445
|
+
* - `'auto'`: starts as `'start'`, then automatically flips to `'end'` if the popup
|
|
2446
|
+
* would overflow the right edge of the viewport. Recommended for triggers placed
|
|
2447
|
+
* in the right side of a layout (e.g. page header action slots).
|
|
2448
|
+
*/
|
|
2449
|
+
align?: 'start' | 'end' | 'auto';
|
|
2413
2450
|
/** Whether to show the preset sidebar in the calendar popup (default: true) */
|
|
2414
2451
|
showPresets?: boolean;
|
|
2415
2452
|
/** Display variant: desktop (default), mobile (bottom sheet), or responsive (auto-adapts at md breakpoint) */
|
|
@@ -2471,7 +2508,7 @@ declare function calculateDateRange(presetKey: string): DateRange$1;
|
|
|
2471
2508
|
* />
|
|
2472
2509
|
* ```
|
|
2473
2510
|
*/
|
|
2474
|
-
declare function DateRangePicker({ value, onChange, presets, activePreset, placeholder, className, showPresets, variant, labels, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
|
|
2511
|
+
declare function DateRangePicker({ value, onChange, presets, activePreset, placeholder, className, align, showPresets, variant, labels, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
|
|
2475
2512
|
interface DateRangeFilterProps {
|
|
2476
2513
|
/** Current date range value */
|
|
2477
2514
|
value?: DateRange$1;
|
package/dist/index.js
CHANGED
|
@@ -3876,7 +3876,7 @@ var MessageBubble = React48.forwardRef(
|
|
|
3876
3876
|
"div",
|
|
3877
3877
|
{
|
|
3878
3878
|
className: cn(
|
|
3879
|
-
"flex flex-1 flex-col
|
|
3879
|
+
"flex min-w-0 flex-1 flex-col",
|
|
3880
3880
|
isOutgoing ? "items-end" : "items-start"
|
|
3881
3881
|
),
|
|
3882
3882
|
children: [
|
|
@@ -8655,11 +8655,17 @@ function CommandPalette({
|
|
|
8655
8655
|
placeholder = "Search...",
|
|
8656
8656
|
isLoading = false,
|
|
8657
8657
|
onSelect,
|
|
8658
|
+
onQueryChange,
|
|
8659
|
+
pinnedItems,
|
|
8660
|
+
pinnedCategoryLabel = "Actions",
|
|
8661
|
+
recentItems,
|
|
8662
|
+
recentCategoryLabel = "Recent",
|
|
8658
8663
|
emptyState,
|
|
8659
8664
|
renderItem,
|
|
8660
8665
|
footer,
|
|
8661
8666
|
className,
|
|
8662
|
-
"data-testid": testId = "command-palette"
|
|
8667
|
+
"data-testid": testId = "command-palette",
|
|
8668
|
+
serverFiltered = false
|
|
8663
8669
|
}) {
|
|
8664
8670
|
const {
|
|
8665
8671
|
isOpen,
|
|
@@ -8676,29 +8682,47 @@ function CommandPalette({
|
|
|
8676
8682
|
const inputRef = useRef(null);
|
|
8677
8683
|
const containerRef = useRef(null);
|
|
8678
8684
|
const listRef = useRef(null);
|
|
8685
|
+
useEffect(() => {
|
|
8686
|
+
if (!isOpen) return;
|
|
8687
|
+
onQueryChange?.(query);
|
|
8688
|
+
}, [query, isOpen, onQueryChange]);
|
|
8689
|
+
const PINNED_CATEGORY_ID = "__palette_pinned__";
|
|
8690
|
+
const RECENT_CATEGORY_ID = "__palette_recent__";
|
|
8679
8691
|
const filteredItems = useMemo(() => {
|
|
8680
8692
|
let result = items;
|
|
8681
8693
|
if (activeCategory) {
|
|
8682
8694
|
result = result.filter((item) => item.category === activeCategory);
|
|
8683
8695
|
}
|
|
8684
|
-
if (query.trim()) {
|
|
8696
|
+
if (query.trim() && !serverFiltered) {
|
|
8685
8697
|
const lowerQuery = query.toLowerCase();
|
|
8686
8698
|
result = result.filter(
|
|
8687
8699
|
(item) => item.label.toLowerCase().includes(lowerQuery) || item.subtitle?.toLowerCase().includes(lowerQuery) || item.description?.toLowerCase().includes(lowerQuery)
|
|
8688
8700
|
);
|
|
8689
8701
|
}
|
|
8690
8702
|
return result;
|
|
8691
|
-
}, [items, query, activeCategory]);
|
|
8703
|
+
}, [items, query, activeCategory, serverFiltered]);
|
|
8704
|
+
const effectiveItems = useMemo(() => {
|
|
8705
|
+
const pinned = !activeCategory && pinnedItems?.length ? pinnedItems.map((it) => ({
|
|
8706
|
+
...it,
|
|
8707
|
+
category: it.category ?? PINNED_CATEGORY_ID
|
|
8708
|
+
})) : [];
|
|
8709
|
+
const showRecents = !activeCategory && !query.trim() && filteredItems.length === 0 && !!recentItems?.length;
|
|
8710
|
+
const recents = showRecents ? recentItems.map((it) => ({
|
|
8711
|
+
...it,
|
|
8712
|
+
category: it.category ?? RECENT_CATEGORY_ID
|
|
8713
|
+
})) : [];
|
|
8714
|
+
return [...pinned, ...filteredItems, ...recents];
|
|
8715
|
+
}, [pinnedItems, recentItems, filteredItems, activeCategory, query]);
|
|
8692
8716
|
const groupedItems = useMemo(() => {
|
|
8693
8717
|
const groups = /* @__PURE__ */ new Map();
|
|
8694
|
-
|
|
8718
|
+
effectiveItems.forEach((item) => {
|
|
8695
8719
|
const category = item.category ?? "Other";
|
|
8696
8720
|
const group = groups.get(category) ?? [];
|
|
8697
8721
|
group.push(item);
|
|
8698
8722
|
groups.set(category, group);
|
|
8699
8723
|
});
|
|
8700
8724
|
return groups;
|
|
8701
|
-
}, [
|
|
8725
|
+
}, [effectiveItems]);
|
|
8702
8726
|
useEscapeKey(close, isOpen);
|
|
8703
8727
|
useClickOutside(containerRef, close);
|
|
8704
8728
|
useEffect(() => {
|
|
@@ -8707,8 +8731,8 @@ function CommandPalette({
|
|
|
8707
8731
|
}
|
|
8708
8732
|
}, [isOpen]);
|
|
8709
8733
|
useEffect(() => {
|
|
8710
|
-
setSelectedIndex(
|
|
8711
|
-
}, [
|
|
8734
|
+
setSelectedIndex(effectiveItems.length > 0 ? 0 : -1);
|
|
8735
|
+
}, [effectiveItems.length, setSelectedIndex]);
|
|
8712
8736
|
useEffect(() => {
|
|
8713
8737
|
if (selectedIndex >= 0 && listRef.current) {
|
|
8714
8738
|
const selectedElement = listRef.current.querySelector(
|
|
@@ -8723,7 +8747,7 @@ function CommandPalette({
|
|
|
8723
8747
|
case "ArrowDown":
|
|
8724
8748
|
e.preventDefault();
|
|
8725
8749
|
setSelectedIndex(
|
|
8726
|
-
Math.min(selectedIndex + 1,
|
|
8750
|
+
Math.min(selectedIndex + 1, effectiveItems.length - 1)
|
|
8727
8751
|
);
|
|
8728
8752
|
break;
|
|
8729
8753
|
case "ArrowUp":
|
|
@@ -8732,8 +8756,8 @@ function CommandPalette({
|
|
|
8732
8756
|
break;
|
|
8733
8757
|
case "Enter":
|
|
8734
8758
|
e.preventDefault();
|
|
8735
|
-
if (selectedIndex >= 0 &&
|
|
8736
|
-
const item =
|
|
8759
|
+
if (selectedIndex >= 0 && effectiveItems[selectedIndex]) {
|
|
8760
|
+
const item = effectiveItems[selectedIndex];
|
|
8737
8761
|
if (!item.disabled) {
|
|
8738
8762
|
onSelect?.(item);
|
|
8739
8763
|
close();
|
|
@@ -8751,7 +8775,7 @@ function CommandPalette({
|
|
|
8751
8775
|
}
|
|
8752
8776
|
},
|
|
8753
8777
|
[
|
|
8754
|
-
|
|
8778
|
+
effectiveItems,
|
|
8755
8779
|
selectedIndex,
|
|
8756
8780
|
setSelectedIndex,
|
|
8757
8781
|
onSelect,
|
|
@@ -8772,9 +8796,15 @@ function CommandPalette({
|
|
|
8772
8796
|
);
|
|
8773
8797
|
const getCategoryInfo = useCallback(
|
|
8774
8798
|
(categoryId) => {
|
|
8799
|
+
if (categoryId === PINNED_CATEGORY_ID) {
|
|
8800
|
+
return { id: PINNED_CATEGORY_ID, label: pinnedCategoryLabel };
|
|
8801
|
+
}
|
|
8802
|
+
if (categoryId === RECENT_CATEGORY_ID) {
|
|
8803
|
+
return { id: RECENT_CATEGORY_ID, label: recentCategoryLabel };
|
|
8804
|
+
}
|
|
8775
8805
|
return categories.find((c) => c.id === categoryId);
|
|
8776
8806
|
},
|
|
8777
|
-
[categories]
|
|
8807
|
+
[categories, pinnedCategoryLabel, recentCategoryLabel]
|
|
8778
8808
|
);
|
|
8779
8809
|
if (!isOpen) return null;
|
|
8780
8810
|
let globalIndex = -1;
|
|
@@ -8880,14 +8910,14 @@ function CommandPalette({
|
|
|
8880
8910
|
ref: listRef,
|
|
8881
8911
|
"data-slot": "command-palette-results",
|
|
8882
8912
|
className: "max-h-[60vh] overflow-y-auto",
|
|
8883
|
-
children:
|
|
8913
|
+
children: effectiveItems.length === 0 ? /* @__PURE__ */ jsx(
|
|
8884
8914
|
"div",
|
|
8885
8915
|
{
|
|
8886
8916
|
"data-slot": "command-palette-empty",
|
|
8887
8917
|
className: "text-muted-foreground p-8 text-center",
|
|
8888
8918
|
children: emptyState ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8889
8919
|
/* @__PURE__ */ jsx("div", { className: "mx-auto mb-2 h-8 w-8 opacity-50", children: /* @__PURE__ */ jsx(SearchIcon2, {}) }),
|
|
8890
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: query.trim() ? `No results for "${query}"` : "Start typing to search..." })
|
|
8920
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: isLoading && query.trim() ? `Searching for "${query}"\u2026` : query.trim() ? `No results for "${query}"` : "Start typing to search..." })
|
|
8891
8921
|
] })
|
|
8892
8922
|
}
|
|
8893
8923
|
) : Array.from(groupedItems.entries()).map(
|
|
@@ -9020,7 +9050,7 @@ function CommandPalette({
|
|
|
9020
9050
|
/* @__PURE__ */ jsx("span", { children: "close" })
|
|
9021
9051
|
] }),
|
|
9022
9052
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
9023
|
-
|
|
9053
|
+
effectiveItems.length,
|
|
9024
9054
|
" results"
|
|
9025
9055
|
] })
|
|
9026
9056
|
]
|
|
@@ -11619,6 +11649,7 @@ function DateRangePicker({
|
|
|
11619
11649
|
activePreset,
|
|
11620
11650
|
placeholder = "Pick a date range",
|
|
11621
11651
|
className,
|
|
11652
|
+
align = "auto",
|
|
11622
11653
|
showPresets = true,
|
|
11623
11654
|
variant = "desktop",
|
|
11624
11655
|
labels = {}
|
|
@@ -11641,6 +11672,9 @@ function DateRangePicker({
|
|
|
11641
11672
|
const [hoverDate, setHoverDate] = React48.useState(null);
|
|
11642
11673
|
const calendarRef = React48.useRef(null);
|
|
11643
11674
|
const triggerRef = React48.useRef(null);
|
|
11675
|
+
const [resolvedAlign, setResolvedAlign] = React48.useState(
|
|
11676
|
+
align === "end" ? "end" : "start"
|
|
11677
|
+
);
|
|
11644
11678
|
const isMobileVariant = variant === "mobile";
|
|
11645
11679
|
const isResponsive = variant === "responsive";
|
|
11646
11680
|
const focusTrapRef = useFocusTrap(
|
|
@@ -11679,6 +11713,22 @@ function DateRangePicker({
|
|
|
11679
11713
|
};
|
|
11680
11714
|
}
|
|
11681
11715
|
}, [isMobileVariant, isCalendarOpen]);
|
|
11716
|
+
React48.useLayoutEffect(() => {
|
|
11717
|
+
if (isMobileVariant || !isCalendarOpen) return;
|
|
11718
|
+
if (align === "start" || align === "end") {
|
|
11719
|
+
setResolvedAlign(align);
|
|
11720
|
+
return;
|
|
11721
|
+
}
|
|
11722
|
+
if (typeof window === "undefined") return;
|
|
11723
|
+
const trigger = triggerRef.current;
|
|
11724
|
+
if (!trigger) return;
|
|
11725
|
+
const rect = trigger.getBoundingClientRect();
|
|
11726
|
+
const estimatedPopupWidth = showPresets ? 840 : 640;
|
|
11727
|
+
const margin = 8;
|
|
11728
|
+
const overflowsRight = rect.left + estimatedPopupWidth > window.innerWidth - margin;
|
|
11729
|
+
const fitsLeftAligned = rect.right - estimatedPopupWidth >= margin;
|
|
11730
|
+
setResolvedAlign(overflowsRight && fitsLeftAligned ? "end" : "start");
|
|
11731
|
+
}, [align, isCalendarOpen, isMobileVariant, showPresets]);
|
|
11682
11732
|
const handlePresetSelect = (presetKey) => {
|
|
11683
11733
|
const range = calculateDateRange(presetKey);
|
|
11684
11734
|
setRangeStart(range.start);
|
|
@@ -12018,7 +12068,8 @@ function DateRangePicker({
|
|
|
12018
12068
|
{
|
|
12019
12069
|
ref: calendarRef,
|
|
12020
12070
|
className: cn(
|
|
12021
|
-
"absolute top-full
|
|
12071
|
+
"absolute top-full z-50 mt-1",
|
|
12072
|
+
resolvedAlign === "end" ? "right-0" : "left-0",
|
|
12022
12073
|
"bg-background border-border rounded-lg border shadow-lg"
|
|
12023
12074
|
),
|
|
12024
12075
|
role: "dialog",
|