Skip to content

Commit 488d036

Browse files
committed
refactor: flip to caseSensitive (default is case-insensitive)
- Rename caseInsensitive -> caseSensitive on Filter type and options - Default behavior (caseSensitive=false or unset via UI) uses regex (?i) - Checkbox now labeled 'Case sensitive'; checking it opts into exact match - Only triggers regex when caseSensitive is explicitly false (backward compat)
1 parent 3dbae7d commit 488d036

6 files changed

Lines changed: 44 additions & 44 deletions

File tree

packages/core/src/components/data-table/i18n.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const dataTableLabels = defineI18nLabels({
5050
filterOperator_between: "between",
5151
filterOperator_in: "in",
5252
filterOperator_nin: "not in",
53-
filterCaseInsensitive: "Case insensitive",
53+
filterCaseSensitive: "Case sensitive",
5454

5555
// Filter chip label templates
5656
filterChipLabel: (props: { column: string; operator: string; value: string }) =>
@@ -98,7 +98,7 @@ export const dataTableLabels = defineI18nLabels({
9898
filterOperator_between: "の範囲内",
9999
filterOperator_in: "次のいずれか",
100100
filterOperator_nin: "次のいずれでもない",
101-
filterCaseInsensitive: "大文字小文字を区別しない",
101+
filterCaseSensitive: "大文字小文字を区別する",
102102

103103
// Filter chip label templates (Japanese: column: value operator)
104104
filterChipLabel: (props: { column: string; operator: string; value: string }) =>

packages/core/src/components/data-table/toolbar.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ describe("StringFilterEditor", () => {
240240
await user.click(screen.getByRole("button", { name: "Apply" }));
241241

242242
expect(control.addFilter).toHaveBeenCalledWith("name", "contains", "Bob", {
243-
caseInsensitive: false,
243+
caseSensitive: false,
244244
});
245245
});
246246

@@ -261,7 +261,7 @@ describe("StringFilterEditor", () => {
261261
await user.keyboard("{Enter}");
262262

263263
expect(control.addFilter).toHaveBeenCalledWith("name", "contains", "Charlie", {
264-
caseInsensitive: false,
264+
caseSensitive: false,
265265
});
266266
});
267267

@@ -283,7 +283,7 @@ describe("StringFilterEditor", () => {
283283
expect(control.removeFilter).toHaveBeenCalledWith("name");
284284
});
285285

286-
it("shows a Case insensitive checkbox", async () => {
286+
it("shows a Case sensitive checkbox", async () => {
287287
const user = userEvent.setup();
288288
const control = makeControl({
289289
filters: [{ field: "name", operator: "contains", value: "Alice" }],
@@ -294,10 +294,10 @@ describe("StringFilterEditor", () => {
294294

295295
await user.click(screen.getByRole("button", { name: /Name contains Alice/ }));
296296

297-
expect(await screen.findByText("Case insensitive")).toBeDefined();
297+
expect(await screen.findByText("Case sensitive")).toBeDefined();
298298
});
299299

300-
it("Apply with case-insensitive checked calls addFilter with caseInsensitive option", async () => {
300+
it("Apply with case-sensitive checked calls addFilter with caseSensitive option", async () => {
301301
const user = userEvent.setup();
302302
const control = makeControl({
303303
filters: [{ field: "name", operator: "contains", value: "Alice" }],
@@ -314,14 +314,14 @@ describe("StringFilterEditor", () => {
314314
await user.click(screen.getByRole("button", { name: "Apply" }));
315315

316316
expect(control.addFilter).toHaveBeenCalledWith("name", "contains", "Alice", {
317-
caseInsensitive: true,
317+
caseSensitive: true,
318318
});
319319
});
320320

321-
it("restores case-insensitive state from existing filter", async () => {
321+
it("restores case-sensitive state from existing filter", async () => {
322322
const user = userEvent.setup();
323323
const control = makeControl({
324-
filters: [{ field: "name", operator: "contains", value: "Alice", caseInsensitive: true }],
324+
filters: [{ field: "name", operator: "contains", value: "Alice", caseSensitive: true }],
325325
});
326326
render(<TestFilters control={control} columns={[stringColumn]} />, {
327327
wrapper,

packages/core/src/components/data-table/toolbar.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function AddFilterPopover({
120120
const [field, setField] = useState<string | null>(null);
121121
const [operator, setOperator] = useState<FilterOperator>("eq");
122122
const [value, setValue] = useState<AddFilterDraftValue>("");
123-
const [caseInsensitive, setCaseInsensitive] = useState(false);
123+
const [caseSensitive, setCaseSensitive] = useState(false);
124124

125125
const fieldLabelMap = useMemo(
126126
() => new Map(availableColumns.map((col) => [col.filter.field, col.label ?? col.filter.field])),
@@ -146,14 +146,14 @@ function AddFilterPopover({
146146
setField(null);
147147
setOperator("eq");
148148
setValue("");
149-
setCaseInsensitive(false);
149+
setCaseSensitive(false);
150150
return;
151151
}
152152

153153
setField(column.filter.field);
154154
setOperator(DEFAULT_OPERATOR[column.filter.type]);
155155
setValue(getInitialAddFilterDraftValue(column.filter.type));
156-
setCaseInsensitive(false);
156+
setCaseSensitive(false);
157157
}, []);
158158

159159
const handleOpenChange = useCallback(
@@ -177,7 +177,7 @@ function AddFilterPopover({
177177
setField(nextField);
178178
setOperator(DEFAULT_OPERATOR[nextColumn.filter.type]);
179179
setValue(getInitialAddFilterDraftValue(nextColumn.filter.type));
180-
setCaseInsensitive(false);
180+
setCaseSensitive(false);
181181
},
182182
[availableColumns],
183183
);
@@ -190,10 +190,10 @@ function AddFilterPopover({
190190
selectedColumn.filter.field,
191191
operator,
192192
toAddFilterSubmittedValue(selectedColumn.filter.type, value),
193-
selectedColumn.filter.type === "string" ? { caseInsensitive } : undefined,
193+
selectedColumn.filter.type === "string" ? { caseSensitive } : undefined,
194194
);
195195
setOpen(false);
196-
}, [selectedColumn, value, operator, caseInsensitive, control]);
196+
}, [selectedColumn, value, operator, caseSensitive, control]);
197197

198198
const renderValueEditor = () => {
199199
if (!selectedColumn) return null;
@@ -354,15 +354,15 @@ function AddFilterPopover({
354354
{selectedColumn?.filter.type === "string" && (
355355
<label className="astw:flex astw:items-center astw:gap-1.5 astw:text-sm">
356356
<Checkbox.Root
357-
checked={caseInsensitive}
358-
onCheckedChange={setCaseInsensitive}
357+
checked={caseSensitive}
358+
onCheckedChange={setCaseSensitive}
359359
className="astw:flex astw:size-4 astw:items-center astw:justify-center astw:rounded-sm astw:border astw:border-input data-[checked]:astw:border-primary data-[checked]:astw:bg-primary data-[checked]:astw:text-primary-foreground"
360360
>
361361
<Checkbox.Indicator className="astw:flex astw:items-center astw:justify-center">
362362
<Check className="astw:size-3" />
363363
</Checkbox.Indicator>
364364
</Checkbox.Root>
365-
{t("filterCaseInsensitive")}
365+
{t("filterCaseSensitive")}
366366
</label>
367367
)}
368368
<Button
@@ -662,18 +662,18 @@ function StringFilterEditor({
662662
: "contains",
663663
);
664664
const [localValue, setLocalValue] = useState(String(filter.value ?? ""));
665-
const [localCaseInsensitive, setLocalCaseInsensitive] = useState(filter.caseInsensitive ?? false);
665+
const [localCaseSensitive, setLocalCaseSensitive] = useState(filter.caseSensitive ?? false);
666666

667667
const handleCommit = useCallback(() => {
668668
if (localValue.trim() === "") {
669669
control.removeFilter(config.field);
670670
} else {
671671
control.addFilter(config.field, localOp, localValue, {
672-
caseInsensitive: localCaseInsensitive,
672+
caseSensitive: localCaseSensitive,
673673
});
674674
}
675675
onClose();
676-
}, [localValue, localOp, localCaseInsensitive, control, config.field, onClose]);
676+
}, [localValue, localOp, localCaseSensitive, control, config.field, onClose]);
677677

678678
return (
679679
<div
@@ -699,15 +699,15 @@ function StringFilterEditor({
699699
/>
700700
<label className="astw:flex astw:items-center astw:gap-1.5 astw:text-sm">
701701
<Checkbox.Root
702-
checked={localCaseInsensitive}
703-
onCheckedChange={setLocalCaseInsensitive}
702+
checked={localCaseSensitive}
703+
onCheckedChange={setLocalCaseSensitive}
704704
className="astw:flex astw:size-4 astw:items-center astw:justify-center astw:rounded-sm astw:border astw:border-input data-[checked]:astw:border-primary data-[checked]:astw:bg-primary data-[checked]:astw:text-primary-foreground"
705705
>
706706
<Checkbox.Indicator className="astw:flex astw:items-center astw:justify-center">
707707
<Check className="astw:size-3" />
708708
</Checkbox.Indicator>
709709
</Checkbox.Root>
710-
{t("filterCaseInsensitive")}
710+
{t("filterCaseSensitive")}
711711
</label>
712712
<Button size="xs" onClick={handleCommit} className="astw:self-end">
713713
{t("applyFilter")}
@@ -1076,7 +1076,7 @@ function getChipDisplayLabel(
10761076
if (!valueLabel) return columnLabel;
10771077

10781078
const operatorLabel = getOperatorLabel(filter.operator, t);
1079-
const ciSuffix = filter.caseInsensitive ? " (Aa)" : "";
1079+
const ciSuffix = filter.caseSensitive ? " (Aa)" : "";
10801080

10811081
if (config.type === "enum") {
10821082
return t("filterChipLabelEnum", {

packages/core/src/hooks/use-collection-variables.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,32 +162,32 @@ describe("useCollectionVariables", () => {
162162
expect(result.current.variables.pagination).toEqual({ first: 20 });
163163
});
164164

165-
it("adds a case-insensitive filter and converts to regex in query variables", () => {
165+
it("string filter defaults to case-insensitive regex in query variables", () => {
166166
const { result } = renderHook(() => useCollectionVariables({}));
167167

168168
act(() => {
169169
result.current.control.addFilter("name", "contains", "Alice", {
170-
caseInsensitive: true,
170+
caseSensitive: false,
171171
});
172172
});
173173

174174
expect(result.current.control.filters[0]).toMatchObject({
175175
field: "name",
176176
operator: "contains",
177177
value: "Alice",
178-
caseInsensitive: true,
178+
caseSensitive: false,
179179
});
180180
expect(result.current.variables.query).toEqual({
181181
name: { regex: "(?i)Alice" },
182182
});
183183
});
184184

185-
it("converts eq operator to regex with anchors when case-insensitive", () => {
185+
it("converts eq operator to regex with anchors when caseSensitive is false", () => {
186186
const { result } = renderHook(() => useCollectionVariables({}));
187187

188188
act(() => {
189189
result.current.control.addFilter("name", "eq", "Alice", {
190-
caseInsensitive: true,
190+
caseSensitive: false,
191191
});
192192
});
193193

@@ -196,12 +196,12 @@ describe("useCollectionVariables", () => {
196196
});
197197
});
198198

199-
it("converts hasPrefix operator to regex when case-insensitive", () => {
199+
it("converts hasPrefix operator to regex when caseSensitive is false", () => {
200200
const { result } = renderHook(() => useCollectionVariables({}));
201201

202202
act(() => {
203203
result.current.control.addFilter("name", "hasPrefix", "Al", {
204-
caseInsensitive: true,
204+
caseSensitive: false,
205205
});
206206
});
207207

@@ -210,12 +210,12 @@ describe("useCollectionVariables", () => {
210210
});
211211
});
212212

213-
it("converts hasSuffix operator to regex when case-insensitive", () => {
213+
it("converts hasSuffix operator to regex when caseSensitive is false", () => {
214214
const { result } = renderHook(() => useCollectionVariables({}));
215215

216216
act(() => {
217217
result.current.control.addFilter("name", "hasSuffix", "ce", {
218-
caseInsensitive: true,
218+
caseSensitive: false,
219219
});
220220
});
221221

@@ -229,7 +229,7 @@ describe("useCollectionVariables", () => {
229229

230230
act(() => {
231231
result.current.control.addFilter("name", "contains", "a.b*c", {
232-
caseInsensitive: true,
232+
caseSensitive: false,
233233
});
234234
});
235235

@@ -238,12 +238,12 @@ describe("useCollectionVariables", () => {
238238
});
239239
});
240240

241-
it("uses original operator when caseInsensitive is false", () => {
241+
it("uses original operator when caseSensitive is true", () => {
242242
const { result } = renderHook(() => useCollectionVariables({}));
243243

244244
act(() => {
245245
result.current.control.addFilter("name", "contains", "Alice", {
246-
caseInsensitive: false,
246+
caseSensitive: true,
247247
});
248248
});
249249

packages/core/src/hooks/use-collection-variables.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,15 @@ export function useCollectionVariables(
161161
field: string,
162162
operator: FilterOperator,
163163
value: unknown,
164-
filterOptions?: { caseInsensitive?: boolean },
164+
filterOptions?: { caseSensitive?: boolean },
165165
) => {
166166
setFiltersState((prev) => {
167167
const existing = prev.findIndex((f) => f.field === field);
168168
const newFilter: Filter = {
169169
field,
170170
operator,
171171
value,
172-
caseInsensitive: filterOptions?.caseInsensitive,
172+
caseSensitive: filterOptions?.caseSensitive,
173173
};
174174
if (existing >= 0) {
175175
const updated = [...prev];
@@ -234,7 +234,7 @@ export function useCollectionVariables(
234234
if (filters.length === 0) return undefined;
235235
const filterQuery: Record<string, Record<string, unknown>> = {};
236236
for (const filter of filters) {
237-
if (filter.caseInsensitive && typeof filter.value === "string") {
237+
if (filter.caseSensitive === false && typeof filter.value === "string") {
238238
filterQuery[filter.field] = {
239239
regex: toCaseInsensitiveRegex(filter.operator, filter.value),
240240
};

packages/core/src/types/collection.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ export interface Filter<TFieldName extends string = string> {
180180
field: TFieldName;
181181
operator: FilterOperator;
182182
value: unknown;
183-
caseInsensitive?: boolean;
183+
caseSensitive?: boolean;
184184
}
185185

186186
/**
@@ -197,7 +197,7 @@ export type TableMetadataFilter<TTable extends TableMetadata> =
197197
field: N;
198198
operator: OperatorForFilterType[FieldTypeToFilterConfigType[T]];
199199
value: unknown;
200-
caseInsensitive?: boolean;
200+
caseSensitive?: boolean;
201201
}
202202
: never
203203
: never
@@ -378,7 +378,7 @@ export interface CollectionControl<
378378
field: F,
379379
operator: OperatorForField<TFilter, F>,
380380
value: unknown,
381-
options?: { caseInsensitive?: boolean },
381+
options?: { caseSensitive?: boolean },
382382
): void;
383383
setFilters: (filters: Filter<TFieldName>[]) => void;
384384
removeFilter(field: TFieldName): void;

0 commit comments

Comments
 (0)