@ai-matrx/design-system 0.25.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 (81) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/dist/data-table/copy-helpers.cjs.map +1 -1
  3. package/dist/data-table/copy-helpers.d.cts +3 -1
  4. package/dist/data-table/copy-helpers.d.ts +3 -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/facets.cjs +118 -0
  17. package/dist/data-table/facets.cjs.map +1 -0
  18. package/dist/data-table/facets.d.cts +100 -0
  19. package/dist/data-table/facets.d.ts +100 -0
  20. package/dist/data-table/facets.js +98 -0
  21. package/dist/data-table/facets.js.map +1 -0
  22. package/dist/data-table/filter-engine.cjs +88 -0
  23. package/dist/data-table/filter-engine.cjs.map +1 -1
  24. package/dist/data-table/filter-engine.d.cts +3 -1
  25. package/dist/data-table/filter-engine.d.ts +3 -1
  26. package/dist/data-table/filter-engine.js +88 -0
  27. package/dist/data-table/filter-engine.js.map +1 -1
  28. package/dist/data-table/host.cjs.map +1 -1
  29. package/dist/data-table/host.d.cts +14 -3
  30. package/dist/data-table/host.d.ts +14 -3
  31. package/dist/data-table/host.js.map +1 -1
  32. package/dist/data-table/index.cjs +918 -152
  33. package/dist/data-table/index.cjs.map +1 -1
  34. package/dist/data-table/index.d.cts +5 -2
  35. package/dist/data-table/index.d.ts +5 -2
  36. package/dist/data-table/index.js +956 -189
  37. package/dist/data-table/index.js.map +1 -1
  38. package/dist/data-table/infer-filter.cjs +2 -0
  39. package/dist/data-table/infer-filter.cjs.map +1 -1
  40. package/dist/data-table/infer-filter.d.cts +4 -2
  41. package/dist/data-table/infer-filter.d.ts +4 -2
  42. package/dist/data-table/infer-filter.js +2 -0
  43. package/dist/data-table/infer-filter.js.map +1 -1
  44. package/dist/data-table/layered-filters.d.cts +3 -1
  45. package/dist/data-table/layered-filters.d.ts +3 -1
  46. package/dist/data-table/menu-targets.cjs +77 -0
  47. package/dist/data-table/menu-targets.cjs.map +1 -0
  48. package/dist/data-table/menu-targets.d.cts +108 -0
  49. package/dist/data-table/menu-targets.d.ts +108 -0
  50. package/dist/data-table/menu-targets.js +57 -0
  51. package/dist/data-table/menu-targets.js.map +1 -0
  52. package/dist/data-table/pagination.cjs.map +1 -1
  53. package/dist/data-table/pagination.js.map +1 -1
  54. package/dist/data-table/query-control.cjs.map +1 -1
  55. package/dist/data-table/query-control.d.cts +3 -1
  56. package/dist/data-table/query-control.d.ts +3 -1
  57. package/dist/data-table/query-control.js.map +1 -1
  58. package/dist/data-table/spreadsheet.cjs +61 -13
  59. package/dist/data-table/spreadsheet.cjs.map +1 -1
  60. package/dist/data-table/spreadsheet.d.cts +36 -1
  61. package/dist/data-table/spreadsheet.d.ts +36 -1
  62. package/dist/data-table/spreadsheet.js +61 -13
  63. package/dist/data-table/spreadsheet.js.map +1 -1
  64. package/dist/data-table/types.cjs.map +1 -1
  65. package/dist/data-table/types.d.cts +3 -1
  66. package/dist/data-table/types.d.ts +3 -1
  67. package/dist/data-table/url-state.d.cts +3 -1
  68. package/dist/data-table/url-state.d.ts +3 -1
  69. package/dist/data-table/uuid-cell.cjs.map +1 -1
  70. package/dist/data-table/uuid-cell.js.map +1 -1
  71. package/dist/data-table/xlsx.cjs.map +1 -1
  72. package/dist/data-table/xlsx.d.cts +3 -1
  73. package/dist/data-table/xlsx.d.ts +3 -1
  74. package/dist/data-table/xlsx.js.map +1 -1
  75. package/dist/field-formats/index.cjs +15 -0
  76. package/dist/field-formats/index.cjs.map +1 -1
  77. package/dist/field-formats/index.js +15 -0
  78. package/dist/field-formats/index.js.map +1 -1
  79. package/dist/{types-nlLCMiqd.d.ts → types-D9JBR6ZU.d.ts} +118 -5
  80. package/dist/{types-CmQrOz-T.d.cts → types-jQddSUnj.d.cts} +118 -5
  81. package/package.json +31 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-table/layered-filters.ts","../../src/data-table/filter-engine.ts"],"sourcesContent":["/**\n * Shared vocabulary for ordered, AND-combined table filters. The same rule\n * shape is URL-safe, can be evaluated by local tables, and can be handed to a\n * controlled table's server query without a surface inventing another query\n * builder.\n */\n\nimport { z } from \"zod\";\nimport type { ColumnFiltersState } from \"./types\";\n\nexport const LAYERED_FILTER_OPERATORS = [\n \"contains\",\n \"not_contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"word\",\n \"not_word\",\n \"is_empty\",\n \"is_not_empty\",\n \"greater_than\",\n \"greater_or_equal\",\n \"less_than\",\n \"less_or_equal\",\n \"between\",\n] as const;\n\nexport type LayeredFilterOperator = (typeof LAYERED_FILTER_OPERATORS)[number];\n\nexport interface LayeredFilterRule {\n id: string;\n field: string;\n operator: LayeredFilterOperator;\n value: string;\n valueTo?: string | undefined;\n}\n\nexport type LayeredFilterField =\n | {\n id: string;\n label: string;\n kind: \"text\";\n operators?: LayeredFilterOperator[];\n }\n | {\n id: string;\n label: string;\n kind: \"number\";\n operators?: LayeredFilterOperator[];\n placeholder?: string;\n }\n | {\n id: string;\n label: string;\n kind: \"select\";\n operators?: LayeredFilterOperator[];\n options: Array<{ value: string; label: string }>;\n };\n\nconst layeredFilterRuleSchema = z.object({\n id: z.string().min(1),\n field: z.string().min(1),\n operator: z.enum(LAYERED_FILTER_OPERATORS),\n value: z.string(),\n valueTo: z.string().optional(),\n});\n\nconst layeredFilterRulesSchema = z.array(layeredFilterRuleSchema).max(20);\n\nconst TEXT_OPERATORS: LayeredFilterOperator[] = [\n \"contains\",\n \"not_contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"word\",\n \"not_word\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nconst NUMBER_OPERATORS: LayeredFilterOperator[] = [\n \"equals\",\n \"not_equals\",\n \"greater_than\",\n \"greater_or_equal\",\n \"less_than\",\n \"less_or_equal\",\n \"between\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nconst SELECT_OPERATORS: LayeredFilterOperator[] = [\n \"equals\",\n \"not_equals\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nexport const LAYERED_FILTER_OPERATOR_LABELS: Record<\n LayeredFilterOperator,\n string\n> = {\n contains: \"contains\",\n not_contains: \"doesn't contain\",\n equals: \"is\",\n not_equals: \"is not\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n word: \"has the word\",\n not_word: \"doesn't have the word\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n greater_than: \"is greater than\",\n greater_or_equal: \"is at least\",\n less_than: \"is less than\",\n less_or_equal: \"is at most\",\n between: \"is between\",\n};\n\nexport function operatorsForLayeredField(\n field: LayeredFilterField,\n): LayeredFilterOperator[] {\n if (field.operators) return field.operators;\n if (field.kind === \"number\") return NUMBER_OPERATORS;\n if (field.kind === \"select\") return SELECT_OPERATORS;\n return TEXT_OPERATORS;\n}\n\nexport function layeredFilterNeedsValue(\n operator: LayeredFilterOperator,\n): boolean {\n return operator !== \"is_empty\" && operator !== \"is_not_empty\";\n}\n\nexport function isCompleteLayeredFilterRule(rule: LayeredFilterRule): boolean {\n if (!layeredFilterNeedsValue(rule.operator)) return true;\n if (rule.value.trim() === \"\") return false;\n return rule.operator !== \"between\" || Boolean(rule.valueTo?.trim());\n}\n\nexport function completeLayeredFilterRules(\n rules: readonly LayeredFilterRule[] | undefined,\n): LayeredFilterRule[] {\n return (rules ?? []).filter(isCompleteLayeredFilterRule);\n}\n\nexport function isLayeredFilterOperator(\n value: string,\n): value is LayeredFilterOperator {\n return LAYERED_FILTER_OPERATORS.some((operator) => operator === value);\n}\n\n/** Decode URL-owned rules without trusting a hand-edited link. */\nexport function decodeLayeredFilterRules(\n raw: string | null,\n): LayeredFilterRule[] {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n const result = layeredFilterRulesSchema.safeParse(parsed);\n return result.success ? result.data : [];\n } catch {\n return [];\n }\n}\n\n/** Stable compact URL/wire form; rule order is preserved. */\nexport function encodeLayeredFilterRules(\n rules: readonly LayeredFilterRule[] | undefined,\n): string | null {\n return rules?.length ? JSON.stringify(rules) : null;\n}\n\n/**\n * Translate ordinary per-column controls into the same ordered rule language\n * used by the advanced builder. Controlled tables can send these rules to one\n * server evaluator instead of rebuilding numeric/text filter semantics.\n * Select filters are intentionally omitted because their multi-select control\n * is OR-combined and should stay in its native query parameter.\n */\nexport function columnFiltersToLayeredRules(\n filters: ColumnFiltersState,\n fieldIds: readonly string[],\n): LayeredFilterRule[] {\n const rules: LayeredFilterRule[] = [];\n for (const field of fieldIds) {\n const filter = filters[field];\n if (!filter) continue;\n\n if (filter.kind === \"text\") {\n rules.push({\n id: `column-${field}`,\n field,\n operator:\n filter.mode === \"empty\"\n ? \"is_empty\"\n : filter.mode === \"not_empty\"\n ? \"is_not_empty\"\n : \"contains\",\n value: filter.value,\n });\n continue;\n }\n\n if (filter.kind === \"number\") {\n if (filter.min !== undefined && filter.max !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"between\",\n value: String(filter.min),\n valueTo: String(filter.max),\n });\n } else if (filter.min !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"greater_or_equal\",\n value: String(filter.min),\n });\n } else if (filter.max !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"less_or_equal\",\n value: String(filter.max),\n });\n }\n continue;\n }\n\n if (filter.kind === \"boolean\") {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"equals\",\n value: String(filter.value),\n });\n }\n }\n return rules;\n}\n\nfunction normalizedText(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n return String(value).trim().toLocaleLowerCase();\n}\n\nfunction words(value: string): string[] {\n return value.split(/[^\\p{L}\\p{N}]+/u).filter(Boolean);\n}\n\n/** Local-table evaluator. Controlled tables send the same rule shape server-side. */\nexport function layeredFilterMatchesValue(\n value: unknown,\n rule: LayeredFilterRule,\n): boolean {\n const actual = normalizedText(value);\n const expected = rule.value.trim().toLocaleLowerCase();\n const expectedTo = rule.valueTo?.trim().toLocaleLowerCase() ?? \"\";\n\n switch (rule.operator) {\n case \"contains\":\n return actual.includes(expected);\n case \"not_contains\":\n return !actual.includes(expected);\n case \"equals\":\n return actual === expected;\n case \"not_equals\":\n return actual !== expected;\n case \"starts_with\":\n return actual.startsWith(expected);\n case \"ends_with\":\n return actual.endsWith(expected);\n case \"word\":\n return words(actual).includes(expected);\n case \"not_word\":\n return !words(actual).includes(expected);\n case \"is_empty\":\n return actual === \"\";\n case \"is_not_empty\":\n return actual !== \"\";\n case \"greater_than\":\n return Number(actual) > Number(expected);\n case \"greater_or_equal\":\n return Number(actual) >= Number(expected);\n case \"less_than\":\n return Number(actual) < Number(expected);\n case \"less_or_equal\":\n return Number(actual) <= Number(expected);\n case \"between\": {\n const numeric = Number(actual);\n return numeric >= Number(expected) && numeric <= Number(expectedTo);\n }\n }\n}\n\nexport function layeredFilterRuleSummary(\n rule: LayeredFilterRule,\n fields: readonly LayeredFilterField[],\n): string {\n const field = fields.find((candidate) => candidate.id === rule.field);\n const fieldLabel = field?.label ?? rule.field;\n const operator = LAYERED_FILTER_OPERATOR_LABELS[rule.operator];\n if (!layeredFilterNeedsValue(rule.operator))\n return `${fieldLabel} ${operator}`;\n const selectedLabel =\n field?.kind === \"select\"\n ? field.options.find((option) => option.value === rule.value)?.label\n : undefined;\n const value = selectedLabel ?? rule.value;\n return rule.operator === \"between\"\n ? `${fieldLabel} ${operator} ${value} and ${rule.valueTo ?? \"\"}`\n : `${fieldLabel} ${operator} ${value}`;\n}\n","import type {\n ColumnFilterValue,\n ColumnFiltersState,\n MatrxColumnDef,\n SortState,\n TableSearchMatchMode,\n} from \"./types\";\nimport {\n completeLayeredFilterRules,\n layeredFilterMatchesValue,\n type LayeredFilterRule,\n} from \"./layered-filters\";\n\n/**\n * Sentinel select-filter values for \"no value\" / \"any value\" — every select\n * filter offers them automatically when the column has empty cells, so any\n * table can isolate rows missing a value (or having one) without extra config.\n */\nexport const SELECT_EMPTY_VALUE = \"__empty__\";\nexport const SELECT_NOT_EMPTY_VALUE = \"__not_empty__\";\n/** Exact SQL-style NULL selection, distinct from the empty-cell option. */\nexport const SELECT_NULL_VALUE = \"__null__\";\n\nexport function columnId<T>(col: MatrxColumnDef<T>): string {\n if (col.id) return col.id;\n if (col.accessorKey) return String(col.accessorKey);\n throw new Error(\"MatrxDataTable column requires `id` or `accessorKey`\");\n}\n\nexport function getCellValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n if (col.accessorFn) return col.accessorFn(row);\n if (col.accessorKey) {\n return (row as Record<string, unknown>)[col.accessorKey];\n }\n return undefined;\n}\n\nexport function getFilterValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n return col.filterValue ? col.filterValue(row) : getCellValue(row, col);\n}\n\nexport function getSortValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n return col.sortValue ? col.sortValue(row) : getCellValue(row, col);\n}\n\nexport function stringifyCellValue(value: unknown): string {\n if (value == null) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (value instanceof Date) return value.toISOString();\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** Unicode-aware tokenization shared by whole-word table search. */\nexport function tableSearchWords(value: string): string[] {\n return value\n .toLocaleLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean);\n}\n\n/**\n * Match the primary table search against one row's searchable text. In\n * whole-word mode every entered word must exist as a complete token, so\n * `are` matches `we are ready` but never `hardware`.\n */\nexport function matchesTableSearch(\n searchableText: string,\n query: string,\n mode: TableSearchMatchMode = \"contains\",\n): boolean {\n const normalizedQuery = query.trim().toLocaleLowerCase();\n if (!normalizedQuery) return true;\n if (mode === \"contains\") {\n return searchableText.toLocaleLowerCase().includes(normalizedQuery);\n }\n const actualWords = new Set(tableSearchWords(searchableText));\n const expectedWords = tableSearchWords(normalizedQuery);\n return (\n expectedWords.length > 0 &&\n expectedWords.every((word) => actualWords.has(word))\n );\n}\n\nfunction compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n return Number(a) - Number(b);\n }\n return stringifyCellValue(a).localeCompare(stringifyCellValue(b), undefined, {\n numeric: true,\n sensitivity: \"base\",\n });\n}\n\n/** Select filters treat array-valued cells as sets, never as serialized JSON choices. */\nexport function selectCellValues(value: unknown): string[] {\n return (Array.isArray(value) ? value : [value])\n .map(stringifyCellValue)\n .filter((item) => item !== \"\");\n}\n\nexport function passesColumnFilter(\n value: unknown,\n filter: ColumnFilterValue,\n): boolean {\n const matches = (() => {\n switch (filter.kind) {\n case \"text\": {\n const s = stringifyCellValue(value);\n if (filter.mode === \"null\") return value == null;\n if (filter.mode === \"not_null\") return value != null;\n if (filter.mode === \"empty\") return s.trim() === \"\";\n if (filter.mode === \"not_empty\") return s.trim() !== \"\";\n const q = filter.value.trim().toLowerCase();\n if (!q) return true;\n return s.toLowerCase().includes(q);\n }\n case \"select\": {\n // `values: []` is an explicit multi-select state: the user deselected\n // every option, so it must produce an empty result. Legacy single-value\n // filters and an absent `values` field retain their clear/all behavior.\n if (filter.values !== undefined && filter.values.length === 0) {\n return false;\n }\n const selected = filter.values ??\n (filter.value && filter.value !== \"__all__\" ? [filter.value] : []);\n if (selected.length === 0) return true;\n const values = selectCellValues(value);\n // OR semantics across the set; sentinels compose (\"A or (empty)\").\n return selected.some((v) =>\n v === SELECT_NULL_VALUE\n ? value == null\n : v === SELECT_EMPTY_VALUE\n ? values.length === 0\n : v === SELECT_NOT_EMPTY_VALUE\n ? values.length > 0\n : v === \"\"\n ? value === \"\" || (Array.isArray(value) && value.includes(\"\"))\n : values.includes(v),\n );\n }\n case \"boolean\": {\n return Boolean(value) === filter.value;\n }\n case \"number\": {\n // A missing cell is not zero. Without this guard, Number(\"\") made a\n // blank numeric value pass filters whose range included zero.\n const raw = stringifyCellValue(value).trim();\n if (raw === \"\") return false;\n const normalized = raw.replace(/[^0-9.-]/g, \"\");\n if (normalized === \"\") return false;\n const n = typeof value === \"number\"\n ? value\n : Number(normalized);\n if (!Number.isFinite(n)) return false;\n if (filter.min !== undefined && n < filter.min) return false;\n if (filter.max !== undefined && n > filter.max) return false;\n return true;\n }\n }\n })();\n return filter.negated ? !matches : matches;\n}\n\nexport function filterAndSortRows<T>(\n rows: T[],\n columns: MatrxColumnDef<T>[],\n columnFilters: ColumnFiltersState,\n sort: SortState | null,\n globalSearch: string,\n anyOf?: { columnIds: string[]; query: string },\n layeredFilters?: readonly LayeredFilterRule[],\n globalSearchMode: TableSearchMatchMode = \"contains\",\n searchText?: (row: T) => string,\n): T[] {\n const colById = new Map(columns.map((c) => [columnId(c), c]));\n const q = globalSearch.trim().toLowerCase();\n const anyQ = anyOf?.query.trim().toLowerCase() ?? \"\";\n const activeLayeredFilters = completeLayeredFilterRules(layeredFilters);\n\n let result = rows.filter((row) => {\n for (const [id, filter] of Object.entries(columnFilters)) {\n if (!filter) continue;\n const col = colById.get(id);\n if (!col || col.filter === false) continue;\n if (!passesColumnFilter(getFilterValue(row, col), filter)) return false;\n }\n\n for (const rule of activeLayeredFilters) {\n const col = colById.get(rule.field);\n if (!col || !layeredFilterMatchesValue(getFilterValue(row, col), rule)) {\n return false;\n }\n }\n\n if (anyQ && anyOf) {\n const hit = anyOf.columnIds.some((id) => {\n const col = colById.get(id);\n if (!col) return false;\n return stringifyCellValue(getFilterValue(row, col))\n .toLowerCase()\n .includes(anyQ);\n });\n if (!hit) return false;\n }\n\n if (!q) return true;\n const searchableValues = columns\n .filter(\n (col) =>\n col.filter !== false || Boolean(col.accessorKey || col.accessorFn),\n )\n .map((col) => stringifyCellValue(getFilterValue(row, col)));\n const additionalSearchText = searchText?.(row);\n if (additionalSearchText) searchableValues.push(additionalSearchText);\n if (globalSearchMode === \"contains\") {\n return searchableValues.some((value) =>\n matchesTableSearch(value, q, \"contains\"),\n );\n }\n return matchesTableSearch(searchableValues.join(\" \"), q, \"whole_words\");\n });\n\n if (sort) {\n const col = colById.get(sort.id);\n if (col && col.sortable !== false) {\n const dir = sort.direction === \"asc\" ? 1 : -1;\n result = [...result].sort((a, b) => {\n const va = getSortValue(a, col);\n const vb = getSortValue(b, col);\n // Empty cells (null / \"\") sort LAST in both directions — sorting a\n // column should surface its values, never a wall of blanks.\n const ea = va == null || stringifyCellValue(va) === \"\";\n const eb = vb == null || stringifyCellValue(vb) === \"\";\n if (ea !== eb) return ea ? 1 : -1;\n return compareValues(va, vb) * dir;\n });\n }\n }\n\n return result;\n}\n\nexport function countActiveColumnFilters(filters: ColumnFiltersState): number {\n let n = 0;\n for (const f of Object.values(filters)) {\n if (!f) continue;\n switch (f.kind) {\n case \"text\":\n if (f.value.trim() || (f.mode && f.mode !== \"contains\")) n += 1;\n break;\n case \"select\":\n if (f.values !== undefined || (f.value && f.value !== \"__all__\"))\n n += 1;\n break;\n case \"boolean\":\n n += 1;\n break;\n case \"number\":\n if (f.min !== undefined || f.max !== undefined) n += 1;\n break;\n }\n }\n return n;\n}\n\nexport function isColumnFilterActive(\n filter: ColumnFilterValue | undefined,\n): boolean {\n if (!filter) return false;\n switch (filter.kind) {\n case \"text\":\n return (\n filter.value.trim().length > 0 ||\n (filter.mode !== undefined && filter.mode !== \"contains\")\n );\n case \"select\":\n return filter.values !== undefined\n ? true\n : Boolean(filter.value) && filter.value !== \"__all__\";\n case \"boolean\":\n return true;\n case \"number\":\n return filter.min !== undefined || filter.max !== undefined;\n }\n}\n\n/** Apply draft edits onto a row for display (shallow field merge). */\nexport function applyRowEdits<T>(\n row: T,\n edits: Record<string, unknown> | undefined,\n): T {\n if (!edits || Object.keys(edits).length === 0) return row;\n return { ...row, ...edits };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/data-table/layered-filters.ts","../../src/data-table/date-filter.ts","../../src/data-table/filter-engine.ts"],"sourcesContent":["/**\n * Shared vocabulary for ordered, AND-combined table filters. The same rule\n * shape is URL-safe, can be evaluated by local tables, and can be handed to a\n * controlled table's server query without a surface inventing another query\n * builder.\n */\n\nimport { z } from \"zod\";\nimport type { ColumnFiltersState } from \"./types\";\n\nexport const LAYERED_FILTER_OPERATORS = [\n \"contains\",\n \"not_contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"word\",\n \"not_word\",\n \"is_empty\",\n \"is_not_empty\",\n \"greater_than\",\n \"greater_or_equal\",\n \"less_than\",\n \"less_or_equal\",\n \"between\",\n] as const;\n\nexport type LayeredFilterOperator = (typeof LAYERED_FILTER_OPERATORS)[number];\n\nexport interface LayeredFilterRule {\n id: string;\n field: string;\n operator: LayeredFilterOperator;\n value: string;\n valueTo?: string | undefined;\n}\n\nexport type LayeredFilterField =\n | {\n id: string;\n label: string;\n kind: \"text\";\n operators?: LayeredFilterOperator[];\n }\n | {\n id: string;\n label: string;\n kind: \"number\";\n operators?: LayeredFilterOperator[];\n placeholder?: string;\n }\n | {\n id: string;\n label: string;\n kind: \"select\";\n operators?: LayeredFilterOperator[];\n options: Array<{ value: string; label: string }>;\n };\n\nconst layeredFilterRuleSchema = z.object({\n id: z.string().min(1),\n field: z.string().min(1),\n operator: z.enum(LAYERED_FILTER_OPERATORS),\n value: z.string(),\n valueTo: z.string().optional(),\n});\n\nconst layeredFilterRulesSchema = z.array(layeredFilterRuleSchema).max(20);\n\nconst TEXT_OPERATORS: LayeredFilterOperator[] = [\n \"contains\",\n \"not_contains\",\n \"equals\",\n \"not_equals\",\n \"starts_with\",\n \"ends_with\",\n \"word\",\n \"not_word\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nconst NUMBER_OPERATORS: LayeredFilterOperator[] = [\n \"equals\",\n \"not_equals\",\n \"greater_than\",\n \"greater_or_equal\",\n \"less_than\",\n \"less_or_equal\",\n \"between\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nconst SELECT_OPERATORS: LayeredFilterOperator[] = [\n \"equals\",\n \"not_equals\",\n \"is_empty\",\n \"is_not_empty\",\n];\n\nexport const LAYERED_FILTER_OPERATOR_LABELS: Record<\n LayeredFilterOperator,\n string\n> = {\n contains: \"contains\",\n not_contains: \"doesn't contain\",\n equals: \"is\",\n not_equals: \"is not\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n word: \"has the word\",\n not_word: \"doesn't have the word\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n greater_than: \"is greater than\",\n greater_or_equal: \"is at least\",\n less_than: \"is less than\",\n less_or_equal: \"is at most\",\n between: \"is between\",\n};\n\nexport function operatorsForLayeredField(\n field: LayeredFilterField,\n): LayeredFilterOperator[] {\n if (field.operators) return field.operators;\n if (field.kind === \"number\") return NUMBER_OPERATORS;\n if (field.kind === \"select\") return SELECT_OPERATORS;\n return TEXT_OPERATORS;\n}\n\nexport function layeredFilterNeedsValue(\n operator: LayeredFilterOperator,\n): boolean {\n return operator !== \"is_empty\" && operator !== \"is_not_empty\";\n}\n\nexport function isCompleteLayeredFilterRule(rule: LayeredFilterRule): boolean {\n if (!layeredFilterNeedsValue(rule.operator)) return true;\n if (rule.value.trim() === \"\") return false;\n return rule.operator !== \"between\" || Boolean(rule.valueTo?.trim());\n}\n\nexport function completeLayeredFilterRules(\n rules: readonly LayeredFilterRule[] | undefined,\n): LayeredFilterRule[] {\n return (rules ?? []).filter(isCompleteLayeredFilterRule);\n}\n\nexport function isLayeredFilterOperator(\n value: string,\n): value is LayeredFilterOperator {\n return LAYERED_FILTER_OPERATORS.some((operator) => operator === value);\n}\n\n/** Decode URL-owned rules without trusting a hand-edited link. */\nexport function decodeLayeredFilterRules(\n raw: string | null,\n): LayeredFilterRule[] {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n const result = layeredFilterRulesSchema.safeParse(parsed);\n return result.success ? result.data : [];\n } catch {\n return [];\n }\n}\n\n/** Stable compact URL/wire form; rule order is preserved. */\nexport function encodeLayeredFilterRules(\n rules: readonly LayeredFilterRule[] | undefined,\n): string | null {\n return rules?.length ? JSON.stringify(rules) : null;\n}\n\n/**\n * Translate ordinary per-column controls into the same ordered rule language\n * used by the advanced builder. Controlled tables can send these rules to one\n * server evaluator instead of rebuilding numeric/text filter semantics.\n * Select filters are intentionally omitted because their multi-select control\n * is OR-combined and should stay in its native query parameter.\n */\nexport function columnFiltersToLayeredRules(\n filters: ColumnFiltersState,\n fieldIds: readonly string[],\n): LayeredFilterRule[] {\n const rules: LayeredFilterRule[] = [];\n for (const field of fieldIds) {\n const filter = filters[field];\n if (!filter) continue;\n\n if (filter.kind === \"text\") {\n rules.push({\n id: `column-${field}`,\n field,\n operator:\n filter.mode === \"empty\"\n ? \"is_empty\"\n : filter.mode === \"not_empty\"\n ? \"is_not_empty\"\n : \"contains\",\n value: filter.value,\n });\n continue;\n }\n\n if (filter.kind === \"number\") {\n if (filter.min !== undefined && filter.max !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"between\",\n value: String(filter.min),\n valueTo: String(filter.max),\n });\n } else if (filter.min !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"greater_or_equal\",\n value: String(filter.min),\n });\n } else if (filter.max !== undefined) {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"less_or_equal\",\n value: String(filter.max),\n });\n }\n continue;\n }\n\n if (filter.kind === \"boolean\") {\n rules.push({\n id: `column-${field}`,\n field,\n operator: \"equals\",\n value: String(filter.value),\n });\n }\n }\n return rules;\n}\n\nfunction normalizedText(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n return String(value).trim().toLocaleLowerCase();\n}\n\nfunction words(value: string): string[] {\n return value.split(/[^\\p{L}\\p{N}]+/u).filter(Boolean);\n}\n\n/** Local-table evaluator. Controlled tables send the same rule shape server-side. */\nexport function layeredFilterMatchesValue(\n value: unknown,\n rule: LayeredFilterRule,\n): boolean {\n const actual = normalizedText(value);\n const expected = rule.value.trim().toLocaleLowerCase();\n const expectedTo = rule.valueTo?.trim().toLocaleLowerCase() ?? \"\";\n\n switch (rule.operator) {\n case \"contains\":\n return actual.includes(expected);\n case \"not_contains\":\n return !actual.includes(expected);\n case \"equals\":\n return actual === expected;\n case \"not_equals\":\n return actual !== expected;\n case \"starts_with\":\n return actual.startsWith(expected);\n case \"ends_with\":\n return actual.endsWith(expected);\n case \"word\":\n return words(actual).includes(expected);\n case \"not_word\":\n return !words(actual).includes(expected);\n case \"is_empty\":\n return actual === \"\";\n case \"is_not_empty\":\n return actual !== \"\";\n case \"greater_than\":\n return Number(actual) > Number(expected);\n case \"greater_or_equal\":\n return Number(actual) >= Number(expected);\n case \"less_than\":\n return Number(actual) < Number(expected);\n case \"less_or_equal\":\n return Number(actual) <= Number(expected);\n case \"between\": {\n const numeric = Number(actual);\n return numeric >= Number(expected) && numeric <= Number(expectedTo);\n }\n }\n}\n\nexport function layeredFilterRuleSummary(\n rule: LayeredFilterRule,\n fields: readonly LayeredFilterField[],\n): string {\n const field = fields.find((candidate) => candidate.id === rule.field);\n const fieldLabel = field?.label ?? rule.field;\n const operator = LAYERED_FILTER_OPERATOR_LABELS[rule.operator];\n if (!layeredFilterNeedsValue(rule.operator))\n return `${fieldLabel} ${operator}`;\n const selectedLabel =\n field?.kind === \"select\"\n ? field.options.find((option) => option.value === rule.value)?.label\n : undefined;\n const value = selectedLabel ?? rule.value;\n return rule.operator === \"between\"\n ? `${fieldLabel} ${operator} ${value} and ${rule.valueTo ?? \"\"}`\n : `${fieldLabel} ${operator} ${value}`;\n}\n","/** Relative time ranges shared by every canonical table date column. */\nexport const TIME_RANGE_PRESET_VALUES = [\n \"all\", \"1m\", \"15m\", \"30m\", \"1h\", \"2h\", \"6h\", \"12h\",\n \"today\", \"yesterday\", \"this_week\", \"this_month\", \"this_year\",\n \"older_1m\", \"older_15m\", \"older_30m\", \"older_1h\", \"older_2h\", \"older_6h\", \"older_12h\",\n \"older_today\", \"older_this_week\", \"older_this_month\", \"older_this_year\",\n] as const;\n\nexport type TimeRangePreset = (typeof TIME_RANGE_PRESET_VALUES)[number];\n\nexport interface TimeRangePresetOption {\n value: TimeRangePreset;\n label: string;\n group: \"all\" | \"recent\" | \"older\" | \"calendar\";\n}\n\n/** A contiguous range: `since` is inclusive and `until` is exclusive. */\nexport interface DateFilterBounds {\n since?: string;\n until?: string;\n}\n\nexport interface DateColumnFilterValue extends DateFilterBounds {\n kind: \"date\";\n /** Date ranges are contiguous only; complement queries need a source contract first. */\n negated?: never;\n /** A relative range. Omit for explicit custom bounds. */\n preset?: TimeRangePreset;\n /** ISO instant captured when a relative preset was chosen. */\n anchor?: string;\n}\n\nexport const TIME_RANGE_PRESETS: readonly TimeRangePresetOption[] = [\n { value: \"all\", label: \"All time\", group: \"all\" },\n { value: \"1m\", label: \"Last minute\", group: \"recent\" },\n { value: \"15m\", label: \"Last 15 minutes\", group: \"recent\" },\n { value: \"30m\", label: \"Last 30 minutes\", group: \"recent\" },\n { value: \"1h\", label: \"Last hour\", group: \"recent\" },\n { value: \"2h\", label: \"Last 2 hours\", group: \"recent\" },\n { value: \"6h\", label: \"Last 6 hours\", group: \"recent\" },\n { value: \"12h\", label: \"Last 12 hours\", group: \"recent\" },\n { value: \"today\", label: \"Today\", group: \"calendar\" },\n { value: \"yesterday\", label: \"Yesterday\", group: \"calendar\" },\n { value: \"this_week\", label: \"This week\", group: \"calendar\" },\n { value: \"this_month\", label: \"This month\", group: \"calendar\" },\n { value: \"this_year\", label: \"This year\", group: \"calendar\" },\n { value: \"older_1m\", label: \"Older than 1 minute\", group: \"older\" },\n { value: \"older_15m\", label: \"Older than 15 minutes\", group: \"older\" },\n { value: \"older_30m\", label: \"Older than 30 minutes\", group: \"older\" },\n { value: \"older_1h\", label: \"Older than 1 hour\", group: \"older\" },\n { value: \"older_2h\", label: \"Older than 2 hours\", group: \"older\" },\n { value: \"older_6h\", label: \"Older than 6 hours\", group: \"older\" },\n { value: \"older_12h\", label: \"Older than 12 hours\", group: \"older\" },\n { value: \"older_today\", label: \"Before today\", group: \"older\" },\n { value: \"older_this_week\", label: \"Before this week\", group: \"older\" },\n { value: \"older_this_month\", label: \"Before this month\", group: \"older\" },\n { value: \"older_this_year\", label: \"Before this year\", group: \"older\" },\n];\n\nfunction startOfDay(date: Date): Date {\n const next = new Date(date);\n next.setHours(0, 0, 0, 0);\n return next;\n}\n\nfunction startOfWeek(date: Date): Date {\n const next = startOfDay(date);\n next.setDate(next.getDate() - (next.getDay() === 0 ? 6 : next.getDay() - 1));\n return next;\n}\n\nfunction startOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nfunction startOfYear(date: Date): Date {\n return new Date(date.getFullYear(), 0, 1);\n}\n\nfunction validDate(value: Date | string | undefined): Date | undefined {\n if (value === undefined) return undefined;\n const date = value instanceof Date ? new Date(value) : new Date(value);\n return Number.isNaN(date.valueOf()) ? undefined : date;\n}\n\n/**\n * Resolve a date filter without reading the clock implicitly. Relative presets\n * use their captured `anchor`; callers may provide `now` only for legacy or\n * programmatic values without one. `until` remains exclusive throughout.\n */\nexport function dateFilterBounds(\n filter: DateColumnFilterValue,\n now: Date | string = new Date(),\n): DateFilterBounds {\n if (!filter.preset) {\n return {\n ...(filter.since === undefined ? {} : { since: filter.since }),\n ...(filter.until === undefined ? {} : { until: filter.until }),\n };\n }\n if (filter.preset === \"all\") return {};\n\n const anchor = validDate(filter.anchor) ?? validDate(now) ?? new Date();\n const ago = (milliseconds: number) =>\n new Date(anchor.valueOf() - milliseconds).toISOString();\n const recent: Partial<Record<TimeRangePreset, number>> = {\n \"1m\": 60_000,\n \"15m\": 15 * 60_000,\n \"30m\": 30 * 60_000,\n \"1h\": 60 * 60_000,\n \"2h\": 2 * 60 * 60_000,\n \"6h\": 6 * 60 * 60_000,\n \"12h\": 12 * 60 * 60_000,\n };\n const duration = recent[filter.preset.replace(\"older_\", \"\") as TimeRangePreset];\n if (duration !== undefined) {\n return filter.preset.startsWith(\"older_\") ? { until: ago(duration) } : { since: ago(duration) };\n }\n\n const starts: Partial<Record<TimeRangePreset, Date>> = {\n today: startOfDay(anchor),\n this_week: startOfWeek(anchor),\n this_month: startOfMonth(anchor),\n this_year: startOfYear(anchor),\n older_today: startOfDay(anchor),\n older_this_week: startOfWeek(anchor),\n older_this_month: startOfMonth(anchor),\n older_this_year: startOfYear(anchor),\n };\n if (filter.preset === \"yesterday\") {\n const until = startOfDay(anchor);\n const since = new Date(until);\n since.setDate(since.getDate() - 1);\n return { since: since.toISOString(), until: until.toISOString() };\n }\n const start = starts[filter.preset];\n if (!start) return {};\n return filter.preset.startsWith(\"older_\")\n ? { until: start.toISOString() }\n : { since: start.toISOString() };\n}\n","import type {\n ColumnFilterValue,\n ColumnFiltersState,\n MatrxColumnDef,\n SortState,\n TableSearchMatchMode,\n} from \"./types\";\nimport {\n completeLayeredFilterRules,\n layeredFilterMatchesValue,\n type LayeredFilterRule,\n} from \"./layered-filters\";\nimport { dateFilterBounds } from \"./date-filter\";\n\n/**\n * Sentinel select-filter values for \"no value\" / \"any value\" — every select\n * filter offers them automatically when the column has empty cells, so any\n * table can isolate rows missing a value (or having one) without extra config.\n */\nexport const SELECT_EMPTY_VALUE = \"__empty__\";\nexport const SELECT_NOT_EMPTY_VALUE = \"__not_empty__\";\n/** Exact SQL-style NULL selection, distinct from the empty-cell option. */\nexport const SELECT_NULL_VALUE = \"__null__\";\n\nexport function columnId<T>(col: MatrxColumnDef<T>): string {\n if (col.id) return col.id;\n if (col.accessorKey) return String(col.accessorKey);\n throw new Error(\"MatrxDataTable column requires `id` or `accessorKey`\");\n}\n\nexport function getCellValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n if (col.accessorFn) return col.accessorFn(row);\n if (col.accessorKey) {\n return (row as Record<string, unknown>)[col.accessorKey];\n }\n return undefined;\n}\n\nexport function getFilterValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n return col.filterValue ? col.filterValue(row) : getCellValue(row, col);\n}\n\nexport function getSortValue<T>(row: T, col: MatrxColumnDef<T>): unknown {\n return col.sortValue ? col.sortValue(row) : getCellValue(row, col);\n}\n\nexport function stringifyCellValue(value: unknown): string {\n if (value == null) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (value instanceof Date) return value.toISOString();\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** Unicode-aware tokenization shared by whole-word table search. */\nexport function tableSearchWords(value: string): string[] {\n return value\n .toLocaleLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean);\n}\n\n/**\n * Match the primary table search against one row's searchable text. In\n * whole-word mode every entered word must exist as a complete token, so\n * `are` matches `we are ready` but never `hardware`.\n */\nexport function matchesTableSearch(\n searchableText: string,\n query: string,\n mode: TableSearchMatchMode = \"contains\",\n): boolean {\n const normalizedQuery = query.trim().toLocaleLowerCase();\n if (!normalizedQuery) return true;\n if (mode === \"contains\") {\n return searchableText.toLocaleLowerCase().includes(normalizedQuery);\n }\n const actualWords = new Set(tableSearchWords(searchableText));\n const expectedWords = tableSearchWords(normalizedQuery);\n return (\n expectedWords.length > 0 &&\n expectedWords.every((word) => actualWords.has(word))\n );\n}\n\nfunction compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n return Number(a) - Number(b);\n }\n return stringifyCellValue(a).localeCompare(stringifyCellValue(b), undefined, {\n numeric: true,\n sensitivity: \"base\",\n });\n}\n\n/** Select filters treat array-valued cells as sets, never as serialized JSON choices. */\nexport function selectCellValues(value: unknown): string[] {\n return (Array.isArray(value) ? value : [value])\n .map(stringifyCellValue)\n .filter((item) => item !== \"\");\n}\n\nexport function passesColumnFilter(\n value: unknown,\n filter: ColumnFilterValue,\n): boolean {\n const matches = (() => {\n switch (filter.kind) {\n case \"text\": {\n const s = stringifyCellValue(value);\n if (filter.mode === \"null\") return value == null;\n if (filter.mode === \"not_null\") return value != null;\n if (filter.mode === \"empty\") return s.trim() === \"\";\n if (filter.mode === \"not_empty\") return s.trim() !== \"\";\n const q = filter.value.trim().toLowerCase();\n if (!q) return true;\n return s.toLowerCase().includes(q);\n }\n case \"select\": {\n // `values: []` is an explicit multi-select state: the user deselected\n // every option, so it must produce an empty result. Legacy single-value\n // filters and an absent `values` field retain their clear/all behavior.\n if (filter.values !== undefined && filter.values.length === 0) {\n return false;\n }\n const selected = filter.values ??\n (filter.value && filter.value !== \"__all__\" ? [filter.value] : []);\n if (selected.length === 0) return true;\n const values = selectCellValues(value);\n // OR semantics across the set; sentinels compose (\"A or (empty)\").\n return selected.some((v) =>\n v === SELECT_NULL_VALUE\n ? value == null\n : v === SELECT_EMPTY_VALUE\n ? values.length === 0\n : v === SELECT_NOT_EMPTY_VALUE\n ? values.length > 0\n : v === \"\"\n ? value === \"\" || (Array.isArray(value) && value.includes(\"\"))\n : values.includes(v),\n );\n }\n case \"boolean\": {\n return Boolean(value) === filter.value;\n }\n case \"number\": {\n // A missing cell is not zero. Without this guard, Number(\"\") made a\n // blank numeric value pass filters whose range included zero.\n const raw = stringifyCellValue(value).trim();\n if (raw === \"\") return false;\n const normalized = raw.replace(/[^0-9.-]/g, \"\");\n if (normalized === \"\") return false;\n const n = typeof value === \"number\"\n ? value\n : Number(normalized);\n if (!Number.isFinite(n)) return false;\n if (filter.min !== undefined && n < filter.min) return false;\n if (filter.max !== undefined && n > filter.max) return false;\n return true;\n }\n case \"date\": {\n const raw = value instanceof Date ? value : new Date(stringifyCellValue(value));\n if (Number.isNaN(raw.valueOf())) return false;\n const { since, until } = dateFilterBounds(filter);\n const timestamp = raw.valueOf();\n if (since !== undefined) {\n const sinceTimestamp = new Date(since).valueOf();\n if (Number.isNaN(sinceTimestamp) || timestamp < sinceTimestamp) return false;\n }\n if (until !== undefined) {\n const untilTimestamp = new Date(until).valueOf();\n if (Number.isNaN(untilTimestamp) || timestamp >= untilTimestamp) return false;\n }\n return true;\n }\n }\n })();\n return filter.negated ? !matches : matches;\n}\n\nexport function filterAndSortRows<T>(\n rows: T[],\n columns: MatrxColumnDef<T>[],\n columnFilters: ColumnFiltersState,\n sort: SortState | null,\n globalSearch: string,\n anyOf?: { columnIds: string[]; query: string },\n layeredFilters?: readonly LayeredFilterRule[],\n globalSearchMode: TableSearchMatchMode = \"contains\",\n searchText?: (row: T) => string,\n): T[] {\n const colById = new Map(columns.map((c) => [columnId(c), c]));\n const q = globalSearch.trim().toLowerCase();\n const anyQ = anyOf?.query.trim().toLowerCase() ?? \"\";\n const activeLayeredFilters = completeLayeredFilterRules(layeredFilters);\n\n let result = rows.filter((row) => {\n for (const [id, filter] of Object.entries(columnFilters)) {\n if (!filter) continue;\n const col = colById.get(id);\n if (!col || col.filter === false) continue;\n if (!passesColumnFilter(getFilterValue(row, col), filter)) return false;\n }\n\n for (const rule of activeLayeredFilters) {\n const col = colById.get(rule.field);\n if (!col || !layeredFilterMatchesValue(getFilterValue(row, col), rule)) {\n return false;\n }\n }\n\n if (anyQ && anyOf) {\n const hit = anyOf.columnIds.some((id) => {\n const col = colById.get(id);\n if (!col) return false;\n return stringifyCellValue(getFilterValue(row, col))\n .toLowerCase()\n .includes(anyQ);\n });\n if (!hit) return false;\n }\n\n if (!q) return true;\n const searchableValues = columns\n .filter(\n (col) =>\n col.filter !== false || Boolean(col.accessorKey || col.accessorFn),\n )\n .map((col) => stringifyCellValue(getFilterValue(row, col)));\n const additionalSearchText = searchText?.(row);\n if (additionalSearchText) searchableValues.push(additionalSearchText);\n if (globalSearchMode === \"contains\") {\n return searchableValues.some((value) =>\n matchesTableSearch(value, q, \"contains\"),\n );\n }\n return matchesTableSearch(searchableValues.join(\" \"), q, \"whole_words\");\n });\n\n if (sort) {\n const col = colById.get(sort.id);\n if (col && col.sortable !== false) {\n const dir = sort.direction === \"asc\" ? 1 : -1;\n result = [...result].sort((a, b) => {\n const va = getSortValue(a, col);\n const vb = getSortValue(b, col);\n // Empty cells (null / \"\") sort LAST in both directions — sorting a\n // column should surface its values, never a wall of blanks.\n const ea = va == null || stringifyCellValue(va) === \"\";\n const eb = vb == null || stringifyCellValue(vb) === \"\";\n if (ea !== eb) return ea ? 1 : -1;\n return compareValues(va, vb) * dir;\n });\n }\n }\n\n return result;\n}\n\nexport function countActiveColumnFilters(filters: ColumnFiltersState): number {\n let n = 0;\n for (const f of Object.values(filters)) {\n if (!f) continue;\n switch (f.kind) {\n case \"text\":\n if (f.value.trim() || (f.mode && f.mode !== \"contains\")) n += 1;\n break;\n case \"select\":\n if (f.values !== undefined || (f.value && f.value !== \"__all__\"))\n n += 1;\n break;\n case \"boolean\":\n n += 1;\n break;\n case \"number\":\n if (f.min !== undefined || f.max !== undefined) n += 1;\n break;\n case \"date\":\n if (isColumnFilterActive(f)) n += 1;\n break;\n }\n }\n return n;\n}\n\nexport function isColumnFilterActive(\n filter: ColumnFilterValue | undefined,\n): boolean {\n if (!filter) return false;\n switch (filter.kind) {\n case \"text\":\n return (\n filter.value.trim().length > 0 ||\n (filter.mode !== undefined && filter.mode !== \"contains\")\n );\n case \"select\":\n return filter.values !== undefined\n ? true\n : Boolean(filter.value) && filter.value !== \"__all__\";\n case \"boolean\":\n return true;\n case \"number\":\n return filter.min !== undefined || filter.max !== undefined;\n case \"date\": {\n const bounds = dateFilterBounds(filter);\n return bounds.since !== undefined || bounds.until !== undefined;\n }\n }\n}\n\n/** Apply draft edits onto a row for display (shallow field merge). */\nexport function applyRowEdits<T>(\n row: T,\n edits: Record<string, unknown> | undefined,\n): T {\n if (!edits || Object.keys(edits).length === 0) return row;\n return { ...row, ...edits };\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (rowId: string) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultRowContext?: (row: unknown, controls: import(\"./types\").MatrxDataTableRecordControls) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAoH;AAgCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,UAAM,4BAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,4CAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,aAAO,yBAAW,WAAW;AAAG;AAa9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,UAAM,4BAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,4CAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,aAAO,yBAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,UAAM,4BAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,4CAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,aAAO,yBAAW,kBAAkB;AAAG;","names":[]}
1
+ {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\nimport type { MatrxTableMenuPayload, MatrxTableMenuTarget } from \"./menu-targets\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\n/**\n * The host's door onto the table's right-click levels.\n *\n * A canonical table registers ONE resolver per instance. The host's own menu\n * reads which of the four levels was clicked (`readMenuTarget`) and asks for\n * that level's descriptor — the package never interprets what comes back, and\n * the host never reaches into the table for the row or the range.\n */\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAoH;AAyCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,UAAM,4BAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,4CAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,aAAO,yBAAW,WAAW;AAAG;AAa9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,UAAM,4BAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,4CAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,aAAO,yBAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,UAAM,4BAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,4CAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,aAAO,yBAAW,kBAAkB;AAAG;","names":[]}
@@ -1,16 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
- import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-CmQrOz-T.cjs';
4
3
  import { CopyControlProps } from './copy-types.cjs';
5
4
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.cjs';
5
+ import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-jQddSUnj.cjs';
6
+ import { MatrxTableMenuTarget, MatrxTableMenuPayload } from './menu-targets.cjs';
6
7
  import '../content-transfer.cjs';
7
8
  import '@ai-matrx/kit/content-transfer';
8
9
  import '../content-transfer/icon.cjs';
9
10
  import '../types-CJWU1Gae.cjs';
10
11
  import './grouping.cjs';
11
12
  import './fill.cjs';
13
+ import './facets.cjs';
12
14
  import './spreadsheet.cjs';
13
15
  import './grid-selection.cjs';
16
+ import './date-filter.cjs';
14
17
 
15
18
  interface TableLinkProps {
16
19
  href: string;
@@ -74,8 +77,16 @@ interface TableDoors {
74
77
  peekKind?: string;
75
78
  canPeek?: boolean;
76
79
  }
80
+ /**
81
+ * The host's door onto the table's right-click levels.
82
+ *
83
+ * A canonical table registers ONE resolver per instance. The host's own menu
84
+ * reads which of the four levels was clicked (`readMenuTarget`) and asks for
85
+ * that level's descriptor — the package never interprets what comes back, and
86
+ * the host never reaches into the table for the row or the range.
87
+ */
77
88
  interface TableRowContextRegistry {
78
- register(tableId: string, resolve: (rowId: string) => unknown): () => void;
89
+ register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void;
79
90
  }
80
91
  interface TableContextMenuBoundaryProps {
81
92
  label: string;
@@ -95,7 +106,7 @@ interface MatrxDataTableHost {
95
106
  ResourcePeek?: ComponentType<TablePeekProps>;
96
107
  SavedViews?: ComponentType<TableSavedViewsProps>;
97
108
  rowContextRegistry?: TableRowContextRegistry;
98
- createDefaultRowContext?: (row: unknown, controls: MatrxDataTableRecordControls) => unknown;
109
+ createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown;
99
110
  ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */
100
111
  defaultDensity?: MatrxDataTableDensity;
101
112
  notify?: {
@@ -1,16 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
- import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-nlLCMiqd.js';
4
3
  import { CopyControlProps } from './copy-types.js';
5
4
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.js';
5
+ import { b as TableSavedViewsProps, c as MatrxDataTableDensity, d as MatrxDataTableRecordControls } from '../types-D9JBR6ZU.js';
6
+ import { MatrxTableMenuTarget, MatrxTableMenuPayload } from './menu-targets.js';
6
7
  import '../content-transfer.js';
7
8
  import '@ai-matrx/kit/content-transfer';
8
9
  import '../content-transfer/icon.js';
9
10
  import '../types-CJWU1Gae.js';
10
11
  import './grouping.js';
11
12
  import './fill.js';
13
+ import './facets.js';
12
14
  import './spreadsheet.js';
13
15
  import './grid-selection.js';
16
+ import './date-filter.js';
14
17
 
15
18
  interface TableLinkProps {
16
19
  href: string;
@@ -74,8 +77,16 @@ interface TableDoors {
74
77
  peekKind?: string;
75
78
  canPeek?: boolean;
76
79
  }
80
+ /**
81
+ * The host's door onto the table's right-click levels.
82
+ *
83
+ * A canonical table registers ONE resolver per instance. The host's own menu
84
+ * reads which of the four levels was clicked (`readMenuTarget`) and asks for
85
+ * that level's descriptor — the package never interprets what comes back, and
86
+ * the host never reaches into the table for the row or the range.
87
+ */
77
88
  interface TableRowContextRegistry {
78
- register(tableId: string, resolve: (rowId: string) => unknown): () => void;
89
+ register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void;
79
90
  }
80
91
  interface TableContextMenuBoundaryProps {
81
92
  label: string;
@@ -95,7 +106,7 @@ interface MatrxDataTableHost {
95
106
  ResourcePeek?: ComponentType<TablePeekProps>;
96
107
  SavedViews?: ComponentType<TableSavedViewsProps>;
97
108
  rowContextRegistry?: TableRowContextRegistry;
98
- createDefaultRowContext?: (row: unknown, controls: MatrxDataTableRecordControls) => unknown;
109
+ createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown;
99
110
  ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */
100
111
  defaultDensity?: MatrxDataTableDensity;
101
112
  notify?: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (rowId: string) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultRowContext?: (row: unknown, controls: import(\"./types\").MatrxDataTableRecordControls) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;AACA,SAAS,eAAe,kBAA4F;AAgCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,MAAM,cAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,SAAO,WAAW,WAAW;AAAG;AAa9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,MAAM,cAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,SAAO,WAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,MAAM,cAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,SAAO,WAAW,kBAAkB;AAAG;","names":[]}
1
+ {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\nimport type { MatrxTableMenuPayload, MatrxTableMenuTarget } from \"./menu-targets\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\n/**\n * The host's door onto the table's right-click levels.\n *\n * A canonical table registers ONE resolver per instance. The host's own menu\n * reads which of the four levels was clicked (`readMenuTarget`) and asks for\n * that level's descriptor — the package never interprets what comes back, and\n * the host never reaches into the table for the row or the range.\n */\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;AACA,SAAS,eAAe,kBAA4F;AAyCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,MAAM,cAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,SAAO,WAAW,WAAW;AAAG;AAa9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,MAAM,cAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,SAAO,WAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,MAAM,cAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,SAAO,WAAW,kBAAkB;AAAG;","names":[]}