@upbound/monarch-blocks 0.4.1 → 0.6.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.
- package/README.md +17 -0
- package/dist/cel-filter-bar.js +29 -15
- package/dist/cel-filter-bar.js.map +1 -1
- package/dist/chart.js.map +1 -1
- package/dist/chat-interface.js +1 -1
- package/dist/chat-interface.js.map +1 -1
- package/dist/code-block.js.map +1 -1
- package/dist/data-table.d.ts +33 -180
- package/dist/data-table.js +452 -307
- package/dist/data-table.js.map +1 -1
- package/dist/empty-view-DO36LNvk.d.ts +179 -0
- package/dist/filter-bar.d.ts +6 -2
- package/dist/filter-bar.js +102 -54
- package/dist/filter-bar.js.map +1 -1
- package/dist/floating-widget.js.map +1 -1
- package/dist/graph.css +73 -0
- package/dist/graph.d.ts +182 -0
- package/dist/graph.js +1780 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1444 -369
- package/dist/index.js.map +1 -1
- package/dist/page-header.js.map +1 -1
- package/dist/relative-time.js.map +1 -1
- package/dist/section-header.js.map +1 -1
- package/dist/section-nav.js.map +1 -1
- package/dist/timeline.js.map +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { IconName } from '@upbound/monarch-core';
|
|
3
|
+
import { RowData, Cell } from '@tanstack/react-table';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Non-CEL column filter definitions — the `meta.filter` vocabulary consumed by
|
|
7
|
+
* contextual (right-click cell) filtering and by the plain filter bar.
|
|
8
|
+
* Mirrors TableWrapper's `Filters/types.ts` shapes; `id` is omitted here since
|
|
9
|
+
* it comes from the owning `ColumnDef.id`, not the filter definition itself.
|
|
10
|
+
*/
|
|
11
|
+
type ColumnFilterType = 'checkbox' | 'radio' | 'dateRange' | 'text' | 'multiText';
|
|
12
|
+
type ColumnFilterOption = {
|
|
13
|
+
label: string;
|
|
14
|
+
value: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
children?: ColumnFilterOption[];
|
|
17
|
+
};
|
|
18
|
+
type FetchColumnFilterOptionsArgs = {
|
|
19
|
+
query: string;
|
|
20
|
+
page: number;
|
|
21
|
+
signal: AbortSignal;
|
|
22
|
+
};
|
|
23
|
+
type FetchColumnFilterOptionsResult = {
|
|
24
|
+
items: ColumnFilterOption[];
|
|
25
|
+
hasMore: boolean;
|
|
26
|
+
};
|
|
27
|
+
type FetchColumnFilterOptions = (args: FetchColumnFilterOptionsArgs) => Promise<FetchColumnFilterOptionsResult>;
|
|
28
|
+
type ColumnFilterBase = {
|
|
29
|
+
title: string;
|
|
30
|
+
type: ColumnFilterType;
|
|
31
|
+
order?: number;
|
|
32
|
+
};
|
|
33
|
+
type StaticCheckboxColumnFilter = ColumnFilterBase & {
|
|
34
|
+
type: 'checkbox';
|
|
35
|
+
options: string[] | ColumnFilterOption[];
|
|
36
|
+
fetchFilterOptions?: never;
|
|
37
|
+
/** Whether the chip's value popup is a searchable Combobox. Defaults to `true`. */
|
|
38
|
+
searchable?: boolean;
|
|
39
|
+
};
|
|
40
|
+
type AsyncCheckboxColumnFilter = ColumnFilterBase & {
|
|
41
|
+
type: 'checkbox';
|
|
42
|
+
fetchFilterOptions: FetchColumnFilterOptions;
|
|
43
|
+
options?: never;
|
|
44
|
+
/** Whether the chip's value popup is a searchable Combobox. Defaults to `true`. */
|
|
45
|
+
searchable?: boolean;
|
|
46
|
+
};
|
|
47
|
+
type CheckboxColumnFilter = StaticCheckboxColumnFilter | AsyncCheckboxColumnFilter;
|
|
48
|
+
type RadioColumnFilter = ColumnFilterBase & {
|
|
49
|
+
type: 'radio';
|
|
50
|
+
options: string[] | ColumnFilterOption[];
|
|
51
|
+
/** Whether the chip's value popup is a searchable Combobox. Defaults to `true`. */
|
|
52
|
+
searchable?: boolean;
|
|
53
|
+
};
|
|
54
|
+
type DateRangeColumnFilter = ColumnFilterBase & {
|
|
55
|
+
type: 'dateRange';
|
|
56
|
+
/** When true, always show time inputs. When false, never show them. When omitted, auto-detect from value. */
|
|
57
|
+
includeTime?: boolean;
|
|
58
|
+
};
|
|
59
|
+
type TextColumnFilter = ColumnFilterBase & {
|
|
60
|
+
type: 'text';
|
|
61
|
+
placeholder?: string;
|
|
62
|
+
};
|
|
63
|
+
type MultiTextColumnFilter = ColumnFilterBase & {
|
|
64
|
+
type: 'multiText';
|
|
65
|
+
/** Defaults to comma (`,`) when omitted. */
|
|
66
|
+
delimiter?: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
placeholder?: string;
|
|
69
|
+
};
|
|
70
|
+
type ColumnFilterDefinition = CheckboxColumnFilter | DateRangeColumnFilter | RadioColumnFilter | TextColumnFilter | MultiTextColumnFilter;
|
|
71
|
+
type CheckboxColumnFilterValue = string[] | undefined;
|
|
72
|
+
type RadioColumnFilterValue = string | undefined;
|
|
73
|
+
type DateRangeColumnFilterValue = {
|
|
74
|
+
startDate: Date | null;
|
|
75
|
+
endDate: Date | null;
|
|
76
|
+
} | undefined;
|
|
77
|
+
type TextColumnFilterValue = string | undefined;
|
|
78
|
+
type MultiTextColumnFilterValue = string[] | undefined;
|
|
79
|
+
type ColumnFilterValue = CheckboxColumnFilterValue | RadioColumnFilterValue | DateRangeColumnFilterValue | TextColumnFilterValue | MultiTextColumnFilterValue;
|
|
80
|
+
|
|
81
|
+
/** Derives a contextual (right-click cell) column-filter value from a cell. */
|
|
82
|
+
type ContextualFilterValueParser<TData extends RowData, TValue> = (cell: Cell<TData, TValue>) => ColumnFilterValue | undefined;
|
|
83
|
+
/** Derives a contextual (right-click cell) global-search term from a cell. */
|
|
84
|
+
type ContextualGlobalSearchValueParser<TData extends RowData, TValue> = (cell: Cell<TData, TValue>) => string | undefined;
|
|
85
|
+
/** A fixed-width grid track: sizes to content or an explicit CSS length. */
|
|
86
|
+
type GridColumnFixed = {
|
|
87
|
+
fixed: string;
|
|
88
|
+
flex?: never;
|
|
89
|
+
};
|
|
90
|
+
type GridColumnFlexContentMin = {
|
|
91
|
+
min: 'max-content' | 'min-content';
|
|
92
|
+
minCap?: string;
|
|
93
|
+
};
|
|
94
|
+
type GridColumnFlexFixedMin = {
|
|
95
|
+
min?: string;
|
|
96
|
+
minCap?: never;
|
|
97
|
+
};
|
|
98
|
+
/** A proportional grid track: shares space by weight, with optional min/max. */
|
|
99
|
+
type GridColumnFlex = {
|
|
100
|
+
flex: number;
|
|
101
|
+
max?: string;
|
|
102
|
+
fixed?: never;
|
|
103
|
+
} & (GridColumnFlexContentMin | GridColumnFlexFixedMin);
|
|
104
|
+
/**
|
|
105
|
+
* Column sizing for grid layout mode.
|
|
106
|
+
*
|
|
107
|
+
* Fixed column (sizes to content or explicit value):
|
|
108
|
+
* { fixed: 'max-content' }
|
|
109
|
+
* { fixed: '200px' }
|
|
110
|
+
*
|
|
111
|
+
* Proportional column (shares space by weight, with optional min/max):
|
|
112
|
+
* { flex: 2, min: '100px' }
|
|
113
|
+
* { flex: 0.5, min: 'max-content' }
|
|
114
|
+
* { flex: 0.5, min: 'max-content', minCap: '200px' }
|
|
115
|
+
* { flex: 1, min: '80px', max: '500px' }
|
|
116
|
+
*/
|
|
117
|
+
type GridColumnSizing = GridColumnFixed | GridColumnFlex;
|
|
118
|
+
/**
|
|
119
|
+
* Column-def metadata `DataTable` reads — a straight port of TableWrapper's
|
|
120
|
+
* `ColumnMeta` module augmentation. Import this file for its side effect
|
|
121
|
+
* (`import '@/lib/data-table/table-meta'`) wherever a `ColumnDef` is authored
|
|
122
|
+
* with any of these fields.
|
|
123
|
+
*/
|
|
124
|
+
declare module '@tanstack/react-table' {
|
|
125
|
+
interface ColumnMeta<TData extends RowData, TValue> {
|
|
126
|
+
/** Pins the column left or right. Pinned columns are excluded from column reordering. */
|
|
127
|
+
pinning?: 'left' | 'right';
|
|
128
|
+
/** Marks an actions column — hides its header label and excludes it from contextual filtering. */
|
|
129
|
+
actions?: boolean;
|
|
130
|
+
/** The column's non-CEL filter definition, read by the plain filter bar and contextual filtering. */
|
|
131
|
+
filter?: ColumnFilterDefinition;
|
|
132
|
+
/** Parses a cell into a filter value for contextual (right-click) cell filtering. */
|
|
133
|
+
contextualFilterValue?: ContextualFilterValueParser<TData, TValue>;
|
|
134
|
+
/** Parses a cell into a search term for contextual (right-click) global search. */
|
|
135
|
+
contextualGlobalSearchValue?: ContextualGlobalSearchValueParser<TData, TValue>;
|
|
136
|
+
/** When true, the column is used only for filtering and is never rendered in the table. */
|
|
137
|
+
filterOnly?: boolean;
|
|
138
|
+
/** Column sizing for `layout="grid"` mode — see `GridColumnSizing`. */
|
|
139
|
+
grid?: GridColumnSizing;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type TableDataState = 'empty' | 'loading' | 'error' | 'success';
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Monarch-native equivalent of TableWrapper's `EmptyConfig` — same four
|
|
147
|
+
* states (error / empty / filtered-empty), rebuilt on Monarch's `Empty`
|
|
148
|
+
* compound API instead of a single props-driven component. Two deliberate
|
|
149
|
+
* adaptations: `icon` takes a Monarch `IconName` (no FontAwesome dependency),
|
|
150
|
+
* and `action` is a rendered node rather than a `ComponentType` reference.
|
|
151
|
+
* `details` has no native `Empty` slot — it composes `Alert` instead.
|
|
152
|
+
*/
|
|
153
|
+
type DataTableEmptyConfig = {
|
|
154
|
+
icon?: IconName;
|
|
155
|
+
header?: React.ReactNode;
|
|
156
|
+
subheader?: React.ReactNode;
|
|
157
|
+
details?: React.ReactNode;
|
|
158
|
+
action?: React.ReactNode;
|
|
159
|
+
className?: string;
|
|
160
|
+
wrapperClassName?: string;
|
|
161
|
+
};
|
|
162
|
+
declare const defaultErrorConfig: DataTableEmptyConfig;
|
|
163
|
+
declare const defaultEmptyConfig: DataTableEmptyConfig;
|
|
164
|
+
declare const defaultNoFilterFoundConfig: DataTableEmptyConfig;
|
|
165
|
+
type DataTableEmptyView = {
|
|
166
|
+
empty?: DataTableEmptyConfig;
|
|
167
|
+
error?: DataTableEmptyConfig;
|
|
168
|
+
filter?: DataTableEmptyConfig;
|
|
169
|
+
};
|
|
170
|
+
declare function DataTableEmptyView({ emptyView, tableState, filterCount, resetFilters, className, }: {
|
|
171
|
+
emptyView?: DataTableEmptyView;
|
|
172
|
+
/** `'success'`/`'loading'` render nothing here — the table body handles those. */
|
|
173
|
+
tableState: TableDataState;
|
|
174
|
+
filterCount: number;
|
|
175
|
+
resetFilters: () => void;
|
|
176
|
+
className?: string;
|
|
177
|
+
}): React.JSX.Element;
|
|
178
|
+
|
|
179
|
+
export { type DataTableEmptyConfig as D, type TableDataState as T, DataTableEmptyView as a, defaultErrorConfig as b, defaultNoFilterFoundConfig as c, defaultEmptyConfig as d };
|
package/dist/filter-bar.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { ComboboxContent } from '@upbound/monarch-core';
|
|
2
3
|
|
|
3
4
|
type FilterType = 'checkbox' | 'radio' | 'text' | 'multiText' | 'date';
|
|
4
5
|
interface FilterOption {
|
|
@@ -58,6 +59,7 @@ interface ActiveFilter {
|
|
|
58
59
|
key: string;
|
|
59
60
|
value?: FilterValue;
|
|
60
61
|
}
|
|
62
|
+
type PortalContainer = React.ComponentProps<typeof ComboboxContent>['container'];
|
|
61
63
|
interface FilterBarProps extends React.ComponentProps<'div'> {
|
|
62
64
|
filters: FilterDefinition[];
|
|
63
65
|
activeFilters: ActiveFilter[];
|
|
@@ -65,15 +67,17 @@ interface FilterBarProps extends React.ComponentProps<'div'> {
|
|
|
65
67
|
onRemoveFilter: (key: string) => void;
|
|
66
68
|
onChangeFilter: (key: string, value: FilterValue) => void;
|
|
67
69
|
}
|
|
68
|
-
declare function FilterBar({ filters, activeFilters, onAddFilter, onRemoveFilter, onChangeFilter, className, children, ...props }: FilterBarProps): React.JSX.Element;
|
|
70
|
+
declare function FilterBar({ filters, activeFilters, onAddFilter, onRemoveFilter, onChangeFilter, className, children, ref, ...props }: FilterBarProps): React.JSX.Element;
|
|
69
71
|
interface FilterChipProps {
|
|
70
72
|
definition: FilterDefinition;
|
|
71
73
|
value: FilterValue | undefined;
|
|
72
74
|
/** Opens the chip's value popup as soon as it mounts — used right after the filter is added. */
|
|
73
75
|
autoOpen?: boolean;
|
|
76
|
+
/** Portals a searchable checkbox/radio chip's Combobox popup here instead of the default `document.body` — see `FilterBar`'s own `containerRef` for why. */
|
|
77
|
+
container?: PortalContainer;
|
|
74
78
|
onChangeValue: (value: FilterValue) => void;
|
|
75
79
|
onRemove: () => void;
|
|
76
80
|
}
|
|
77
|
-
declare function FilterChip({ definition, value, autoOpen, onChangeValue, onRemove }: FilterChipProps): React.JSX.Element;
|
|
81
|
+
declare function FilterChip({ definition, value, autoOpen, container, onChangeValue, onRemove }: FilterChipProps): React.JSX.Element;
|
|
78
82
|
|
|
79
83
|
export { type ActiveFilter, type CheckboxFilterDefinition, type CheckboxFilterValue, type DateFilterDefinition, type DateFilterValue, FilterBar, type FilterBarProps, FilterChip, type FilterDefinition, type FilterOption, type FilterType, type FilterValue, type MultiTextFilterDefinition, type MultiTextFilterValue, type RadioFilterDefinition, type RadioFilterValue, type TextFilterDefinition, type TextFilterValue };
|
package/dist/filter-bar.js
CHANGED
|
@@ -66,6 +66,9 @@ var twMerge = extendTailwindMerge({
|
|
|
66
66
|
function cn(...inputs) {
|
|
67
67
|
return twMerge(clsx(inputs));
|
|
68
68
|
}
|
|
69
|
+
function sortBy(items, getKey) {
|
|
70
|
+
return [...items].sort((a, b) => getKey(a).localeCompare(getKey(b)));
|
|
71
|
+
}
|
|
69
72
|
|
|
70
73
|
// src/filter-bar/filter-bar.tsx
|
|
71
74
|
import { Badge } from "@upbound/monarch-core";
|
|
@@ -90,7 +93,6 @@ import {
|
|
|
90
93
|
DropdownMenu,
|
|
91
94
|
DropdownMenuCheckboxItem,
|
|
92
95
|
DropdownMenuContent,
|
|
93
|
-
DropdownMenuItem,
|
|
94
96
|
DropdownMenuRadioGroup,
|
|
95
97
|
DropdownMenuRadioItem,
|
|
96
98
|
DropdownMenuTrigger
|
|
@@ -132,6 +134,17 @@ function applyTimeToDate(date, time) {
|
|
|
132
134
|
function formatDateLabel(date) {
|
|
133
135
|
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
134
136
|
}
|
|
137
|
+
function composeRefs(...refs) {
|
|
138
|
+
return (node) => {
|
|
139
|
+
for (const ref of refs) {
|
|
140
|
+
if (typeof ref === "function") ref(node);
|
|
141
|
+
else if (ref) ref.current = node;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function hasOrder(filter) {
|
|
146
|
+
return typeof filter.order === "number";
|
|
147
|
+
}
|
|
135
148
|
function FilterBar(_a) {
|
|
136
149
|
var _b = _a, {
|
|
137
150
|
filters,
|
|
@@ -140,7 +153,8 @@ function FilterBar(_a) {
|
|
|
140
153
|
onRemoveFilter,
|
|
141
154
|
onChangeFilter,
|
|
142
155
|
className,
|
|
143
|
-
children
|
|
156
|
+
children,
|
|
157
|
+
ref
|
|
144
158
|
} = _b, props = __objRest(_b, [
|
|
145
159
|
"filters",
|
|
146
160
|
"activeFilters",
|
|
@@ -148,39 +162,50 @@ function FilterBar(_a) {
|
|
|
148
162
|
"onRemoveFilter",
|
|
149
163
|
"onChangeFilter",
|
|
150
164
|
"className",
|
|
151
|
-
"children"
|
|
165
|
+
"children",
|
|
166
|
+
"ref"
|
|
152
167
|
]);
|
|
153
168
|
const usedKeys = new Set(activeFilters.map((f) => f.key));
|
|
154
|
-
const
|
|
169
|
+
const remainingFilters = filters.filter((f) => !usedKeys.has(f.key));
|
|
170
|
+
const availableFilters = filters.some(hasOrder) ? remainingFilters : sortBy(remainingFilters, (f) => f.label);
|
|
155
171
|
const shouldShowFilters = availableFilters.length > 0 || activeFilters.length > 0;
|
|
156
172
|
const [pendingOpenKey, setPendingOpenKey] = React.useState(null);
|
|
157
173
|
function handleAddFilter(key) {
|
|
158
174
|
onAddFilter(key);
|
|
159
175
|
setPendingOpenKey(key);
|
|
160
176
|
}
|
|
177
|
+
const containerRef = React.useRef(null);
|
|
161
178
|
return /* @__PURE__ */ jsxs(
|
|
162
179
|
"div",
|
|
163
180
|
__spreadProps(__spreadValues({
|
|
164
181
|
"data-slot": "filter-bar",
|
|
165
182
|
"data-visible-filters": shouldShowFilters,
|
|
166
|
-
className: cn("flex flex-wrap items-center gap-2", className)
|
|
183
|
+
className: cn("flex flex-wrap items-center gap-2", className),
|
|
184
|
+
ref: composeRefs(containerRef, ref)
|
|
167
185
|
}, props), {
|
|
168
186
|
children: [
|
|
169
|
-
availableFilters.length > 0 && /* @__PURE__ */ jsxs(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
availableFilters.length > 0 && /* @__PURE__ */ jsxs(
|
|
188
|
+
Combobox,
|
|
189
|
+
{
|
|
190
|
+
items: availableFilters,
|
|
191
|
+
itemToStringValue: (item) => item.label,
|
|
192
|
+
itemToStringLabel: (item) => item.label,
|
|
193
|
+
onValueChange: (filter) => {
|
|
194
|
+
if (filter) handleAddFilter(filter.key);
|
|
195
|
+
},
|
|
196
|
+
children: [
|
|
197
|
+
/* @__PURE__ */ jsxs(ComboboxTrigger, { "aria-label": "Add filter", render: /* @__PURE__ */ jsx(Button, { variant: "outline" }), children: [
|
|
198
|
+
/* @__PURE__ */ jsx(Icon, { name: "plus", "data-icon": "inline-start" }),
|
|
199
|
+
"Add filter"
|
|
200
|
+
] }),
|
|
201
|
+
/* @__PURE__ */ jsxs(ComboboxContent, { container: containerRef, align: "start", className: "w-48", children: [
|
|
202
|
+
/* @__PURE__ */ jsx(ComboboxInput, { showTrigger: false, placeholder: "Search filters\u2026" }),
|
|
203
|
+
/* @__PURE__ */ jsx(ComboboxEmpty, { children: "No filters found." }),
|
|
204
|
+
/* @__PURE__ */ jsx(ComboboxList, { children: (filter) => /* @__PURE__ */ jsx(ComboboxItem, { value: filter, children: filter.label }, filter.key) })
|
|
205
|
+
] })
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
),
|
|
184
209
|
activeFilters.map((active) => {
|
|
185
210
|
const definition = filters.find((f) => f.key === active.key);
|
|
186
211
|
if (!definition) return null;
|
|
@@ -190,6 +215,7 @@ function FilterBar(_a) {
|
|
|
190
215
|
definition,
|
|
191
216
|
value: active.value,
|
|
192
217
|
autoOpen: active.key === pendingOpenKey,
|
|
218
|
+
container: containerRef,
|
|
193
219
|
onChangeValue: (value) => onChangeFilter(active.key, value),
|
|
194
220
|
onRemove: () => onRemoveFilter(active.key)
|
|
195
221
|
},
|
|
@@ -201,7 +227,7 @@ function FilterBar(_a) {
|
|
|
201
227
|
})
|
|
202
228
|
);
|
|
203
229
|
}
|
|
204
|
-
function FilterChip({ definition, value, autoOpen, onChangeValue, onRemove }) {
|
|
230
|
+
function FilterChip({ definition, value, autoOpen, container, onChangeValue, onRemove }) {
|
|
205
231
|
var _a;
|
|
206
232
|
const type = (_a = definition.type) != null ? _a : "checkbox";
|
|
207
233
|
switch (type) {
|
|
@@ -212,6 +238,7 @@ function FilterChip({ definition, value, autoOpen, onChangeValue, onRemove }) {
|
|
|
212
238
|
definition,
|
|
213
239
|
value,
|
|
214
240
|
autoOpen,
|
|
241
|
+
container,
|
|
215
242
|
onChangeValue,
|
|
216
243
|
onRemove
|
|
217
244
|
}
|
|
@@ -223,6 +250,7 @@ function FilterChip({ definition, value, autoOpen, onChangeValue, onRemove }) {
|
|
|
223
250
|
definition,
|
|
224
251
|
value,
|
|
225
252
|
autoOpen,
|
|
253
|
+
container,
|
|
226
254
|
onChangeValue,
|
|
227
255
|
onRemove
|
|
228
256
|
}
|
|
@@ -269,11 +297,13 @@ function CheckboxFilterChip({
|
|
|
269
297
|
definition,
|
|
270
298
|
value,
|
|
271
299
|
autoOpen,
|
|
300
|
+
container,
|
|
272
301
|
onChangeValue,
|
|
273
302
|
onRemove
|
|
274
303
|
}) {
|
|
275
304
|
var _a, _b;
|
|
276
|
-
const { label,
|
|
305
|
+
const { label, searchable = false } = definition;
|
|
306
|
+
const options = sortBy(definition.options, (o) => o.label);
|
|
277
307
|
const values = asCheckboxValue(value);
|
|
278
308
|
const displayLabel = values.length === 0 ? "Any" : values.length === 1 ? (_b = (_a = options.find((o) => o.value === values[0])) == null ? void 0 : _a.label) != null ? _b : values[0] : `${values.length} selected`;
|
|
279
309
|
function toggle(optionValue) {
|
|
@@ -299,25 +329,33 @@ function CheckboxFilterChip({
|
|
|
299
329
|
children: /* @__PURE__ */ jsx("span", { className: values.length === 0 ? "text-muted-foreground" : "", children: displayLabel })
|
|
300
330
|
}
|
|
301
331
|
),
|
|
302
|
-
/* @__PURE__ */ jsxs(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
332
|
+
/* @__PURE__ */ jsxs(
|
|
333
|
+
ComboboxContent,
|
|
334
|
+
{
|
|
335
|
+
container,
|
|
336
|
+
className: "min-w-64",
|
|
337
|
+
collisionAvoidance: { side: "none", align: "shift" },
|
|
338
|
+
children: [
|
|
339
|
+
/* @__PURE__ */ jsx(ComboboxInput, { showTrigger: false, placeholder: `Search ${label.toLowerCase()}\u2026` }),
|
|
340
|
+
values.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
341
|
+
/* @__PURE__ */ jsxs(ComboboxSelectedChips, { children: [
|
|
342
|
+
/* @__PURE__ */ jsx(ComboboxValue, { children: (selected) => /* @__PURE__ */ jsx(Fragment, { children: selected.map((item) => /* @__PURE__ */ jsx(ComboboxChip, { children: item.label }, item.value)) }) }),
|
|
343
|
+
/* @__PURE__ */ jsx(ComboboxClearAll, { onClick: () => onChangeValue([]) })
|
|
344
|
+
] }),
|
|
345
|
+
/* @__PURE__ */ jsx(ComboboxSeparator, {})
|
|
346
|
+
] }),
|
|
347
|
+
/* @__PURE__ */ jsxs(ComboboxEmpty, { children: [
|
|
348
|
+
"No ",
|
|
349
|
+
label.toLowerCase(),
|
|
350
|
+
" found."
|
|
351
|
+
] }),
|
|
352
|
+
/* @__PURE__ */ jsx(ComboboxList, { children: (item) => /* @__PURE__ */ jsxs(ComboboxItem, { value: item, children: [
|
|
353
|
+
item.icon,
|
|
354
|
+
item.label
|
|
355
|
+
] }, item.value) })
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
)
|
|
321
359
|
]
|
|
322
360
|
}
|
|
323
361
|
) : /* @__PURE__ */ jsxs(DropdownMenu, { defaultOpen: autoOpen, children: [
|
|
@@ -345,11 +383,13 @@ function RadioFilterChip({
|
|
|
345
383
|
definition,
|
|
346
384
|
value,
|
|
347
385
|
autoOpen,
|
|
386
|
+
container,
|
|
348
387
|
onChangeValue,
|
|
349
388
|
onRemove
|
|
350
389
|
}) {
|
|
351
390
|
var _a, _b, _c;
|
|
352
|
-
const { label,
|
|
391
|
+
const { label, searchable = false } = definition;
|
|
392
|
+
const options = sortBy(definition.options, (o) => o.label);
|
|
353
393
|
const selectedValue = asRadioValue(value);
|
|
354
394
|
const displayLabel = selectedValue ? (_b = (_a = options.find((o) => o.value === selectedValue)) == null ? void 0 : _a.label) != null ? _b : selectedValue : "Any";
|
|
355
395
|
const selected = (_c = options.find((o) => o.value === selectedValue)) != null ? _c : null;
|
|
@@ -374,18 +414,26 @@ function RadioFilterChip({
|
|
|
374
414
|
children: /* @__PURE__ */ jsx("span", { className: selectedValue ? "" : "text-muted-foreground", children: displayLabel })
|
|
375
415
|
}
|
|
376
416
|
),
|
|
377
|
-
/* @__PURE__ */ jsxs(
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
"
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
417
|
+
/* @__PURE__ */ jsxs(
|
|
418
|
+
ComboboxContent,
|
|
419
|
+
{
|
|
420
|
+
container,
|
|
421
|
+
className: "min-w-64",
|
|
422
|
+
collisionAvoidance: { side: "none", align: "shift" },
|
|
423
|
+
children: [
|
|
424
|
+
/* @__PURE__ */ jsx(ComboboxInput, { showTrigger: false, placeholder: `Search ${label.toLowerCase()}\u2026` }),
|
|
425
|
+
/* @__PURE__ */ jsxs(ComboboxEmpty, { children: [
|
|
426
|
+
"No ",
|
|
427
|
+
label.toLowerCase(),
|
|
428
|
+
" found."
|
|
429
|
+
] }),
|
|
430
|
+
/* @__PURE__ */ jsx(ComboboxList, { children: (item) => /* @__PURE__ */ jsxs(ComboboxItem, { value: item, children: [
|
|
431
|
+
item.icon,
|
|
432
|
+
item.label
|
|
433
|
+
] }, item.value) })
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
)
|
|
389
437
|
]
|
|
390
438
|
}
|
|
391
439
|
) : /* @__PURE__ */ jsxs(DropdownMenu, { defaultOpen: autoOpen, children: [
|