@jackbernnie/hiyf 0.3.7 → 0.3.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.
@@ -40,6 +40,17 @@ export interface TableColumn<T> {
40
40
  filterValue?: string;
41
41
  /** Called when a filter option is selected. */
42
42
  onFilterChange?: (value: string) => void;
43
+ /**
44
+ * Multi-select filter mode: the currently selected option values. When provided
45
+ * (with onFilterValuesChange), the header menu renders filterOptions as toggling
46
+ * check items that DON'T close the menu, so several can be selected in one visit.
47
+ * There is no "all" convention in this mode — an empty array means unfiltered, and
48
+ * a "Clear" item appears whenever anything is selected. Mutually exclusive with
49
+ * filterValue/onFilterChange single-select mode.
50
+ */
51
+ filterValues?: string[];
52
+ /** Called with the full updated selection whenever a multi-select option is toggled. */
53
+ onFilterValuesChange?: (values: string[]) => void;
43
54
  /** Optional explanatory text shown in a hover tooltip via an info icon next to the header. */
44
55
  headerInfo?: string;
45
56
  /**
@@ -70,9 +70,16 @@ function HeaderMenu({
70
70
  onSortChange
71
71
  }) {
72
72
  const activeSort = sort?.key === column.key ? sort : void 0;
73
+ const multi = column.filterValues !== void 0;
73
74
  const firstFilterValue = column.filterOptions?.[0]?.value;
74
- const filterActive = column.filterValue !== void 0 && firstFilterValue !== void 0 && column.filterValue !== firstFilterValue;
75
+ const filterActive = multi ? (column.filterValues?.length ?? 0) > 0 : column.filterValue !== void 0 && firstFilterValue !== void 0 && column.filterValue !== firstFilterValue;
75
76
  const active = Boolean(activeSort) || filterActive;
77
+ const toggleValue = (value) => {
78
+ const cur = column.filterValues ?? [];
79
+ column.onFilterValuesChange?.(
80
+ cur.includes(value) ? cur.filter((v) => v !== value) : [...cur, value]
81
+ );
82
+ };
76
83
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
77
84
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
78
85
  "button",
@@ -107,17 +114,46 @@ function HeaderMenu({
107
114
  )
108
115
  ] }),
109
116
  column.sortable && column.filterOptions && column.filterOptions.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
110
- column.filterOptions?.map((option) => /* @__PURE__ */ jsxs(
111
- DropdownMenuItem,
112
- {
113
- onSelect: () => column.onFilterChange?.(option.value),
114
- children: [
115
- /* @__PURE__ */ jsx(CheckGlyph, { visible: column.filterValue === option.value }),
116
- option.label
117
- ]
118
- },
119
- option.value
120
- ))
117
+ column.filterOptions?.map(
118
+ (option) => multi ? (
119
+ // Multi-select: toggling keeps the menu open so several values can be
120
+ // picked in one visit (preventDefault stops Radix's close-on-select).
121
+ // whitespace-nowrap: a filter label is a name — it widens the menu, never wraps.
122
+ /* @__PURE__ */ jsxs(
123
+ DropdownMenuItem,
124
+ {
125
+ className: "whitespace-nowrap",
126
+ onSelect: (event) => {
127
+ event.preventDefault();
128
+ toggleValue(option.value);
129
+ },
130
+ children: [
131
+ /* @__PURE__ */ jsx(CheckGlyph, { visible: (column.filterValues ?? []).includes(option.value) }),
132
+ option.label
133
+ ]
134
+ },
135
+ option.value
136
+ )
137
+ ) : /* @__PURE__ */ jsxs(
138
+ DropdownMenuItem,
139
+ {
140
+ className: "whitespace-nowrap",
141
+ onSelect: () => column.onFilterChange?.(option.value),
142
+ children: [
143
+ /* @__PURE__ */ jsx(CheckGlyph, { visible: column.filterValue === option.value }),
144
+ option.label
145
+ ]
146
+ },
147
+ option.value
148
+ )
149
+ ),
150
+ multi && (column.filterValues?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
151
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
152
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: () => column.onFilterValuesChange?.([]), children: [
153
+ /* @__PURE__ */ jsx(CheckGlyph, { visible: false }),
154
+ "Clear"
155
+ ] })
156
+ ] }) : null
121
157
  ] })
122
158
  ] });
123
159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackbernnie/hiyf",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "human-in-your-face — an AI design protocol (a locked, LLM-safe design system). Forked from Polar's Orbit (Apache-2.0).",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",