@ai-matrx/design-system 0.26.0 → 0.27.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/data-table/copy-helpers.cjs.map +1 -1
  3. package/dist/data-table/copy-helpers.d.cts +2 -1
  4. package/dist/data-table/copy-helpers.d.ts +2 -1
  5. package/dist/data-table/copy-helpers.js.map +1 -1
  6. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  7. package/dist/data-table/data-row-inspector.js.map +1 -1
  8. package/dist/data-table/data-row-window.cjs.map +1 -1
  9. package/dist/data-table/data-row-window.js.map +1 -1
  10. package/dist/data-table/date-filter.cjs +145 -0
  11. package/dist/data-table/date-filter.cjs.map +1 -0
  12. package/dist/data-table/date-filter.d.cts +31 -0
  13. package/dist/data-table/date-filter.d.ts +31 -0
  14. package/dist/data-table/date-filter.js +125 -0
  15. package/dist/data-table/date-filter.js.map +1 -0
  16. package/dist/data-table/filter-engine.cjs +88 -0
  17. package/dist/data-table/filter-engine.cjs.map +1 -1
  18. package/dist/data-table/filter-engine.d.cts +2 -1
  19. package/dist/data-table/filter-engine.d.ts +2 -1
  20. package/dist/data-table/filter-engine.js +88 -0
  21. package/dist/data-table/filter-engine.js.map +1 -1
  22. package/dist/data-table/host.d.cts +2 -1
  23. package/dist/data-table/host.d.ts +2 -1
  24. package/dist/data-table/index.cjs +238 -7
  25. package/dist/data-table/index.cjs.map +1 -1
  26. package/dist/data-table/index.d.cts +3 -2
  27. package/dist/data-table/index.d.ts +3 -2
  28. package/dist/data-table/index.js +238 -7
  29. package/dist/data-table/index.js.map +1 -1
  30. package/dist/data-table/infer-filter.cjs +2 -0
  31. package/dist/data-table/infer-filter.cjs.map +1 -1
  32. package/dist/data-table/infer-filter.d.cts +3 -2
  33. package/dist/data-table/infer-filter.d.ts +3 -2
  34. package/dist/data-table/infer-filter.js +2 -0
  35. package/dist/data-table/infer-filter.js.map +1 -1
  36. package/dist/data-table/layered-filters.d.cts +2 -1
  37. package/dist/data-table/layered-filters.d.ts +2 -1
  38. package/dist/data-table/query-control.cjs.map +1 -1
  39. package/dist/data-table/query-control.d.cts +2 -1
  40. package/dist/data-table/query-control.d.ts +2 -1
  41. package/dist/data-table/query-control.js.map +1 -1
  42. package/dist/data-table/types.cjs.map +1 -1
  43. package/dist/data-table/types.d.cts +2 -1
  44. package/dist/data-table/types.d.ts +2 -1
  45. package/dist/data-table/url-state.d.cts +2 -1
  46. package/dist/data-table/url-state.d.ts +2 -1
  47. package/dist/data-table/xlsx.cjs.map +1 -1
  48. package/dist/data-table/xlsx.d.cts +2 -1
  49. package/dist/data-table/xlsx.d.ts +2 -1
  50. package/dist/data-table/xlsx.js.map +1 -1
  51. package/dist/field-formats/index.cjs +15 -0
  52. package/dist/field-formats/index.cjs.map +1 -1
  53. package/dist/field-formats/index.js +15 -0
  54. package/dist/field-formats/index.js.map +1 -1
  55. package/dist/{types-Cu5_eUG1.d.ts → types-D9JBR6ZU.d.ts} +3 -2
  56. package/dist/{types-DrJXAAoD.d.cts → types-jQddSUnj.d.cts} +3 -2
  57. package/package.json +11 -1
@@ -58,6 +58,8 @@ __export(data_table_exports, {
58
58
  SavedViewsControl: () => SavedViewsControl,
59
59
  TABLE_STYLE_METADATA_KEY: () => TABLE_STYLE_METADATA_KEY,
60
60
  TABLE_STYLE_VERSION: () => TABLE_STYLE_VERSION,
61
+ TIME_RANGE_PRESETS: () => TIME_RANGE_PRESETS,
62
+ TIME_RANGE_PRESET_VALUES: () => TIME_RANGE_PRESET_VALUES,
61
63
  TableTitleRow: () => TableTitleRow,
62
64
  TableViewTabs: () => TableViewTabs,
63
65
  UNKNOWN_TOTAL_BADGE: () => UNKNOWN_TOTAL_BADGE,
@@ -81,6 +83,7 @@ __export(data_table_exports, {
81
83
  computeVariableWindow: () => computeVariableWindow,
82
84
  computeWindow: () => computeWindow,
83
85
  createUndoStack: () => createUndoStack,
86
+ dateFilterBounds: () => dateFilterBounds,
84
87
  describeCoverage: () => describeCoverage,
85
88
  detectSeries: () => detectSeries,
86
89
  directClickKinds: () => directClickKinds,
@@ -5131,6 +5134,124 @@ function layeredFilterRuleSummary(rule, fields) {
5131
5134
  return rule.operator === "between" ? `${fieldLabel} ${operator} ${value} and ${rule.valueTo ?? ""}` : `${fieldLabel} ${operator} ${value}`;
5132
5135
  }
5133
5136
 
5137
+ // src/data-table/date-filter.ts
5138
+ var TIME_RANGE_PRESET_VALUES = [
5139
+ "all",
5140
+ "1m",
5141
+ "15m",
5142
+ "30m",
5143
+ "1h",
5144
+ "2h",
5145
+ "6h",
5146
+ "12h",
5147
+ "today",
5148
+ "yesterday",
5149
+ "this_week",
5150
+ "this_month",
5151
+ "this_year",
5152
+ "older_1m",
5153
+ "older_15m",
5154
+ "older_30m",
5155
+ "older_1h",
5156
+ "older_2h",
5157
+ "older_6h",
5158
+ "older_12h",
5159
+ "older_today",
5160
+ "older_this_week",
5161
+ "older_this_month",
5162
+ "older_this_year"
5163
+ ];
5164
+ var TIME_RANGE_PRESETS = [
5165
+ { value: "all", label: "All time", group: "all" },
5166
+ { value: "1m", label: "Last minute", group: "recent" },
5167
+ { value: "15m", label: "Last 15 minutes", group: "recent" },
5168
+ { value: "30m", label: "Last 30 minutes", group: "recent" },
5169
+ { value: "1h", label: "Last hour", group: "recent" },
5170
+ { value: "2h", label: "Last 2 hours", group: "recent" },
5171
+ { value: "6h", label: "Last 6 hours", group: "recent" },
5172
+ { value: "12h", label: "Last 12 hours", group: "recent" },
5173
+ { value: "today", label: "Today", group: "calendar" },
5174
+ { value: "yesterday", label: "Yesterday", group: "calendar" },
5175
+ { value: "this_week", label: "This week", group: "calendar" },
5176
+ { value: "this_month", label: "This month", group: "calendar" },
5177
+ { value: "this_year", label: "This year", group: "calendar" },
5178
+ { value: "older_1m", label: "Older than 1 minute", group: "older" },
5179
+ { value: "older_15m", label: "Older than 15 minutes", group: "older" },
5180
+ { value: "older_30m", label: "Older than 30 minutes", group: "older" },
5181
+ { value: "older_1h", label: "Older than 1 hour", group: "older" },
5182
+ { value: "older_2h", label: "Older than 2 hours", group: "older" },
5183
+ { value: "older_6h", label: "Older than 6 hours", group: "older" },
5184
+ { value: "older_12h", label: "Older than 12 hours", group: "older" },
5185
+ { value: "older_today", label: "Before today", group: "older" },
5186
+ { value: "older_this_week", label: "Before this week", group: "older" },
5187
+ { value: "older_this_month", label: "Before this month", group: "older" },
5188
+ { value: "older_this_year", label: "Before this year", group: "older" }
5189
+ ];
5190
+ function startOfDay(date) {
5191
+ const next = new Date(date);
5192
+ next.setHours(0, 0, 0, 0);
5193
+ return next;
5194
+ }
5195
+ function startOfWeek(date) {
5196
+ const next = startOfDay(date);
5197
+ next.setDate(next.getDate() - (next.getDay() === 0 ? 6 : next.getDay() - 1));
5198
+ return next;
5199
+ }
5200
+ function startOfMonth(date) {
5201
+ return new Date(date.getFullYear(), date.getMonth(), 1);
5202
+ }
5203
+ function startOfYear(date) {
5204
+ return new Date(date.getFullYear(), 0, 1);
5205
+ }
5206
+ function validDate(value) {
5207
+ if (value === void 0) return void 0;
5208
+ const date = value instanceof Date ? new Date(value) : new Date(value);
5209
+ return Number.isNaN(date.valueOf()) ? void 0 : date;
5210
+ }
5211
+ function dateFilterBounds(filter, now = /* @__PURE__ */ new Date()) {
5212
+ if (!filter.preset) {
5213
+ return {
5214
+ ...filter.since === void 0 ? {} : { since: filter.since },
5215
+ ...filter.until === void 0 ? {} : { until: filter.until }
5216
+ };
5217
+ }
5218
+ if (filter.preset === "all") return {};
5219
+ const anchor = validDate(filter.anchor) ?? validDate(now) ?? /* @__PURE__ */ new Date();
5220
+ const ago = (milliseconds) => new Date(anchor.valueOf() - milliseconds).toISOString();
5221
+ const recent = {
5222
+ "1m": 6e4,
5223
+ "15m": 15 * 6e4,
5224
+ "30m": 30 * 6e4,
5225
+ "1h": 60 * 6e4,
5226
+ "2h": 2 * 60 * 6e4,
5227
+ "6h": 6 * 60 * 6e4,
5228
+ "12h": 12 * 60 * 6e4
5229
+ };
5230
+ const duration = recent[filter.preset.replace("older_", "")];
5231
+ if (duration !== void 0) {
5232
+ return filter.preset.startsWith("older_") ? { until: ago(duration) } : { since: ago(duration) };
5233
+ }
5234
+ const starts = {
5235
+ today: startOfDay(anchor),
5236
+ this_week: startOfWeek(anchor),
5237
+ this_month: startOfMonth(anchor),
5238
+ this_year: startOfYear(anchor),
5239
+ older_today: startOfDay(anchor),
5240
+ older_this_week: startOfWeek(anchor),
5241
+ older_this_month: startOfMonth(anchor),
5242
+ older_this_year: startOfYear(anchor)
5243
+ };
5244
+ if (filter.preset === "yesterday") {
5245
+ const until = startOfDay(anchor);
5246
+ const since = new Date(until);
5247
+ since.setDate(since.getDate() - 1);
5248
+ return { since: since.toISOString(), until: until.toISOString() };
5249
+ }
5250
+ const start = starts[filter.preset];
5251
+ if (!start) return {};
5252
+ return filter.preset.startsWith("older_") ? { until: start.toISOString() } : { since: start.toISOString() };
5253
+ }
5254
+
5134
5255
  // src/data-table/filter-engine.ts
5135
5256
  var SELECT_EMPTY_VALUE = "__empty__";
5136
5257
  var SELECT_NOT_EMPTY_VALUE = "__not_empty__";
@@ -5233,6 +5354,21 @@ function passesColumnFilter(value, filter) {
5233
5354
  if (filter.max !== void 0 && n2 > filter.max) return false;
5234
5355
  return true;
5235
5356
  }
5357
+ case "date": {
5358
+ const raw = value instanceof Date ? value : new Date(stringifyCellValue(value));
5359
+ if (Number.isNaN(raw.valueOf())) return false;
5360
+ const { since, until } = dateFilterBounds(filter);
5361
+ const timestamp = raw.valueOf();
5362
+ if (since !== void 0) {
5363
+ const sinceTimestamp = new Date(since).valueOf();
5364
+ if (Number.isNaN(sinceTimestamp) || timestamp < sinceTimestamp) return false;
5365
+ }
5366
+ if (until !== void 0) {
5367
+ const untilTimestamp = new Date(until).valueOf();
5368
+ if (Number.isNaN(untilTimestamp) || timestamp >= untilTimestamp) return false;
5369
+ }
5370
+ return true;
5371
+ }
5236
5372
  }
5237
5373
  })();
5238
5374
  return filter.negated ? !matches : matches;
@@ -5310,6 +5446,9 @@ function countActiveColumnFilters(filters) {
5310
5446
  case "number":
5311
5447
  if (f.min !== void 0 || f.max !== void 0) n2 += 1;
5312
5448
  break;
5449
+ case "date":
5450
+ if (isColumnFilterActive(f)) n2 += 1;
5451
+ break;
5313
5452
  }
5314
5453
  }
5315
5454
  return n2;
@@ -5325,6 +5464,10 @@ function isColumnFilterActive(filter) {
5325
5464
  return true;
5326
5465
  case "number":
5327
5466
  return filter.min !== void 0 || filter.max !== void 0;
5467
+ case "date": {
5468
+ const bounds = dateFilterBounds(filter);
5469
+ return bounds.since !== void 0 || bounds.until !== void 0;
5470
+ }
5328
5471
  }
5329
5472
  }
5330
5473
  function applyRowEdits(row, edits) {
@@ -6141,7 +6284,7 @@ function ColumnHeaderCell({
6141
6284
  const visibleFilter = deferredFilter ? draftFilter : filterValue;
6142
6285
  const setNegated = (negated) => {
6143
6286
  setPendingNegation(negated);
6144
- if (!visibleFilter) return;
6287
+ if (!visibleFilter || visibleFilter.kind === "date") return;
6145
6288
  const next = { ...visibleFilter, ...negated ? { negated: true } : {} };
6146
6289
  if (!negated) delete next.negated;
6147
6290
  if (deferredFilter) setDraftFilter(next);
@@ -6149,7 +6292,7 @@ function ColumnHeaderCell({
6149
6292
  };
6150
6293
  const markerLabels = marker ? markerCopy(marker) : void 0;
6151
6294
  const accessibleLabel = markerLabels?.label ?? labelText;
6152
- const menuLabel = accessibleLabel ? `Sort or filter ${accessibleLabel}` : "Sort or filter column";
6295
+ const menuLabel = filterKind ? accessibleLabel ? `Sort or filter ${accessibleLabel}` : "Sort or filter column" : accessibleLabel ? `Sort ${accessibleLabel}` : "Sort column";
6153
6296
  const menuContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
6154
6297
  PopoverContent,
6155
6298
  {
@@ -6217,7 +6360,7 @@ function ColumnHeaderCell({
6217
6360
  kind: filterKind,
6218
6361
  value: visibleFilter,
6219
6362
  onChange: (next) => {
6220
- const preservingNegation = next && (visibleFilter?.negated ?? pendingNegation) ? { ...next, negated: true } : next;
6363
+ const preservingNegation = next && next.kind !== "date" && (visibleFilter?.negated ?? pendingNegation) ? { ...next, negated: true } : next;
6221
6364
  if (deferredFilter) setDraftFilter(preservingNegation);
6222
6365
  else onFilterChange(preservingNegation);
6223
6366
  },
@@ -6237,7 +6380,7 @@ function ColumnHeaderCell({
6237
6380
  allowNullModes
6238
6381
  }
6239
6382
  ) : null,
6240
- filterKind && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
6383
+ filterKind && filterKind !== "date" && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
6241
6384
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "mb-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Match mode" }),
6242
6385
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "grid grid-cols-2 gap-1 rounded-md border p-0.5", children: [
6243
6386
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
@@ -6596,6 +6739,9 @@ function FilterBody({
6596
6739
  )
6597
6740
  ] });
6598
6741
  }
6742
+ if (kind === "date") {
6743
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(DateFilterBody, { value, onChange });
6744
+ }
6599
6745
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(NumberFilterBody, { value, onChange });
6600
6746
  }
6601
6747
  function FacetChecklist({
@@ -6704,6 +6850,72 @@ function FacetChecklist({
6704
6850
  ) : null
6705
6851
  ] });
6706
6852
  }
6853
+ function DateFilterBody({
6854
+ value,
6855
+ onChange
6856
+ }) {
6857
+ const dateValue = value?.kind === "date" ? value : void 0;
6858
+ const isCustom = dateValue !== void 0 && dateValue.preset === void 0;
6859
+ const selected = dateValue?.preset ?? (isCustom ? "__custom__" : "all");
6860
+ const setBound = (bound, raw) => {
6861
+ const next = raw ? new Date(raw) : void 0;
6862
+ const iso = next && !Number.isNaN(next.valueOf()) ? next.toISOString() : void 0;
6863
+ const current = dateValue && dateValue.preset === void 0 ? dateValue : { kind: "date" };
6864
+ const updated = { ...current, [bound]: iso };
6865
+ if (updated.since === void 0 && updated.until === void 0) onChange(void 0);
6866
+ else onChange(updated);
6867
+ };
6868
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-2 px-1", children: [
6869
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between", children: [
6870
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Date range" }),
6871
+ dateValue ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: "text-[11px] text-muted-foreground hover:text-foreground", onClick: () => onChange(void 0), children: "clear" }) : null
6872
+ ] }),
6873
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
6874
+ Select,
6875
+ {
6876
+ value: selected,
6877
+ onValueChange: (next) => {
6878
+ if (next === "all") {
6879
+ onChange(void 0);
6880
+ return;
6881
+ }
6882
+ if (next === "__custom__") {
6883
+ onChange({ kind: "date" });
6884
+ return;
6885
+ }
6886
+ onChange({ kind: "date", preset: next, anchor: (/* @__PURE__ */ new Date()).toISOString() });
6887
+ },
6888
+ children: [
6889
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectValue, {}) }),
6890
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(SelectContent, { children: [
6891
+ ["all", "recent", "calendar", "older"].map((group) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { children: [
6892
+ group !== "all" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: group }) : null,
6893
+ TIME_RANGE_PRESETS.filter((option) => option.group === group).map((option) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectItem, { value: option.value, children: option.label }, option.value))
6894
+ ] }, group)),
6895
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectItem, { value: "__custom__", children: "Custom range" })
6896
+ ] })
6897
+ ]
6898
+ }
6899
+ ),
6900
+ isCustom ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "grid gap-1.5", children: [
6901
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "grid gap-0.5 text-[11px] text-muted-foreground", children: [
6902
+ "On or after",
6903
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Input, { type: "datetime-local", value: dateTimeLocal(dateValue?.since), onChange: (event) => setBound("since", event.target.value), className: "h-8 text-xs" })
6904
+ ] }),
6905
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "grid gap-0.5 text-[11px] text-muted-foreground", children: [
6906
+ "Before",
6907
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Input, { type: "datetime-local", value: dateTimeLocal(dateValue?.until), onChange: (event) => setBound("until", event.target.value), className: "h-8 text-xs" })
6908
+ ] })
6909
+ ] }) : null
6910
+ ] });
6911
+ }
6912
+ function dateTimeLocal(value) {
6913
+ if (!value) return "";
6914
+ const date = new Date(value);
6915
+ if (Number.isNaN(date.valueOf())) return "";
6916
+ const offset = date.getTimezoneOffset() * 6e4;
6917
+ return new Date(date.valueOf() - offset).toISOString().slice(0, 16);
6918
+ }
6707
6919
  function SearchableSelectFilter({
6708
6920
  selected,
6709
6921
  options,
@@ -9286,7 +9498,8 @@ var filterSchema = import_zod2.z.union([
9286
9498
  import_zod2.z.object({ kind: import_zod2.z.literal("text"), value: import_zod2.z.string(), mode: import_zod2.z.enum(["contains", "empty", "not_empty", "null", "not_null"]).optional(), negated: import_zod2.z.boolean().optional() }),
9287
9499
  import_zod2.z.object({ kind: import_zod2.z.literal("select"), value: import_zod2.z.string(), values: import_zod2.z.array(import_zod2.z.string()).optional(), negated: import_zod2.z.boolean().optional() }),
9288
9500
  import_zod2.z.object({ kind: import_zod2.z.literal("boolean"), value: import_zod2.z.boolean(), negated: import_zod2.z.boolean().optional() }),
9289
- import_zod2.z.object({ kind: import_zod2.z.literal("number"), min: import_zod2.z.number().optional(), max: import_zod2.z.number().optional(), negated: import_zod2.z.boolean().optional() })
9501
+ import_zod2.z.object({ kind: import_zod2.z.literal("number"), min: import_zod2.z.number().optional(), max: import_zod2.z.number().optional(), negated: import_zod2.z.boolean().optional() }),
9502
+ import_zod2.z.object({ kind: import_zod2.z.literal("date"), preset: import_zod2.z.enum(TIME_RANGE_PRESET_VALUES).optional(), since: import_zod2.z.string().datetime({ offset: true }).optional(), until: import_zod2.z.string().datetime({ offset: true }).optional(), anchor: import_zod2.z.string().datetime({ offset: true }).optional() })
9290
9503
  ]);
9291
9504
  var layeredRuleSchema = import_zod2.z.object({ id: import_zod2.z.string().min(1), field: import_zod2.z.string().min(1), operator: import_zod2.z.enum(LAYERED_FILTER_OPERATORS), value: import_zod2.z.string(), valueTo: import_zod2.z.string().optional() });
9292
9505
  var snapshotSchema = import_zod2.z.object({
@@ -9314,7 +9527,8 @@ function normalizeFilters(raw) {
9314
9527
  if (value.kind === "text") filters[id] = { kind: "text", value: value.value, ...value.mode === void 0 ? {} : { mode: value.mode }, ...value.negated === void 0 ? {} : { negated: value.negated } };
9315
9528
  else if (value.kind === "select") filters[id] = { kind: "select", value: value.value, ...value.values === void 0 ? {} : { values: value.values }, ...value.negated === void 0 ? {} : { negated: value.negated } };
9316
9529
  else if (value.kind === "boolean") filters[id] = { kind: "boolean", value: value.value, ...value.negated === void 0 ? {} : { negated: value.negated } };
9317
- else filters[id] = { kind: "number", ...value.min === void 0 ? {} : { min: value.min }, ...value.max === void 0 ? {} : { max: value.max }, ...value.negated === void 0 ? {} : { negated: value.negated } };
9530
+ else if (value.kind === "number") filters[id] = { kind: "number", ...value.min === void 0 ? {} : { min: value.min }, ...value.max === void 0 ? {} : { max: value.max }, ...value.negated === void 0 ? {} : { negated: value.negated } };
9531
+ else filters[id] = { kind: "date", ...value.preset === void 0 ? {} : { preset: value.preset }, ...value.since === void 0 ? {} : { since: value.since }, ...value.until === void 0 ? {} : { until: value.until }, ...value.anchor === void 0 ? {} : { anchor: value.anchor } };
9318
9532
  }
9319
9533
  return filters;
9320
9534
  }
@@ -9864,6 +10078,7 @@ function toText(value) {
9864
10078
  return String(value);
9865
10079
  return null;
9866
10080
  }
10081
+ var BARE_CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})(?:[T ]00:00(?::00(?:\.0+)?)?)?$/;
9867
10082
  function toDate(value) {
9868
10083
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
9869
10084
  if (typeof value === "number") {
@@ -9871,6 +10086,20 @@ function toDate(value) {
9871
10086
  return Number.isNaN(d.getTime()) ? null : d;
9872
10087
  }
9873
10088
  if (typeof value === "string" && value.trim()) {
10089
+ const bare = BARE_CALENDAR_DATE.exec(value.trim());
10090
+ if (bare) {
10091
+ const [year, month, day] = [
10092
+ Number(bare[1]),
10093
+ Number(bare[2]),
10094
+ Number(bare[3])
10095
+ ];
10096
+ const d2 = new Date(year, month - 1, day);
10097
+ d2.setFullYear(year);
10098
+ if (d2.getFullYear() !== year || d2.getMonth() !== month - 1 || d2.getDate() !== day) {
10099
+ return null;
10100
+ }
10101
+ return d2;
10102
+ }
9874
10103
  const d = new Date(value);
9875
10104
  return Number.isNaN(d.getTime()) ? null : d;
9876
10105
  }
@@ -11593,6 +11822,8 @@ function filterKindLabel(kind) {
11593
11822
  return "Boolean";
11594
11823
  case "number":
11595
11824
  return "Number";
11825
+ case "date":
11826
+ return "Date";
11596
11827
  case "auto":
11597
11828
  return "Auto";
11598
11829
  case false:
@@ -14768,7 +14999,7 @@ function MatrxDataTableCore({
14768
14999
  "div",
14769
15000
  {
14770
15001
  "data-matrx-cell-content": true,
14771
- className: "min-w-0 max-w-full flex-1 whitespace-normal break-words [overflow-wrap:anywhere] sm:[&_*]:min-w-0 sm:[&_*]:whitespace-normal sm:[&_*]:[overflow-wrap:anywhere] sm:[&_.truncate]:whitespace-nowrap sm:[&_[data-slot=badge]]:whitespace-nowrap sm:[&_[data-slot=badge]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]]:w-max sm:[&_[data-matrx-cell-control]]:min-w-max sm:[&_[data-matrx-cell-control]]:max-w-none sm:[&_[data-matrx-cell-control]]:whitespace-nowrap sm:[&_[data-matrx-cell-control]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]_*]:whitespace-nowrap sm:[&_[data-matrx-cell-control]_*]:[overflow-wrap:normal]",
15002
+ className: "min-w-0 max-w-full flex-1 whitespace-normal break-words [overflow-wrap:anywhere] sm:[&_*]:min-w-0 sm:[&_*]:whitespace-normal sm:[&_*]:[overflow-wrap:anywhere] sm:[&_.truncate]:whitespace-nowrap sm:[&_[data-slot=badge]]:whitespace-nowrap sm:[&_[data-slot=badge]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]]:w-max sm:[&_[data-matrx-cell-control]]:min-w-max sm:[&_[data-matrx-cell-control]]:max-w-none sm:[&_[data-matrx-cell-control]]:whitespace-nowrap sm:[&_[data-matrx-cell-control]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]_*]:whitespace-nowrap sm:[&_[data-matrx-cell-control]_*]:[overflow-wrap:normal] [&_[data-matrx-cell-fill]]:!w-full [&_[data-matrx-cell-fill]]:!min-w-0 [&_[data-matrx-cell-fill]]:!max-w-full sm:[&_[data-matrx-cell-fill]]:!w-full sm:[&_[data-matrx-cell-fill]]:!min-w-0 sm:[&_[data-matrx-cell-fill]]:!max-w-full",
14772
15003
  children: renderRecordCell(row, col, index)
14773
15004
  }
14774
15005
  )