@lattice-php/lattice 0.10.0 → 0.11.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 (79) hide show
  1. package/dist/action/components/action-form.js +1 -1
  2. package/dist/action/components/action-form.js.map +1 -1
  3. package/dist/chat/components/chat-box.js +1 -1
  4. package/dist/chat/components/chat-box.js.map +1 -1
  5. package/dist/chat/components/prompt-input.js +2 -2
  6. package/dist/chat/components/prompt-input.js.map +1 -1
  7. package/dist/core/components/combobox.js +1 -1
  8. package/dist/core/components/combobox.js.map +1 -1
  9. package/dist/core/components/info-tooltip.js +1 -1
  10. package/dist/core/components/info-tooltip.js.map +1 -1
  11. package/dist/core/components/spinner.js +1 -1
  12. package/dist/core/components/spinner.js.map +1 -1
  13. package/dist/core/components/tabs.js +1 -1
  14. package/dist/core/components/tabs.js.map +1 -1
  15. package/dist/form/components/fields/date-input.js +7 -6
  16. package/dist/form/components/fields/date-input.js.map +1 -1
  17. package/dist/form/components/fields/date-picker-control.d.ts +18 -0
  18. package/dist/form/components/fields/date-picker-control.js +199 -0
  19. package/dist/form/components/fields/date-picker-control.js.map +1 -0
  20. package/dist/form/components/fields/date-picker-value.d.ts +10 -0
  21. package/dist/form/components/fields/date-picker-value.js +125 -0
  22. package/dist/form/components/fields/date-picker-value.js.map +1 -0
  23. package/dist/form/components/fields/date-time-input.d.ts +2 -0
  24. package/dist/form/components/fields/date-time-input.js +34 -0
  25. package/dist/form/components/fields/date-time-input.js.map +1 -0
  26. package/dist/form/components/fields/file-upload.js +3 -3
  27. package/dist/form/components/fields/file-upload.js.map +1 -1
  28. package/dist/form/components/fields/lazy-date-picker-control.d.ts +2 -0
  29. package/dist/form/components/fields/lazy-date-picker-control.js +17 -0
  30. package/dist/form/components/fields/lazy-date-picker-control.js.map +1 -0
  31. package/dist/form/components/fields/number-input.js +1 -1
  32. package/dist/form/components/fields/rich-editor.js +3 -3
  33. package/dist/form/components/fields/rich-editor.js.map +1 -1
  34. package/dist/form/components/fields/row-action-menu.js +2 -2
  35. package/dist/form/components/fields/row-action-menu.js.map +1 -1
  36. package/dist/form/components/fields/select.js +1 -1
  37. package/dist/form/components/fields/select.js.map +1 -1
  38. package/dist/form/components/fields/table-rows.js +2 -2
  39. package/dist/form/components/fields/table-rows.js.map +1 -1
  40. package/dist/form/components/fields/text-input.js +1 -1
  41. package/dist/form/components/fields/time-input.d.ts +2 -0
  42. package/dist/form/components/fields/time-input.js +30 -0
  43. package/dist/form/components/fields/time-input.js.map +1 -0
  44. package/dist/form/components/index.d.ts +2 -0
  45. package/dist/form/components/index.js +3 -1
  46. package/dist/form/components/types.d.ts +1 -1
  47. package/dist/form/components/use-controlled-field.d.ts +2 -0
  48. package/dist/form/components/use-controlled-field.js +6 -2
  49. package/dist/form/components/use-controlled-field.js.map +1 -1
  50. package/dist/form/index.js +2 -0
  51. package/dist/form/index.js.map +1 -1
  52. package/dist/layout/callouts.js +1 -1
  53. package/dist/layout/callouts.js.map +1 -1
  54. package/dist/remote/components/data-list.js +3 -3
  55. package/dist/remote/components/data-list.js.map +1 -1
  56. package/dist/table/components/bulk-bar.js +2 -2
  57. package/dist/table/components/bulk-bar.js.map +1 -1
  58. package/dist/table/components/column-filter-control.js +5 -5
  59. package/dist/table/components/column-filter-control.js.map +1 -1
  60. package/dist/table/components/filter-bar.js +3 -3
  61. package/dist/table/components/filter-bar.js.map +1 -1
  62. package/dist/table/components/filter-controls.js +9 -9
  63. package/dist/table/components/filter-controls.js.map +1 -1
  64. package/dist/table/components/filter-stack-bar.js +1 -1
  65. package/dist/table/components/filter-stack-bar.js.map +1 -1
  66. package/dist/table/components/filter-value-input.js +5 -5
  67. package/dist/table/components/filter-value-input.js.map +1 -1
  68. package/dist/table/components/pagination.js +8 -8
  69. package/dist/table/components/pagination.js.map +1 -1
  70. package/dist/table/components/table.js +4 -4
  71. package/dist/table/components/table.js.map +1 -1
  72. package/dist/table/query.js +1 -1
  73. package/dist/table/query.js.map +1 -1
  74. package/dist/toast/toaster.js +1 -1
  75. package/dist/toast/toaster.js.map +1 -1
  76. package/dist/types/generated.d.ts +67 -1
  77. package/package.json +4 -1
  78. package/resources/icons/calendar.svg +18 -0
  79. package/resources/icons/chevron-left.svg +15 -0
@@ -1 +1 @@
1
- {"version":3,"file":"filter-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/lattice/core/components/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, isActiveFilterValue, stringProp } from \"../filter-values\";\nimport { TableFilterControl } from \"./filter-controls\";\n\nexport function FilterBar({\n filters,\n values,\n processing,\n hasActiveFilters,\n onChange,\n onReset,\n}: {\n filters: FilterData[];\n values: Record<string, unknown>;\n processing: boolean;\n hasActiveFilters: boolean;\n onChange: (key: string, value: unknown) => void;\n onReset: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const active = filters.filter((filter) => isActiveFilterValue(values[filter.key]));\n\n if (!hasActiveFilters) {\n return null;\n }\n\n return (\n <div className=\"border-b border-lt-border px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n {active.map((filter) => (\n <span\n key={filter.key}\n className=\"inline-flex items-center gap-1.5 rounded-lt-sm bg-lt-muted px-2 py-1\"\n >\n <span>\n {`${filter.label}: `}\n <span className=\"font-semibold\">{displayValue(filter, values[filter.key])}</span>\n </span>\n <button\n type=\"button\"\n data-test={`table-filter-chip-${filter.key}-remove`}\n className=\"inline-flex size-5 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-border disabled:opacity-50\"\n disabled={processing}\n aria-label={t(\"filter.remove\", \"Remove {{label}} filter\", {\n label: filter.label,\n })}\n onClick={() => onChange(filter.key, undefined)}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n ))}\n <button\n type=\"button\"\n data-test=\"table-filters-reset\"\n className=\"text-lt-muted-fg underline-offset-2 hover:underline disabled:opacity-50\"\n disabled={processing}\n onClick={onReset}\n >\n {t(\"filter.resetAll\", \"Reset all\")}\n </button>\n </div>\n </div>\n );\n}\n\nexport function FilterMenu({\n filters,\n values,\n processing,\n onChange,\n onSearch,\n}: {\n filters: FilterData[];\n values: Record<string, unknown>;\n processing: boolean;\n onChange: (key: string, value: unknown) => void;\n onSearch?: (filterKey: string, query: string) => Promise<Option[]>;\n}) {\n const { t } = useT(\"lattice\");\n const active = filters.filter((filter) => isActiveFilterValue(values[filter.key]));\n const filtersLabel = t(\"filter.filters\", \"Filters\");\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={filtersLabel}\n data-test=\"table-filters-menu\"\n className=\"relative inline-flex size-7 shrink-0 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted hover:text-lt-fg disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-lt-ring/50 data-[state=open]:bg-lt-muted data-[state=open]:text-lt-fg\"\n disabled={processing}\n >\n <Icon name=\"filter\" aria-hidden=\"true\" className=\"size-lt-icon-md\" />\n {active.length > 0 && (\n <span className=\"absolute -right-1 -top-1 inline-flex size-3.5 items-center justify-center rounded-full bg-lt-primary text-[10px] font-medium leading-none text-lt-primary-fg\">\n {active.length}\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 p-4\">\n <div className=\"grid gap-3\">\n {filters.map((filter) => (\n <div key={filter.key} className=\"grid gap-1\">\n {filter.type !== \"toggle\" && (\n <span className=\"text-xs font-medium text-lt-muted-fg\">{filter.label}</span>\n )}\n <TableFilterControl\n filter={filter}\n value={values[filter.key]}\n processing={processing}\n onChange={(value) => onChange(filter.key, value)}\n onSearch={onSearch ? (query) => onSearch(filter.key, query) : undefined}\n />\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction optionLabel(filter: FilterData, value: string): string {\n return filterOptions(filter).find((option) => option.value === value)?.label ?? value;\n}\n\nfunction displayValue(filter: FilterData, value: unknown): string {\n if (filter.type === \"select\") {\n if (Array.isArray(value)) {\n return value.map((item) => optionLabel(filter, String(item))).join(\", \");\n }\n\n return optionLabel(filter, String(value));\n }\n\n if (filter.type === \"ternary\") {\n return value === \"true\"\n ? stringProp(filter, \"trueLabel\", \"True\")\n : stringProp(filter, \"falseLabel\", \"False\");\n }\n\n if (filter.type === \"date-range\" && value && typeof value === \"object\") {\n const range = value as { from?: string; until?: string };\n\n return [range.from, range.until].filter((part) => part).join(\" – \");\n }\n\n return String(value);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/lattice/core/components/popover\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, isActiveFilterValue, stringProp } from \"../filter-values\";\nimport { TableFilterControl } from \"./filter-controls\";\n\nexport function FilterBar({\n filters,\n values,\n processing,\n hasActiveFilters,\n onChange,\n onReset,\n}: {\n filters: FilterData[];\n values: Record<string, unknown>;\n processing: boolean;\n hasActiveFilters: boolean;\n onChange: (key: string, value: unknown) => void;\n onReset: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const active = filters.filter((filter) => isActiveFilterValue(values[filter.key]));\n\n if (!hasActiveFilters) {\n return null;\n }\n\n return (\n <div className=\"border-b border-lt-border px-4 py-3\">\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n {active.map((filter) => (\n <span\n key={filter.key}\n className=\"inline-flex items-center gap-1.5 rounded-lt-sm bg-lt-muted px-2 py-1\"\n >\n <span>\n {`${filter.label}: `}\n <span className=\"font-semibold\">{displayValue(filter, values[filter.key])}</span>\n </span>\n <button\n type=\"button\"\n data-test={`table-filter-chip-${filter.key}-remove`}\n className=\"inline-flex size-5 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-border disabled:opacity-50\"\n disabled={processing}\n aria-label={t(\"table.filter.remove\", \"Remove {{label}} filter\", {\n label: filter.label,\n })}\n onClick={() => onChange(filter.key, undefined)}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n ))}\n <button\n type=\"button\"\n data-test=\"table-filters-reset\"\n className=\"text-lt-muted-fg underline-offset-2 hover:underline disabled:opacity-50\"\n disabled={processing}\n onClick={onReset}\n >\n {t(\"table.filter.resetAll\", \"Reset all\")}\n </button>\n </div>\n </div>\n );\n}\n\nexport function FilterMenu({\n filters,\n values,\n processing,\n onChange,\n onSearch,\n}: {\n filters: FilterData[];\n values: Record<string, unknown>;\n processing: boolean;\n onChange: (key: string, value: unknown) => void;\n onSearch?: (filterKey: string, query: string) => Promise<Option[]>;\n}) {\n const { t } = useT(\"lattice\");\n const active = filters.filter((filter) => isActiveFilterValue(values[filter.key]));\n const filtersLabel = t(\"table.filter.filters\", \"Filters\");\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={filtersLabel}\n data-test=\"table-filters-menu\"\n className=\"relative inline-flex size-7 shrink-0 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted hover:text-lt-fg disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-lt-ring/50 data-[state=open]:bg-lt-muted data-[state=open]:text-lt-fg\"\n disabled={processing}\n >\n <Icon name=\"filter\" aria-hidden=\"true\" className=\"size-lt-icon-md\" />\n {active.length > 0 && (\n <span className=\"absolute -right-1 -top-1 inline-flex size-3.5 items-center justify-center rounded-full bg-lt-primary text-[10px] font-medium leading-none text-lt-primary-fg\">\n {active.length}\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 p-4\">\n <div className=\"grid gap-3\">\n {filters.map((filter) => (\n <div key={filter.key} className=\"grid gap-1\">\n {filter.type !== \"toggle\" && (\n <span className=\"text-xs font-medium text-lt-muted-fg\">{filter.label}</span>\n )}\n <TableFilterControl\n filter={filter}\n value={values[filter.key]}\n processing={processing}\n onChange={(value) => onChange(filter.key, value)}\n onSearch={onSearch ? (query) => onSearch(filter.key, query) : undefined}\n />\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction optionLabel(filter: FilterData, value: string): string {\n return filterOptions(filter).find((option) => option.value === value)?.label ?? value;\n}\n\nfunction displayValue(filter: FilterData, value: unknown): string {\n if (filter.type === \"select\") {\n if (Array.isArray(value)) {\n return value.map((item) => optionLabel(filter, String(item))).join(\", \");\n }\n\n return optionLabel(filter, String(value));\n }\n\n if (filter.type === \"ternary\") {\n return value === \"true\"\n ? stringProp(filter, \"trueLabel\", \"True\")\n : stringProp(filter, \"falseLabel\", \"False\");\n }\n\n if (filter.type === \"date-range\" && value && typeof value === \"object\") {\n const range = value as { from?: string; until?: string };\n\n return [range.from, range.until].filter((part) => part).join(\" – \");\n }\n\n return String(value);\n}\n"],"mappings":"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"}
@@ -57,7 +57,7 @@ function TableFilterControl({ filter, value, processing, onChange, onSearch }) {
57
57
  }
58
58
  function SelectControl({ filter, value, processing, onChange }) {
59
59
  const { t } = useT("lattice");
60
- const placeholder = stringProp(filter, "placeholder", t("filter.all", "All"));
60
+ const placeholder = stringProp(filter, "placeholder", t("table.filter.all", "All"));
61
61
  return /* @__PURE__ */ jsxs("select", {
62
62
  "aria-label": filter.label,
63
63
  "data-test": `table-filter-${filter.key}`,
@@ -81,7 +81,7 @@ function MultiSelectControl({ filter, value, processing, onChange }) {
81
81
  function toggle(optionValue) {
82
82
  onChange(selected.includes(optionValue) ? selected.filter((item) => item !== optionValue) : [...selected, optionValue]);
83
83
  }
84
- const summary = selected.length === 0 ? stringProp(filter, "placeholder", t("filter.all", "All")) : t("filter.selectedCount", "{{amount}} selected", { amount: selected.length });
84
+ const summary = selected.length === 0 ? stringProp(filter, "placeholder", t("table.filter.all", "All")) : t("table.filter.selectedCount", "{{amount}} selected", { amount: selected.length });
85
85
  return /* @__PURE__ */ jsxs("div", {
86
86
  className: "relative",
87
87
  children: [/* @__PURE__ */ jsxs("button", {
@@ -126,7 +126,7 @@ function SearchableSelectControl({ filter, value, processing, onChange, onSearch
126
126
  const [loading, setLoading] = useState(false);
127
127
  const selected = multiple ? Array.isArray(value) ? value : [] : typeof value === "string" && value !== "" ? [value] : [];
128
128
  const labels = new Map([...filterOptions(filter), ...results].map((option) => [option.value, option.label]));
129
- const summary = selected.length === 0 ? stringProp(filter, "placeholder", t("filter.all", "All")) : multiple ? t("filter.selectedCount", "{{amount}} selected", { amount: selected.length }) : labels.get(selected[0]) ?? selected[0];
129
+ const summary = selected.length === 0 ? stringProp(filter, "placeholder", t("table.filter.all", "All")) : multiple ? t("table.filter.selectedCount", "{{amount}} selected", { amount: selected.length }) : labels.get(selected[0]) ?? selected[0];
130
130
  function search(query) {
131
131
  setLoading(true);
132
132
  onSearch(query).then((options) => {
@@ -146,7 +146,7 @@ function SearchableSelectControl({ filter, value, processing, onChange, onSearch
146
146
  open,
147
147
  onOpenChange: setOpen,
148
148
  options: results,
149
- searchLabel: t("filter.search", "Search"),
149
+ searchLabel: t("table.filter.search", "Search"),
150
150
  selected,
151
151
  testId: `table-filter-${filter.key}`,
152
152
  trigger: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
@@ -167,9 +167,9 @@ function SearchableSelectControl({ filter, value, processing, onChange, onSearch
167
167
  }
168
168
  function TernaryControl({ filter, value, processing, onChange }) {
169
169
  const { t } = useT("lattice");
170
- const placeholder = stringProp(filter, "placeholder", t("filter.all", "All"));
171
- const trueLabel = stringProp(filter, "trueLabel", t("filter.true", "True"));
172
- const falseLabel = stringProp(filter, "falseLabel", t("filter.false", "False"));
170
+ const placeholder = stringProp(filter, "placeholder", t("table.filter.all", "All"));
171
+ const trueLabel = stringProp(filter, "trueLabel", t("table.filter.true", "True"));
172
+ const falseLabel = stringProp(filter, "falseLabel", t("table.filter.false", "False"));
173
173
  return /* @__PURE__ */ jsxs("select", {
174
174
  "aria-label": filter.label,
175
175
  "data-test": `table-filter-${filter.key}`,
@@ -207,7 +207,7 @@ function DateRangeControl({ filter, value, processing, onChange }) {
207
207
  children: [
208
208
  /* @__PURE__ */ jsx("input", {
209
209
  type: "date",
210
- "aria-label": t("filter.from", "{{label}} from", { label: filter.label }),
210
+ "aria-label": t("table.filter.from", "{{label}} from", { label: filter.label }),
211
211
  "data-test": `table-filter-${filter.key}-from`,
212
212
  className: fieldClass,
213
213
  disabled: processing,
@@ -224,7 +224,7 @@ function DateRangeControl({ filter, value, processing, onChange }) {
224
224
  }),
225
225
  /* @__PURE__ */ jsx("input", {
226
226
  type: "date",
227
- "aria-label": t("filter.until", "{{label}} until", { label: filter.label }),
227
+ "aria-label": t("table.filter.until", "{{label}} until", { label: filter.label }),
228
228
  "data-test": `table-filter-${filter.key}-until`,
229
229
  className: fieldClass,
230
230
  disabled: processing,
@@ -1 +1 @@
1
- {"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useState } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Combobox } from \"@lattice-php/lattice/core/components/combobox\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, stringProp } from \"../filter-values\";\nimport { fieldClass } from \"./filter-value-input\";\n\nexport type DateRangeValue = { from?: string; until?: string };\n\nexport type FilterOptionSearch = (query: string) => Promise<Option[]>;\n\n/**\n * Renders the control for a single dedicated table filter, dispatching on the\n * filter's `type`. The current value comes from the table state; `onChange`\n * pushes a new value (an empty value clears the filter).\n */\nexport function TableFilterControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n switch (filter.type) {\n case \"select\":\n if (filter.props.searchable === true && onSearch) {\n return (\n <SearchableSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n onSearch={onSearch}\n />\n );\n }\n\n return filter.props.multiple === true ? (\n <MultiSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n ) : (\n <SelectControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"ternary\":\n return (\n <TernaryControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"date-range\":\n return (\n <DateRangeControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n );\n case \"toggle\":\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n default:\n return null;\n }\n}\n\nfunction SelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"filter.all\", \"All\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n {filterOptions(filter).map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n\nfunction MultiSelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const selected = Array.isArray(value) ? (value as string[]) : [];\n\n function toggle(optionValue: string): void {\n const next = selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue];\n\n onChange(next);\n }\n\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"filter.all\", \"All\"))\n : t(\"filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length });\n\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n aria-label={filter.label}\n aria-expanded={open}\n data-test={`table-filter-${filter.key}`}\n className={`${fieldClass} flex items-center justify-between gap-2`}\n disabled={processing}\n onClick={() => setOpen((current) => !current)}\n >\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </button>\n {open && (\n <div className=\"absolute z-10 mt-1 min-w-full rounded-lt-sm border border-lt-border bg-lt-bg p-1 shadow-lt-md\">\n {filterOptions(filter).map((option) => (\n <label\n key={option.value}\n className=\"flex cursor-pointer items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm hover:bg-lt-muted\"\n >\n <Checkbox\n aria-label={option.label}\n data-test={`table-filter-${filter.key}-${option.value}`}\n checked={selected.includes(option.value)}\n disabled={processing}\n onCheckedChange={() => toggle(option.value)}\n />\n <span className=\"truncate\">{option.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SearchableSelectControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const multiple = filter.props.multiple === true;\n const [open, setOpen] = useState(false);\n const [results, setResults] = useState<Option[]>(() => filterOptions(filter));\n const [loading, setLoading] = useState(false);\n\n const selected = multiple\n ? Array.isArray(value)\n ? (value as string[])\n : []\n : typeof value === \"string\" && value !== \"\"\n ? [value]\n : [];\n\n const labels = new Map(\n [...filterOptions(filter), ...results].map((option) => [option.value, option.label]),\n );\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"filter.all\", \"All\"))\n : multiple\n ? t(\"filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length })\n : (labels.get(selected[0]) ?? selected[0]);\n\n function search(query: string): void {\n setLoading(true);\n void onSearch(query).then((options) => {\n setResults(options);\n setLoading(false);\n });\n }\n\n function choose(optionValue: string): void {\n onChange(\n multiple\n ? selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue]\n : optionValue,\n );\n }\n\n return (\n <Combobox\n contentClassName=\"w-60\"\n loading={loading}\n multiple={multiple}\n onSearch={search}\n onSelect={choose}\n open={open}\n onOpenChange={setOpen}\n options={results}\n searchLabel={t(\"filter.search\", \"Search\")}\n selected={selected}\n testId={`table-filter-${filter.key}`}\n trigger={\n <>\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </>\n }\n triggerClassName={cn(fieldClass, \"flex items-center justify-between gap-2\")}\n triggerProps={{\n \"aria-label\": filter.label,\n \"data-test\": `table-filter-${filter.key}`,\n disabled: processing,\n }}\n />\n );\n}\n\nfunction TernaryControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"filter.all\", \"All\"));\n const trueLabel = stringProp(filter, \"trueLabel\", t(\"filter.true\", \"True\"));\n const falseLabel = stringProp(filter, \"falseLabel\", t(\"filter.false\", \"False\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n <option value=\"true\">{trueLabel}</option>\n <option value=\"false\">{falseLabel}</option>\n </select>\n );\n}\n\nfunction DateRangeControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const range: DateRangeValue = value && typeof value === \"object\" ? (value as DateRangeValue) : {};\n\n function commit(next: DateRangeValue): void {\n onChange({ from: next.from ?? \"\", until: next.until ?? \"\" });\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"date\"\n aria-label={t(\"filter.from\", \"{{label}} from\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-from`}\n className={fieldClass}\n disabled={processing}\n value={range.from ?? \"\"}\n onChange={(event) => commit({ ...range, from: event.target.value })}\n />\n <span className=\"text-lt-muted-fg\" aria-hidden=\"true\">\n –\n </span>\n <input\n type=\"date\"\n aria-label={t(\"filter.until\", \"{{label}} until\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-until`}\n className={fieldClass}\n disabled={processing}\n value={range.until ?? \"\"}\n onChange={(event) => commit({ ...range, until: event.target.value })}\n />\n </div>\n );\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = value === \"1\" || value === true || value === \"true\";\n\n return (\n <label className=\"flex h-9 cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? \"1\" : \"\")}\n />\n <span>{filter.label}</span>\n </label>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,SAAgB,mBAAmB,EACjC,QACA,OACA,YACA,UACA,YAOC;CACD,QAAQ,OAAO,MAAf;EACE,KAAK;GACH,IAAI,OAAO,MAAM,eAAe,QAAQ,UACtC,OACE,oBAAC,yBAAD;IACU;IACD;IACK;IACF;IACA;GACX,CAAA;GAIL,OAAO,OAAO,MAAM,aAAa,OAC/B,oBAAC,oBAAD;IACU;IACD;IACK;IACF;GACX,CAAA,IAED,oBAAC,eAAD;IAAuB;IAAe;IAAmB;IAAsB;GAAW,CAAA;EAE9F,KAAK,WACH,OACE,oBAAC,gBAAD;GAAwB;GAAe;GAAmB;GAAsB;EAAW,CAAA;EAE/F,KAAK,cACH,OACE,oBAAC,kBAAD;GACU;GACD;GACK;GACF;EACX,CAAA;EAEL,KAAK,UACH,OACE,oBAAC,eAAD;GAAuB;GAAe;GAAmB;GAAsB;EAAW,CAAA;EAE9F,SACE,OAAO;CACX;AACF;AAEA,SAAS,cAAc,EACrB,QACA,OACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,cAAc,WAAW,QAAQ,eAAe,EAAE,cAAc,KAAK,CAAC;CAE5E,OACE,qBAAC,UAAD;EACE,cAAY,OAAO;EACnB,aAAW,gBAAgB,OAAO;EAClC,WAAW;EACX,UAAU;EACV,OAAO,OAAO,UAAU,WAAW,QAAQ;EAC3C,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YANlD,CAQE,oBAAC,UAAD;GAAQ,OAAM;aAAI;EAAoB,CAAA,GACrC,cAAc,MAAM,EAAE,KAAK,WAC1B,oBAAC,UAAD;GAA2B,OAAO,OAAO;aACtC,OAAO;EACF,GAFK,OAAO,KAEZ,CACT,CACK;;AAEZ;AAEA,SAAS,mBAAmB,EAC1B,QACA,OACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,WAAW,MAAM,QAAQ,KAAK,IAAK,QAAqB,CAAC;CAE/D,SAAS,OAAO,aAA2B;EAKzC,SAJa,SAAS,SAAS,WAAW,IACtC,SAAS,QAAQ,SAAS,SAAS,WAAW,IAC9C,CAAC,GAAG,UAAU,WAAW,CAEhB;CACf;CAEA,MAAM,UACJ,SAAS,WAAW,IAChB,WAAW,QAAQ,eAAe,EAAE,cAAc,KAAK,CAAC,IACxD,EAAE,wBAAwB,uBAAuB,EAAE,QAAQ,SAAS,OAAO,CAAC;CAElF,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,qBAAC,UAAD;GACE,MAAK;GACL,cAAY,OAAO;GACnB,iBAAe;GACf,aAAW,gBAAgB,OAAO;GAClC,WAAW,GAAG,WAAW;GACzB,UAAU;GACV,eAAe,SAAS,YAAY,CAAC,OAAO;aAP9C,CASE,oBAAC,QAAD;IAAM,WAAU;cAAY;GAAc,CAAA,GAC1C,oBAAC,MAAD;IAAM,MAAK;IAAe,eAAY;IAAO,WAAU;GAA4B,CAAA,CAC7E;MACP,QACC,oBAAC,OAAD;GAAK,WAAU;aACZ,cAAc,MAAM,EAAE,KAAK,WAC1B,qBAAC,SAAD;IAEE,WAAU;cAFZ,CAIE,oBAAC,UAAD;KACE,cAAY,OAAO;KACnB,aAAW,gBAAgB,OAAO,IAAI,GAAG,OAAO;KAChD,SAAS,SAAS,SAAS,OAAO,KAAK;KACvC,UAAU;KACV,uBAAuB,OAAO,OAAO,KAAK;IAC3C,CAAA,GACD,oBAAC,QAAD;KAAM,WAAU;eAAY,OAAO;IAAY,CAAA,CAC1C;MAXA,OAAO,KAWP,CACR;EACE,CAAA,CAEJ;;AAET;AAEA,SAAS,wBAAwB,EAC/B,QACA,OACA,YACA,UACA,YAOC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,WAAW,OAAO,MAAM,aAAa;CAC3C,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,SAAS,cAAc,eAAyB,cAAc,MAAM,CAAC;CAC5E,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAE5C,MAAM,WAAW,WACb,MAAM,QAAQ,KAAK,IAChB,QACD,CAAC,IACH,OAAO,UAAU,YAAY,UAAU,KACrC,CAAC,KAAK,IACN,CAAC;CAEP,MAAM,SAAS,IAAI,IACjB,CAAC,GAAG,cAAc,MAAM,GAAG,GAAG,OAAO,EAAE,KAAK,WAAW,CAAC,OAAO,OAAO,OAAO,KAAK,CAAC,CACrF;CACA,MAAM,UACJ,SAAS,WAAW,IAChB,WAAW,QAAQ,eAAe,EAAE,cAAc,KAAK,CAAC,IACxD,WACE,EAAE,wBAAwB,uBAAuB,EAAE,QAAQ,SAAS,OAAO,CAAC,IAC3E,OAAO,IAAI,SAAS,EAAE,KAAK,SAAS;CAE7C,SAAS,OAAO,OAAqB;EACnC,WAAW,IAAI;EACf,SAAc,KAAK,EAAE,MAAM,YAAY;GACrC,WAAW,OAAO;GAClB,WAAW,KAAK;EAClB,CAAC;CACH;CAEA,SAAS,OAAO,aAA2B;EACzC,SACE,WACI,SAAS,SAAS,WAAW,IAC3B,SAAS,QAAQ,SAAS,SAAS,WAAW,IAC9C,CAAC,GAAG,UAAU,WAAW,IAC3B,WACN;CACF;CAEA,OACE,oBAAC,UAAD;EACE,kBAAiB;EACR;EACC;EACV,UAAU;EACV,UAAU;EACJ;EACN,cAAc;EACd,SAAS;EACT,aAAa,EAAE,iBAAiB,QAAQ;EAC9B;EACV,QAAQ,gBAAgB,OAAO;EAC/B,SACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;aAAY;EAAc,CAAA,GAC1C,oBAAC,MAAD;GAAM,MAAK;GAAe,eAAY;GAAO,WAAU;EAA4B,CAAA,CACnF,EAAA,CAAA;EAEJ,kBAAkB,GAAG,YAAY,yCAAyC;EAC1E,cAAc;GACZ,cAAc,OAAO;GACrB,aAAa,gBAAgB,OAAO;GACpC,UAAU;EACZ;CACD,CAAA;AAEL;AAEA,SAAS,eAAe,EACtB,QACA,OACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,cAAc,WAAW,QAAQ,eAAe,EAAE,cAAc,KAAK,CAAC;CAC5E,MAAM,YAAY,WAAW,QAAQ,aAAa,EAAE,eAAe,MAAM,CAAC;CAC1E,MAAM,aAAa,WAAW,QAAQ,cAAc,EAAE,gBAAgB,OAAO,CAAC;CAE9E,OACE,qBAAC,UAAD;EACE,cAAY,OAAO;EACnB,aAAW,gBAAgB,OAAO;EAClC,WAAW;EACX,UAAU;EACV,OAAO,OAAO,UAAU,WAAW,QAAQ;EAC3C,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YANlD;GAQE,oBAAC,UAAD;IAAQ,OAAM;cAAI;GAAoB,CAAA;GACtC,oBAAC,UAAD;IAAQ,OAAM;cAAQ;GAAkB,CAAA;GACxC,oBAAC,UAAD;IAAQ,OAAM;cAAS;GAAmB,CAAA;EACpC;;AAEZ;AAEA,SAAS,iBAAiB,EACxB,QACA,OACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAwB,SAAS,OAAO,UAAU,WAAY,QAA2B,CAAC;CAEhG,SAAS,OAAO,MAA4B;EAC1C,SAAS;GAAE,MAAM,KAAK,QAAQ;GAAI,OAAO,KAAK,SAAS;EAAG,CAAC;CAC7D;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,SAAD;IACE,MAAK;IACL,cAAY,EAAE,eAAe,kBAAkB,EAAE,OAAO,OAAO,MAAM,CAAC;IACtE,aAAW,gBAAgB,OAAO,IAAI;IACtC,WAAW;IACX,UAAU;IACV,OAAO,MAAM,QAAQ;IACrB,WAAW,UAAU,OAAO;KAAE,GAAG;KAAO,MAAM,MAAM,OAAO;IAAM,CAAC;GACnE,CAAA;GACD,oBAAC,QAAD;IAAM,WAAU;IAAmB,eAAY;cAAO;GAEhD,CAAA;GACN,oBAAC,SAAD;IACE,MAAK;IACL,cAAY,EAAE,gBAAgB,mBAAmB,EAAE,OAAO,OAAO,MAAM,CAAC;IACxE,aAAW,gBAAgB,OAAO,IAAI;IACtC,WAAW;IACX,UAAU;IACV,OAAO,MAAM,SAAS;IACtB,WAAW,UAAU,OAAO;KAAE,GAAG;KAAO,OAAO,MAAM,OAAO;IAAM,CAAC;GACpE,CAAA;EACE;;AAET;AAEA,SAAS,cAAc,EACrB,QACA,OACA,YACA,YAMC;CACD,MAAM,UAAU,UAAU,OAAO,UAAU,QAAQ,UAAU;CAE7D,OACE,qBAAC,SAAD;EAAO,WAAU;YAAjB,CACE,oBAAC,UAAD;GACE,cAAY,OAAO;GACnB,aAAW,gBAAgB,OAAO;GACzB;GACT,UAAU;GACV,kBAAkB,SAAS,SAAS,SAAS,OAAO,MAAM,EAAE;EAC7D,CAAA,GACD,oBAAC,QAAD,EAAA,UAAO,OAAO,MAAY,CAAA,CACrB;;AAEX"}
1
+ {"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useState } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Combobox } from \"@lattice-php/lattice/core/components/combobox\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, stringProp } from \"../filter-values\";\nimport { fieldClass } from \"./filter-value-input\";\n\nexport type DateRangeValue = { from?: string; until?: string };\n\nexport type FilterOptionSearch = (query: string) => Promise<Option[]>;\n\n/**\n * Renders the control for a single dedicated table filter, dispatching on the\n * filter's `type`. The current value comes from the table state; `onChange`\n * pushes a new value (an empty value clears the filter).\n */\nexport function TableFilterControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n switch (filter.type) {\n case \"select\":\n if (filter.props.searchable === true && onSearch) {\n return (\n <SearchableSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n onSearch={onSearch}\n />\n );\n }\n\n return filter.props.multiple === true ? (\n <MultiSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n ) : (\n <SelectControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"ternary\":\n return (\n <TernaryControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"date-range\":\n return (\n <DateRangeControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n );\n case \"toggle\":\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n default:\n return null;\n }\n}\n\nfunction SelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n {filterOptions(filter).map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n\nfunction MultiSelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const selected = Array.isArray(value) ? (value as string[]) : [];\n\n function toggle(optionValue: string): void {\n const next = selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue];\n\n onChange(next);\n }\n\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length });\n\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n aria-label={filter.label}\n aria-expanded={open}\n data-test={`table-filter-${filter.key}`}\n className={`${fieldClass} flex items-center justify-between gap-2`}\n disabled={processing}\n onClick={() => setOpen((current) => !current)}\n >\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </button>\n {open && (\n <div className=\"absolute z-10 mt-1 min-w-full rounded-lt-sm border border-lt-border bg-lt-bg p-1 shadow-lt-md\">\n {filterOptions(filter).map((option) => (\n <label\n key={option.value}\n className=\"flex cursor-pointer items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm hover:bg-lt-muted\"\n >\n <Checkbox\n aria-label={option.label}\n data-test={`table-filter-${filter.key}-${option.value}`}\n checked={selected.includes(option.value)}\n disabled={processing}\n onCheckedChange={() => toggle(option.value)}\n />\n <span className=\"truncate\">{option.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SearchableSelectControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const multiple = filter.props.multiple === true;\n const [open, setOpen] = useState(false);\n const [results, setResults] = useState<Option[]>(() => filterOptions(filter));\n const [loading, setLoading] = useState(false);\n\n const selected = multiple\n ? Array.isArray(value)\n ? (value as string[])\n : []\n : typeof value === \"string\" && value !== \"\"\n ? [value]\n : [];\n\n const labels = new Map(\n [...filterOptions(filter), ...results].map((option) => [option.value, option.label]),\n );\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : multiple\n ? t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length })\n : (labels.get(selected[0]) ?? selected[0]);\n\n function search(query: string): void {\n setLoading(true);\n void onSearch(query).then((options) => {\n setResults(options);\n setLoading(false);\n });\n }\n\n function choose(optionValue: string): void {\n onChange(\n multiple\n ? selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue]\n : optionValue,\n );\n }\n\n return (\n <Combobox\n contentClassName=\"w-60\"\n loading={loading}\n multiple={multiple}\n onSearch={search}\n onSelect={choose}\n open={open}\n onOpenChange={setOpen}\n options={results}\n searchLabel={t(\"table.filter.search\", \"Search\")}\n selected={selected}\n testId={`table-filter-${filter.key}`}\n trigger={\n <>\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </>\n }\n triggerClassName={cn(fieldClass, \"flex items-center justify-between gap-2\")}\n triggerProps={{\n \"aria-label\": filter.label,\n \"data-test\": `table-filter-${filter.key}`,\n disabled: processing,\n }}\n />\n );\n}\n\nfunction TernaryControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n const trueLabel = stringProp(filter, \"trueLabel\", t(\"table.filter.true\", \"True\"));\n const falseLabel = stringProp(filter, \"falseLabel\", t(\"table.filter.false\", \"False\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n <option value=\"true\">{trueLabel}</option>\n <option value=\"false\">{falseLabel}</option>\n </select>\n );\n}\n\nfunction DateRangeControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const range: DateRangeValue = value && typeof value === \"object\" ? (value as DateRangeValue) : {};\n\n function commit(next: DateRangeValue): void {\n onChange({ from: next.from ?? \"\", until: next.until ?? \"\" });\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"date\"\n aria-label={t(\"table.filter.from\", \"{{label}} from\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-from`}\n className={fieldClass}\n disabled={processing}\n value={range.from ?? \"\"}\n onChange={(event) => commit({ ...range, from: event.target.value })}\n />\n <span className=\"text-lt-muted-fg\" aria-hidden=\"true\">\n –\n </span>\n <input\n type=\"date\"\n aria-label={t(\"table.filter.until\", \"{{label}} until\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-until`}\n className={fieldClass}\n disabled={processing}\n value={range.until ?? \"\"}\n onChange={(event) => commit({ ...range, until: event.target.value })}\n />\n </div>\n );\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = value === \"1\" || value === true || value === \"true\";\n\n return (\n <label className=\"flex h-9 cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? \"1\" : \"\")}\n />\n <span>{filter.label}</span>\n </label>\n );\n}\n"],"mappings":"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"}
@@ -20,7 +20,7 @@ function FilterStackBar({ filters, columnsByKey, processing, onRemove }) {
20
20
  "data-test": `filter-chip-${clause.field}-remove`,
21
21
  className: "inline-flex size-5 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50",
22
22
  disabled: processing,
23
- "aria-label": t("filter.remove", "Remove {{label}} filter", { label }),
23
+ "aria-label": t("table.filter.remove", "Remove {{label}} filter", { label }),
24
24
  onClick: () => onRemove(index),
25
25
  children: /* @__PURE__ */ jsx(Icon, {
26
26
  name: "x",
@@ -1 +1 @@
1
- {"version":3,"file":"filter-stack-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-stack-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"../query\";\nimport type { FilterClause, TableColumn } from \"../types\";\n\nexport function FilterStackBar({\n filters,\n columnsByKey,\n processing,\n onRemove,\n}: {\n filters: FilterClause[];\n columnsByKey: Map<string, TableColumn>;\n processing: boolean;\n onRemove: (index: number) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {filters.map((clause, index) => {\n const label = columnsByKey.get(clause.field)?.label ?? clause.field;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <span\n key={`${clause.field}-${clause.operator}-${index}`}\n className=\"inline-flex items-center gap-1.5\"\n >\n <span>\n {valueless\n ? `${label} ${operatorLabel(clause.operator)}`\n : `${label} ${operatorLabel(clause.operator)}: `}\n {!valueless && <span className=\"font-semibold\">{clause.value}</span>}\n </span>\n <button\n type=\"button\"\n data-test={`filter-chip-${clause.field}-remove`}\n className=\"inline-flex size-5 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={t(\"filter.remove\", \"Remove {{label}} filter\", { label })}\n onClick={() => onRemove(index)}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,eAAe,EAC7B,SACA,cACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,QAAQ,KAAK,QAAQ,UAAU;GAC9B,MAAM,QAAQ,aAAa,IAAI,OAAO,KAAK,GAAG,SAAS,OAAO;GAC9D,MAAM,YAAY,2BAA2B,IAAI,OAAO,QAAQ;GAEhE,OACE,qBAAC,QAAD;IAEE,WAAU;cAFZ,CAIE,qBAAC,QAAD,EAAA,UAAA,CACG,YACG,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,MACzC,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,EAAE,KAC9C,CAAC,aAAa,oBAAC,QAAD;KAAM,WAAU;eAAiB,OAAO;IAAY,CAAA,CAC/D,EAAA,CAAA,GACN,oBAAC,UAAD;KACE,MAAK;KACL,aAAW,eAAe,OAAO,MAAM;KACvC,WAAU;KACV,UAAU;KACV,cAAY,EAAE,iBAAiB,2BAA2B,EAAE,MAAM,CAAC;KACnE,eAAe,SAAS,KAAK;eAE7B,oBAAC,MAAD;MAAM,MAAK;MAAI,eAAY;MAAO,WAAU;KAAmB,CAAA;IACzD,CAAA,CACJ;MAnBC,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,OAmBvC;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"filter-stack-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-stack-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { operatorLabel, VALUELESS_FILTER_OPERATORS } from \"../query\";\nimport type { FilterClause, TableColumn } from \"../types\";\n\nexport function FilterStackBar({\n filters,\n columnsByKey,\n processing,\n onRemove,\n}: {\n filters: FilterClause[];\n columnsByKey: Map<string, TableColumn>;\n processing: boolean;\n onRemove: (index: number) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {filters.map((clause, index) => {\n const label = columnsByKey.get(clause.field)?.label ?? clause.field;\n const valueless = VALUELESS_FILTER_OPERATORS.has(clause.operator);\n\n return (\n <span\n key={`${clause.field}-${clause.operator}-${index}`}\n className=\"inline-flex items-center gap-1.5\"\n >\n <span>\n {valueless\n ? `${label} ${operatorLabel(clause.operator)}`\n : `${label} ${operatorLabel(clause.operator)}: `}\n {!valueless && <span className=\"font-semibold\">{clause.value}</span>}\n </span>\n <button\n type=\"button\"\n data-test={`filter-chip-${clause.field}-remove`}\n className=\"inline-flex size-5 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={t(\"table.filter.remove\", \"Remove {{label}} filter\", { label })}\n onClick={() => onRemove(index)}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,eAAe,EAC7B,SACA,cACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,QAAQ,KAAK,QAAQ,UAAU;GAC9B,MAAM,QAAQ,aAAa,IAAI,OAAO,KAAK,GAAG,SAAS,OAAO;GAC9D,MAAM,YAAY,2BAA2B,IAAI,OAAO,QAAQ;GAEhE,OACE,qBAAC,QAAD;IAEE,WAAU;cAFZ,CAIE,qBAAC,QAAD,EAAA,UAAA,CACG,YACG,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,MACzC,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,EAAE,KAC9C,CAAC,aAAa,oBAAC,QAAD;KAAM,WAAU;eAAiB,OAAO;IAAY,CAAA,CAC/D,EAAA,CAAA,GACN,oBAAC,UAAD;KACE,MAAK;KACL,aAAW,eAAe,OAAO,MAAM;KACvC,WAAU;KACV,UAAU;KACV,cAAY,EAAE,uBAAuB,2BAA2B,EAAE,MAAM,CAAC;KACzE,eAAe,SAAS,KAAK;eAE7B,oBAAC,MAAD;MAAM,MAAK;MAAI,eAAY;MAAO,WAAU;KAAmB,CAAA;IACzD,CAAA,CACJ;MAnBC,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,OAmBvC;EAEV,CAAC;CACE,CAAA;AAET"}
@@ -8,7 +8,7 @@ var fieldClass = controlSurface({ density: "compact" });
8
8
  function FilterValueInput({ type, label, value, processing, withSearchIcon = false, grouped = false, ariaLabel, testId, onCommit, onClear }) {
9
9
  const { t } = useT("lattice");
10
10
  const [draft, setDraft] = useState(value);
11
- const inputLabel = ariaLabel ?? t("filter.filterBy", "Filter {{label}}", { label });
11
+ const inputLabel = ariaLabel ?? t("table.filter.filterBy", "Filter {{label}}", { label });
12
12
  const groupedClass = grouped ? "rounded-r-none" : "";
13
13
  useEffect(() => {
14
14
  setDraft(value);
@@ -23,15 +23,15 @@ function FilterValueInput({ type, label, value, processing, withSearchIcon = fal
23
23
  children: [
24
24
  /* @__PURE__ */ jsx("option", {
25
25
  value: "",
26
- children: t("filter.all", "All")
26
+ children: t("table.filter.all", "All")
27
27
  }),
28
28
  /* @__PURE__ */ jsx("option", {
29
29
  value: "true",
30
- children: t("filter.true", "True")
30
+ children: t("table.filter.true", "True")
31
31
  }),
32
32
  /* @__PURE__ */ jsx("option", {
33
33
  value: "false",
34
- children: t("filter.false", "False")
34
+ children: t("table.filter.false", "False")
35
35
  })
36
36
  ]
37
37
  });
@@ -72,7 +72,7 @@ function FilterValueInput({ type, label, value, processing, withSearchIcon = fal
72
72
  }),
73
73
  onClear && draft !== "" && /* @__PURE__ */ jsx("button", {
74
74
  type: "button",
75
- "aria-label": t("filter.clear", "Clear {{label}} filter", { label }),
75
+ "aria-label": t("table.filter.clear", "Clear {{label}} filter", { label }),
76
76
  "data-test": testId ? `${testId}-clear` : void 0,
77
77
  className: "absolute right-1 inline-flex size-6 items-center justify-center rounded-lt-sm hover:bg-lt-muted disabled:opacity-50",
78
78
  disabled: processing,
@@ -1 +1 @@
1
- {"version":3,"file":"filter-value-input.js","names":[],"sources":["../../../resources/js/table/components/filter-value-input.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useEffect, useState } from \"react\";\nimport { controlSurface } from \"@lattice-php/lattice/core/components/control\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { FilterType } from \"@lattice-php/lattice/types/generated\";\n\nexport const fieldClass = controlSurface({ density: \"compact\" });\n\nexport function FilterValueInput({\n type,\n label,\n value,\n processing,\n withSearchIcon = false,\n grouped = false,\n ariaLabel,\n testId,\n onCommit,\n onClear,\n}: {\n type: FilterType;\n label: string;\n value: string;\n processing: boolean;\n withSearchIcon?: boolean;\n grouped?: boolean;\n ariaLabel?: string;\n testId?: string;\n onCommit: (value: string) => void;\n onClear?: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const [draft, setDraft] = useState(value);\n const inputLabel = ariaLabel ?? t(\"filter.filterBy\", \"Filter {{label}}\", { label });\n const groupedClass = grouped ? \"rounded-r-none\" : \"\";\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n if (type === \"boolean\") {\n return (\n <select\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass}`}\n disabled={processing}\n value={value}\n onChange={(event) => onCommit(event.target.value)}\n >\n <option value=\"\">{t(\"filter.all\", \"All\")}</option>\n <option value=\"true\">{t(\"filter.true\", \"True\")}</option>\n <option value=\"false\">{t(\"filter.false\", \"False\")}</option>\n </select>\n );\n }\n\n if (type === \"date\") {\n return (\n <input\n type=\"date\"\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass}`}\n disabled={processing}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n onCommit(event.target.value);\n }}\n />\n );\n }\n\n return (\n <div className=\"relative flex w-full min-w-0 items-center\">\n {withSearchIcon && (\n <Icon\n name=\"search\"\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-2 size-lt-icon-md text-lt-muted-fg\"\n />\n )}\n <input\n type={type === \"number\" ? \"number\" : \"text\"}\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass} ${withSearchIcon ? \"pl-8\" : \"\"} ${onClear ? \"pr-8\" : \"\"}`}\n disabled={processing}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n onCommit(draft);\n }\n }}\n onBlur={() => {\n if (draft !== value) {\n onCommit(draft);\n }\n }}\n />\n {onClear && draft !== \"\" && (\n <button\n type=\"button\"\n aria-label={t(\"filter.clear\", \"Clear {{label}} filter\", { label })}\n data-test={testId ? `${testId}-clear` : undefined}\n className=\"absolute right-1 inline-flex size-6 items-center justify-center rounded-lt-sm hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n onClick={onClear}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;AAMA,IAAa,aAAa,eAAe,EAAE,SAAS,UAAU,CAAC;AAE/D,SAAgB,iBAAiB,EAC/B,MACA,OACA,OACA,YACA,iBAAiB,OACjB,UAAU,OACV,WACA,QACA,UACA,WAYC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,aAAa,aAAa,EAAE,mBAAmB,oBAAoB,EAAE,MAAM,CAAC;CAClF,MAAM,eAAe,UAAU,mBAAmB;CAElD,gBAAgB;EACd,SAAS,KAAK;CAChB,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,SAAS,WACX,OACE,qBAAC,UAAD;EACE,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,WAAW,GAAG;EAC5B,UAAU;EACH;EACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YANlD;GAQE,oBAAC,UAAD;IAAQ,OAAM;cAAI,EAAE,cAAc,KAAK;GAAU,CAAA;GACjD,oBAAC,UAAD;IAAQ,OAAM;cAAQ,EAAE,eAAe,MAAM;GAAU,CAAA;GACvD,oBAAC,UAAD;IAAQ,OAAM;cAAS,EAAE,gBAAgB,OAAO;GAAU,CAAA;EACpD;;CAIZ,IAAI,SAAS,QACX,OACE,oBAAC,SAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,WAAW,GAAG;EAC5B,UAAU;EACV,OAAO;EACP,WAAW,UAAU;GACnB,SAAS,MAAM,OAAO,KAAK;GAC3B,SAAS,MAAM,OAAO,KAAK;EAC7B;CACD,CAAA;CAIL,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,kBACC,oBAAC,MAAD;IACE,MAAK;IACL,eAAY;IACZ,WAAU;GACX,CAAA;GAEH,oBAAC,SAAD;IACE,MAAM,SAAS,WAAW,WAAW;IACrC,cAAY;IACZ,aAAW;IACX,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,iBAAiB,SAAS,GAAG,GAAG,UAAU,SAAS;IAC/F,UAAU;IACV,OAAO;IACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;IAChD,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,SAChB,SAAS,KAAK;IAElB;IACA,cAAc;KACZ,IAAI,UAAU,OACZ,SAAS,KAAK;IAElB;GACD,CAAA;GACA,WAAW,UAAU,MACpB,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,EAAE,gBAAgB,0BAA0B,EAAE,MAAM,CAAC;IACjE,aAAW,SAAS,GAAG,OAAO,UAAU,KAAA;IACxC,WAAU;IACV,UAAU;IACV,SAAS;cAET,oBAAC,MAAD;KAAM,MAAK;KAAI,eAAY;KAAO,WAAU;IAAmB,CAAA;GACzD,CAAA;EAEP;;AAET"}
1
+ {"version":3,"file":"filter-value-input.js","names":[],"sources":["../../../resources/js/table/components/filter-value-input.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useEffect, useState } from \"react\";\nimport { controlSurface } from \"@lattice-php/lattice/core/components/control\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { FilterType } from \"@lattice-php/lattice/types/generated\";\n\nexport const fieldClass = controlSurface({ density: \"compact\" });\n\nexport function FilterValueInput({\n type,\n label,\n value,\n processing,\n withSearchIcon = false,\n grouped = false,\n ariaLabel,\n testId,\n onCommit,\n onClear,\n}: {\n type: FilterType;\n label: string;\n value: string;\n processing: boolean;\n withSearchIcon?: boolean;\n grouped?: boolean;\n ariaLabel?: string;\n testId?: string;\n onCommit: (value: string) => void;\n onClear?: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const [draft, setDraft] = useState(value);\n const inputLabel = ariaLabel ?? t(\"table.filter.filterBy\", \"Filter {{label}}\", { label });\n const groupedClass = grouped ? \"rounded-r-none\" : \"\";\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n if (type === \"boolean\") {\n return (\n <select\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass}`}\n disabled={processing}\n value={value}\n onChange={(event) => onCommit(event.target.value)}\n >\n <option value=\"\">{t(\"table.filter.all\", \"All\")}</option>\n <option value=\"true\">{t(\"table.filter.true\", \"True\")}</option>\n <option value=\"false\">{t(\"table.filter.false\", \"False\")}</option>\n </select>\n );\n }\n\n if (type === \"date\") {\n return (\n <input\n type=\"date\"\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass}`}\n disabled={processing}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n onCommit(event.target.value);\n }}\n />\n );\n }\n\n return (\n <div className=\"relative flex w-full min-w-0 items-center\">\n {withSearchIcon && (\n <Icon\n name=\"search\"\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-2 size-lt-icon-md text-lt-muted-fg\"\n />\n )}\n <input\n type={type === \"number\" ? \"number\" : \"text\"}\n aria-label={inputLabel}\n data-test={testId}\n className={`${fieldClass} ${groupedClass} ${withSearchIcon ? \"pl-8\" : \"\"} ${onClear ? \"pr-8\" : \"\"}`}\n disabled={processing}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n onCommit(draft);\n }\n }}\n onBlur={() => {\n if (draft !== value) {\n onCommit(draft);\n }\n }}\n />\n {onClear && draft !== \"\" && (\n <button\n type=\"button\"\n aria-label={t(\"table.filter.clear\", \"Clear {{label}} filter\", { label })}\n data-test={testId ? `${testId}-clear` : undefined}\n className=\"absolute right-1 inline-flex size-6 items-center justify-center rounded-lt-sm hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n onClick={onClear}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;AAMA,IAAa,aAAa,eAAe,EAAE,SAAS,UAAU,CAAC;AAE/D,SAAgB,iBAAiB,EAC/B,MACA,OACA,OACA,YACA,iBAAiB,OACjB,UAAU,OACV,WACA,QACA,UACA,WAYC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,aAAa,aAAa,EAAE,yBAAyB,oBAAoB,EAAE,MAAM,CAAC;CACxF,MAAM,eAAe,UAAU,mBAAmB;CAElD,gBAAgB;EACd,SAAS,KAAK;CAChB,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,SAAS,WACX,OACE,qBAAC,UAAD;EACE,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,WAAW,GAAG;EAC5B,UAAU;EACH;EACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YANlD;GAQE,oBAAC,UAAD;IAAQ,OAAM;cAAI,EAAE,oBAAoB,KAAK;GAAU,CAAA;GACvD,oBAAC,UAAD;IAAQ,OAAM;cAAQ,EAAE,qBAAqB,MAAM;GAAU,CAAA;GAC7D,oBAAC,UAAD;IAAQ,OAAM;cAAS,EAAE,sBAAsB,OAAO;GAAU,CAAA;EAC1D;;CAIZ,IAAI,SAAS,QACX,OACE,oBAAC,SAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,WAAW,GAAG;EAC5B,UAAU;EACV,OAAO;EACP,WAAW,UAAU;GACnB,SAAS,MAAM,OAAO,KAAK;GAC3B,SAAS,MAAM,OAAO,KAAK;EAC7B;CACD,CAAA;CAIL,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,kBACC,oBAAC,MAAD;IACE,MAAK;IACL,eAAY;IACZ,WAAU;GACX,CAAA;GAEH,oBAAC,SAAD;IACE,MAAM,SAAS,WAAW,WAAW;IACrC,cAAY;IACZ,aAAW;IACX,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,iBAAiB,SAAS,GAAG,GAAG,UAAU,SAAS;IAC/F,UAAU;IACV,OAAO;IACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;IAChD,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,SAChB,SAAS,KAAK;IAElB;IACA,cAAc;KACZ,IAAI,UAAU,OACZ,SAAS,KAAK;IAElB;GACD,CAAA;GACA,WAAW,UAAU,MACpB,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,EAAE,sBAAsB,0BAA0B,EAAE,MAAM,CAAC;IACvE,aAAW,SAAS,GAAG,OAAO,UAAU,KAAA;IACxC,WAAU;IACV,UAAU;IACV,SAAS;cAET,oBAAC,MAAD;KAAM,MAAK;KAAI,eAAY;KAAO,WAAU;IAAmB,CAAA;GACzD,CAAA;EAEP;;AAET"}
@@ -5,7 +5,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
5
5
  const { t } = useT("lattice");
6
6
  return /* @__PURE__ */ jsxs("div", {
7
7
  className: "flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm",
8
- children: [/* @__PURE__ */ jsx("span", { children: pagination.total == null ? t("pagination.page", "Page {{page}}", { page: currentPage }) : t("pagination.showing", "Showing {{from}}-{{to}} of {{total}}", {
8
+ children: [/* @__PURE__ */ jsx("span", { children: pagination.total == null ? t("table.pagination.page", "Page {{page}}", { page: currentPage }) : t("table.pagination.showing", "Showing {{from}}-{{to}} of {{total}}", {
9
9
  from: pagination.from ?? 0,
10
10
  to: pagination.to ?? 0,
11
11
  total: pagination.total
@@ -18,10 +18,10 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
18
18
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
19
19
  disabled: processing,
20
20
  onClick: onLoadMore,
21
- children: processing ? t("pagination.loading", "Loading...") : t("pagination.loadMore", "Load more")
21
+ children: processing ? t("table.pagination.loading", "Loading...") : t("table.pagination.loadMore", "Load more")
22
22
  }) : /* @__PURE__ */ jsx("span", {
23
23
  className: "text-lt-muted-fg",
24
- children: t("pagination.allLoaded", "All rows loaded")
24
+ children: t("table.pagination.allLoaded", "All rows loaded")
25
25
  })
26
26
  }) : mode === "simple" ? /* @__PURE__ */ jsxs("div", {
27
27
  className: "flex items-center gap-2",
@@ -31,14 +31,14 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
31
31
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
32
32
  disabled: processing || currentPage <= 1,
33
33
  onClick: () => onPage(currentPage - 1),
34
- children: t("pagination.previous", "Previous")
34
+ children: t("table.pagination.previous", "Previous")
35
35
  }), /* @__PURE__ */ jsx("button", {
36
36
  type: "button",
37
37
  "data-test": "pagination-next",
38
38
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
39
39
  disabled: processing || !hasNextPage,
40
40
  onClick: () => onPage(currentPage + 1),
41
- children: t("pagination.next", "Next")
41
+ children: t("table.pagination.next", "Next")
42
42
  })]
43
43
  }) : mode === "table" ? /* @__PURE__ */ jsxs("div", {
44
44
  className: "flex items-center gap-2",
@@ -49,7 +49,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
49
49
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
50
50
  disabled: processing || currentPage <= 1,
51
51
  onClick: () => onPage(currentPage - 1),
52
- children: t("pagination.previous", "Previous")
52
+ children: t("table.pagination.previous", "Previous")
53
53
  }),
54
54
  visiblePages.map((pageNumber) => /* @__PURE__ */ jsx("button", {
55
55
  type: "button",
@@ -57,7 +57,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
57
57
  className: "inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50",
58
58
  disabled: processing || pageNumber === currentPage,
59
59
  "aria-current": pageNumber === currentPage ? "page" : void 0,
60
- "aria-label": t("pagination.page", "Page {{page}}", { page: pageNumber }),
60
+ "aria-label": t("table.pagination.page", "Page {{page}}", { page: pageNumber }),
61
61
  onClick: () => onPage(pageNumber),
62
62
  children: pageNumber
63
63
  }, pageNumber)),
@@ -67,7 +67,7 @@ function TablePagination({ pagination, currentPage, processing, mode, hasNextPag
67
67
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
68
68
  disabled: processing || !hasNextPage,
69
69
  onClick: () => onPage(currentPage + 1),
70
- children: t("pagination.next", "Next")
70
+ children: t("table.pagination.next", "Next")
71
71
  })
72
72
  ]
73
73
  }) : null]
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { PaginationType } from \"@lattice-php/lattice/types/generated\";\nimport type { TablePagination as TablePaginationData } from \"../types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\">\n <span>\n {pagination.total == null\n ? t(\"pagination.page\", \"Page {{page}}\", { page: currentPage })\n : t(\"pagination.showing\", \"Showing {{from}}-{{to}} of {{total}}\", {\n from: pagination.from ?? 0,\n to: pagination.to ?? 0,\n total: pagination.total,\n })}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <button\n type=\"button\"\n data-test=\"pagination-load-more\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing}\n onClick={onLoadMore}\n >\n {processing\n ? t(\"pagination.loading\", \"Loading...\")\n : t(\"pagination.loadMore\", \"Load more\")}\n </button>\n ) : (\n <span className=\"text-lt-muted-fg\">{t(\"pagination.allLoaded\", \"All rows loaded\")}</span>\n )}\n </div>\n ) : mode === \"simple\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"pagination.previous\", \"Previous\")}\n </button>\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"pagination.next\", \"Next\")}\n </button>\n </div>\n ) : mode === \"table\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"pagination.previous\", \"Previous\")}\n </button>\n {visiblePages.map((pageNumber) => (\n <button\n key={pageNumber}\n type=\"button\"\n data-test={`pagination-page-${pageNumber}`}\n className=\"inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50\"\n disabled={processing || pageNumber === currentPage}\n aria-current={pageNumber === currentPage ? \"page\" : undefined}\n aria-label={t(\"pagination.page\", \"Page {{page}}\", { page: pageNumber })}\n onClick={() => onPage(pageNumber)}\n >\n {pageNumber}\n </button>\n ))}\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"pagination.next\", \"Next\")}\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;AAKA,SAAgB,gBAAgB,EAC9B,YACA,aACA,YACA,MACA,aACA,cACA,mBACA,QACA,cAWC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD,EAAA,UACG,WAAW,SAAS,OACjB,EAAE,mBAAmB,iBAAiB,EAAE,MAAM,YAAY,CAAC,IAC3D,EAAE,sBAAsB,wCAAwC;GAC9D,MAAM,WAAW,QAAQ;GACzB,IAAI,WAAW,MAAM;GACrB,OAAO,WAAW;EACpB,CAAC,EACD,CAAA,GACL,SAAS,aACR,oBAAC,OAAD;GAAK,KAAK;GAAmB,WAAU;aACpC,WAAW,UACV,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU;IACV,SAAS;cAER,aACG,EAAE,sBAAsB,YAAY,IACpC,EAAE,uBAAuB,WAAW;GAClC,CAAA,IAER,oBAAC,QAAD;IAAM,WAAU;cAAoB,EAAE,wBAAwB,iBAAiB;GAAQ,CAAA;EAEtF,CAAA,IACH,SAAS,WACX,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,eAAe;IACvC,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,uBAAuB,UAAU;GAC9B,CAAA,GACR,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,CAAC;IACzB,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,mBAAmB,MAAM;GACtB,CAAA,CACL;OACH,SAAS,UACX,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,uBAAuB,UAAU;IAC9B,CAAA;IACP,aAAa,KAAK,eACjB,oBAAC,UAAD;KAEE,MAAK;KACL,aAAW,mBAAmB;KAC9B,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,gBAAc,eAAe,cAAc,SAAS,KAAA;KACpD,cAAY,EAAE,mBAAmB,iBAAiB,EAAE,MAAM,WAAW,CAAC;KACtE,eAAe,OAAO,UAAU;eAE/B;IACK,GAVD,UAUC,CACT;IACD,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,CAAC;KACzB,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,mBAAmB,MAAM;IACtB,CAAA;GACL;OACH,IACD;;AAET"}
1
+ {"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { PaginationType } from \"@lattice-php/lattice/types/generated\";\nimport type { TablePagination as TablePaginationData } from \"../types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\">\n <span>\n {pagination.total == null\n ? t(\"table.pagination.page\", \"Page {{page}}\", { page: currentPage })\n : t(\"table.pagination.showing\", \"Showing {{from}}-{{to}} of {{total}}\", {\n from: pagination.from ?? 0,\n to: pagination.to ?? 0,\n total: pagination.total,\n })}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <button\n type=\"button\"\n data-test=\"pagination-load-more\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing}\n onClick={onLoadMore}\n >\n {processing\n ? t(\"table.pagination.loading\", \"Loading...\")\n : t(\"table.pagination.loadMore\", \"Load more\")}\n </button>\n ) : (\n <span className=\"text-lt-muted-fg\">\n {t(\"table.pagination.allLoaded\", \"All rows loaded\")}\n </span>\n )}\n </div>\n ) : mode === \"simple\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"table.pagination.previous\", \"Previous\")}\n </button>\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"table.pagination.next\", \"Next\")}\n </button>\n </div>\n ) : mode === \"table\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"table.pagination.previous\", \"Previous\")}\n </button>\n {visiblePages.map((pageNumber) => (\n <button\n key={pageNumber}\n type=\"button\"\n data-test={`pagination-page-${pageNumber}`}\n className=\"inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50\"\n disabled={processing || pageNumber === currentPage}\n aria-current={pageNumber === currentPage ? \"page\" : undefined}\n aria-label={t(\"table.pagination.page\", \"Page {{page}}\", { page: pageNumber })}\n onClick={() => onPage(pageNumber)}\n >\n {pageNumber}\n </button>\n ))}\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"table.pagination.next\", \"Next\")}\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;AAKA,SAAgB,gBAAgB,EAC9B,YACA,aACA,YACA,MACA,aACA,cACA,mBACA,QACA,cAWC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD,EAAA,UACG,WAAW,SAAS,OACjB,EAAE,yBAAyB,iBAAiB,EAAE,MAAM,YAAY,CAAC,IACjE,EAAE,4BAA4B,wCAAwC;GACpE,MAAM,WAAW,QAAQ;GACzB,IAAI,WAAW,MAAM;GACrB,OAAO,WAAW;EACpB,CAAC,EACD,CAAA,GACL,SAAS,aACR,oBAAC,OAAD;GAAK,KAAK;GAAmB,WAAU;aACpC,WAAW,UACV,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU;IACV,SAAS;cAER,aACG,EAAE,4BAA4B,YAAY,IAC1C,EAAE,6BAA6B,WAAW;GACxC,CAAA,IAER,oBAAC,QAAD;IAAM,WAAU;cACb,EAAE,8BAA8B,iBAAiB;GAC9C,CAAA;EAEL,CAAA,IACH,SAAS,WACX,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,eAAe;IACvC,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,6BAA6B,UAAU;GACpC,CAAA,GACR,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,CAAC;IACzB,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,yBAAyB,MAAM;GAC5B,CAAA,CACL;OACH,SAAS,UACX,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,6BAA6B,UAAU;IACpC,CAAA;IACP,aAAa,KAAK,eACjB,oBAAC,UAAD;KAEE,MAAK;KACL,aAAW,mBAAmB;KAC9B,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,gBAAc,eAAe,cAAc,SAAS,KAAA;KACpD,cAAY,EAAE,yBAAyB,iBAAiB,EAAE,MAAM,WAAW,CAAC;KAC5E,eAAe,OAAO,UAAU;eAE/B;IACK,GAVD,UAUC,CACT;IACD,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,CAAC;KACzB,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,yBAAyB,MAAM;IAC5B,CAAA;GACL;OACH,IACD;;AAET"}
@@ -66,11 +66,11 @@ var TableComponent = ({ node }) => {
66
66
  "data-lattice-component": node.id,
67
67
  className: "relative",
68
68
  children: [hasOverrides && /* @__PURE__ */ jsx("button", {
69
- "aria-label": t("a11y.resetColumnWidths", "Reset column widths"),
69
+ "aria-label": t("table.resetColumnWidths", "Reset column widths"),
70
70
  className: "absolute right-1 top-1 z-10 hidden rounded-lt-sm p-1 text-lt-muted-fg hover:text-lt-fg md:inline-flex",
71
71
  "data-test": "table-reset-columns",
72
72
  onClick: resetColumns,
73
- title: t("a11y.resetColumnWidths", "Reset column widths"),
73
+ title: t("table.resetColumnWidths", "Reset column widths"),
74
74
  type: "button",
75
75
  children: /* @__PURE__ */ jsx(Icon, {
76
76
  name: "rotate-ccw",
@@ -124,7 +124,7 @@ var TableComponent = ({ node }) => {
124
124
  className: "flex items-center px-4 py-3",
125
125
  role: "columnheader",
126
126
  children: /* @__PURE__ */ jsx(Checkbox, {
127
- "aria-label": t("a11y.selectAllRows", "Select all rows"),
127
+ "aria-label": t("table.selectAllRows", "Select all rows"),
128
128
  "data-test": "select-all",
129
129
  checked: selection.allSelected,
130
130
  onCheckedChange: () => selection.toggleAll()
@@ -207,7 +207,7 @@ var TableComponent = ({ node }) => {
207
207
  className: "flex items-center p-4",
208
208
  role: "cell",
209
209
  children: /* @__PURE__ */ jsx(Checkbox, {
210
- "aria-label": t("a11y.selectRow", "Select row {{key}}", { key }),
210
+ "aria-label": t("table.selectRow", "Select row {{key}}", { key }),
211
211
  "data-test": `select-row-${key}`,
212
212
  checked: selection.isSelected(key),
213
213
  onCheckedChange: () => selection.toggle(key)
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","names":[],"sources":["../../../resources/js/table/components/table.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useColumnResizing } from \"@lattice-php/lattice/core/use-column-resizing\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"../align\";\nimport type { TableNode } from \"../types\";\nimport { getBulkActions } from \"../bulk\";\nimport { flattenColumns, getRowActions, getRowKey } from \"../payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"../query\";\nimport { useTable } from \"../use-table\";\nimport { useTableSelection } from \"../use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { FilterBar, FilterMenu } from \"./filter-bar\";\nimport { FilterStackBar } from \"./filter-stack-bar\";\nimport { TablePagination } from \"./pagination\";\nimport { SortBar } from \"./sort-bar\";\nimport { TableActionNode } from \"./table-action-node\";\nimport { ColumnCell } from \"./table-cell\";\n\nconst TableComponent = ({ node }: { children?: ReactNode; node: TableNode }) => {\n const { t } = useT(\"lattice\");\n const {\n columns,\n rows,\n pagination,\n state,\n filters,\n tableFilters,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n } = useTable(node);\n\n const bulkActions = useMemo(\n () => getBulkActions(node.props?.bulkActions),\n [node.props?.bulkActions],\n );\n const hasBulkActions = bulkActions.length > 0;\n const rowEntries = useMemo(\n () =>\n rows.map((row, index) => ({ row, actions: getRowActions(row), key: getRowKey(row, index) })),\n [rows],\n );\n const selection = useTableSelection(rowEntries.map((entry) => entry.key));\n\n const columnsByKey = useMemo(\n () => new Map(flattenColumns(columns).map((column) => [column.key, column])),\n [columns],\n );\n const currentPage = pagination.currentPage ?? state.page;\n const lastPage = pagination.lastPage ?? currentPage;\n const mode = pagination.mode ?? \"table\";\n const visiblePages = getVisiblePages(currentPage, lastPage);\n const hasNextPage = pagination.hasMore ?? currentPage < lastPage;\n const hasActions = rowEntries.some((entry) => entry.actions.length > 0);\n const striped = node.props?.striped === true;\n const hasFilters = columns.some((column) => column.filter?.enabled);\n const filterEntries = filters.map((clause, index) => ({ clause, index }));\n const filterDefinitions = useMemo(\n () => (Array.isArray(node.props?.filters) ? node.props.filters : []),\n [node.props?.filters],\n );\n const hasDedicatedFilters = filterDefinitions.length > 0;\n const hasActiveFilters = filters.length > 0 || Object.keys(tableFilters).length > 0;\n const hasTrailingUtility = hasActions || hasDedicatedFilters;\n const sizingColumns = useMemo(() => getTableSizingColumns(columns), [columns]);\n const utilityTracks = useMemo(\n () => getTableUtilityTracks(hasTrailingUtility, hasBulkActions),\n [hasTrailingUtility, hasBulkActions],\n );\n const resizingEnabled = node.props?.resizableColumns === true;\n const resizeStorageIdentity = nodeIdentity(node);\n const { getResizeHandleProps, gridTemplateColumns, hasOverrides, resetColumns } =\n useColumnResizing({\n columns: sizingColumns,\n enabled: resizingEnabled,\n leadingTracks: utilityTracks.leadingTracks,\n showIndicator: node.props?.resizeIndicator === true,\n storageKey:\n resizingEnabled && resizeStorageIdentity\n ? `lattice:table-columns:${resizeStorageIdentity}`\n : undefined,\n trailingTracks: utilityTracks.trailingTracks,\n });\n\n return (\n <div data-lattice-component={node.id} className=\"relative\">\n {hasOverrides && (\n <button\n aria-label={t(\"a11y.resetColumnWidths\", \"Reset column widths\")}\n className=\"absolute right-1 top-1 z-10 hidden rounded-lt-sm p-1 text-lt-muted-fg hover:text-lt-fg md:inline-flex\"\n data-test=\"table-reset-columns\"\n onClick={resetColumns}\n title={t(\"a11y.resetColumnWidths\", \"Reset column widths\")}\n type=\"button\"\n >\n <Icon name=\"rotate-ccw\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n <div className=\"overflow-x-auto rounded-lt-sm border border-lt-border\">\n {hasDedicatedFilters && hasActiveFilters && (\n <FilterBar\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n hasActiveFilters={hasActiveFilters}\n onChange={setTableFilter}\n onReset={resetFilters}\n />\n )}\n {hasBulkActions && selection.active && (\n <BulkBar\n actions={bulkActions}\n selectedKeys={selection.selectedKeys}\n allMatching={selection.allMatching}\n total={pagination.total ?? undefined}\n query={getQueryParams(state)}\n canSelectAllMatching={\n selection.allVisibleSelected &&\n !selection.allMatching &&\n pagination.total != null &&\n pagination.total > selection.selectedKeys.length\n }\n onSelectAllMatching={selection.selectAllMatching}\n onCompleted={selection.clear}\n />\n )}\n {filters.length > 0 && (\n <FilterStackBar\n filters={filters}\n columnsByKey={columnsByKey}\n processing={processing}\n onRemove={removeFilter}\n />\n )}\n {state.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n state={state}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div className=\"min-w-full text-base\" role=\"table\">\n <div className=\"border-b border-lt-border bg-lt-muted/50\" role=\"rowgroup\">\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && (\n <div className=\"flex items-center px-4 py-3\" role=\"columnheader\">\n <Checkbox\n aria-label={t(\"a11y.selectAllRows\", \"Select all rows\")}\n data-test=\"select-all\"\n checked={selection.allSelected}\n onCheckedChange={() => selection.toggleAll()}\n />\n </div>\n )}\n {columns.map((column, index) => (\n <ColumnHeader\n column={column}\n key={column.key}\n processing={processing}\n resizeHandleProps={\n resizingEnabled ? getResizeHandleProps(sizingColumns[index]) : undefined\n }\n sort={sort}\n state={state}\n />\n ))}\n {hasTrailingUtility && (\n <div\n className=\"flex items-center justify-end gap-2 px-4 py-2 align-middle font-semibold text-lt-fg\"\n role=\"columnheader\"\n >\n {hasDedicatedFilters && (\n <FilterMenu\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n onChange={setTableFilter}\n onSearch={searchFilterOptions}\n />\n )}\n {hasActions && <span className=\"sr-only\">{node.props?.actionsLabel}</span>}\n </div>\n )}\n </div>\n {hasFilters && (\n <div\n className=\"hidden min-w-full border-t border-lt-border md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {columns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.filter?.enabled && (\n <ColumnFilterControl\n column={column}\n clauses={filterEntries.filter((entry) => entry.clause.field === column.key)}\n processing={processing}\n onAdd={addFilter}\n onUpdate={updateFilter}\n onRemove={removeFilter}\n onReplace={replaceColumnFilters}\n onSearch={(query) => searchFilterOptions(column.key, query)}\n />\n )}\n </div>\n ))}\n {hasTrailingUtility && <div className=\"px-4 py-2\" role=\"cell\" />}\n </div>\n )}\n </div>\n <div role=\"rowgroup\">\n {!hasLoaded ? (\n <div className=\"p-4 text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{t(\"table.loading\", \"Loading rows...\")}</div>\n </div>\n ) : rowEntries.length === 0 ? (\n <div className=\"p-8 text-center text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{node.props?.emptyLabel}</div>\n </div>\n ) : (\n rowEntries.map(({ row, actions, key }) => {\n return (\n <div\n key={key}\n className={`grid grid-cols-1 border-b border-lt-border last:border-b-0 md:grid-cols-[var(--lattice-table-columns)] ${\n striped ? \"odd:bg-lt-muted/30\" : \"\"\n }`}\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && (\n <div className=\"flex items-center p-4\" role=\"cell\">\n <Checkbox\n aria-label={t(\"a11y.selectRow\", \"Select row {{key}}\", { key })}\n data-test={`select-row-${key}`}\n checked={selection.isSelected(key)}\n onCheckedChange={() => selection.toggle(key)}\n />\n </div>\n )}\n {columns.map((column) => (\n <div\n key={column.key}\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden p-4 align-middle\",\n alignText(column.align),\n alignJustifyItems(column.align),\n )}\n role=\"cell\"\n >\n <span\n aria-hidden=\"true\"\n className=\"text-xs font-medium text-lt-muted-fg md:hidden\"\n >\n {column.label}\n </span>\n <div\n data-slot=\"table-cell-content\"\n className=\"min-w-0 max-w-full overflow-hidden truncate\"\n >\n <ColumnCell column={column} row={row} />\n </div>\n </div>\n ))}\n {hasTrailingUtility && (\n <div\n className={cn(\n \"items-center justify-start gap-2 p-4 md:justify-end\",\n actions.length > 0 ? \"flex\" : \"hidden md:flex\",\n )}\n role=\"cell\"\n >\n {actions.map((action, actionIndex) => (\n <TableActionNode\n key={action.key ?? action.id ?? actionIndex}\n node={action}\n />\n ))}\n </div>\n )}\n </div>\n );\n })\n )}\n </div>\n </div>\n {hasLoaded && (\n <TablePagination\n pagination={pagination}\n currentPage={currentPage}\n processing={processing}\n mode={mode}\n hasNextPage={hasNextPage}\n visiblePages={visiblePages}\n infiniteLoaderRef={infiniteLoaderRef}\n onPage={goToPage}\n onLoadMore={loadMore}\n />\n )}\n </div>\n </div>\n );\n};\n\nexport default TableComponent;\n"],"mappings":"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"}
1
+ {"version":3,"file":"table.js","names":[],"sources":["../../../resources/js/table/components/table.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useColumnResizing } from \"@lattice-php/lattice/core/use-column-resizing\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"../align\";\nimport type { TableNode } from \"../types\";\nimport { getBulkActions } from \"../bulk\";\nimport { flattenColumns, getRowActions, getRowKey } from \"../payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"../query\";\nimport { useTable } from \"../use-table\";\nimport { useTableSelection } from \"../use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { FilterBar, FilterMenu } from \"./filter-bar\";\nimport { FilterStackBar } from \"./filter-stack-bar\";\nimport { TablePagination } from \"./pagination\";\nimport { SortBar } from \"./sort-bar\";\nimport { TableActionNode } from \"./table-action-node\";\nimport { ColumnCell } from \"./table-cell\";\n\nconst TableComponent = ({ node }: { children?: ReactNode; node: TableNode }) => {\n const { t } = useT(\"lattice\");\n const {\n columns,\n rows,\n pagination,\n state,\n filters,\n tableFilters,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n } = useTable(node);\n\n const bulkActions = useMemo(\n () => getBulkActions(node.props?.bulkActions),\n [node.props?.bulkActions],\n );\n const hasBulkActions = bulkActions.length > 0;\n const rowEntries = useMemo(\n () =>\n rows.map((row, index) => ({ row, actions: getRowActions(row), key: getRowKey(row, index) })),\n [rows],\n );\n const selection = useTableSelection(rowEntries.map((entry) => entry.key));\n\n const columnsByKey = useMemo(\n () => new Map(flattenColumns(columns).map((column) => [column.key, column])),\n [columns],\n );\n const currentPage = pagination.currentPage ?? state.page;\n const lastPage = pagination.lastPage ?? currentPage;\n const mode = pagination.mode ?? \"table\";\n const visiblePages = getVisiblePages(currentPage, lastPage);\n const hasNextPage = pagination.hasMore ?? currentPage < lastPage;\n const hasActions = rowEntries.some((entry) => entry.actions.length > 0);\n const striped = node.props?.striped === true;\n const hasFilters = columns.some((column) => column.filter?.enabled);\n const filterEntries = filters.map((clause, index) => ({ clause, index }));\n const filterDefinitions = useMemo(\n () => (Array.isArray(node.props?.filters) ? node.props.filters : []),\n [node.props?.filters],\n );\n const hasDedicatedFilters = filterDefinitions.length > 0;\n const hasActiveFilters = filters.length > 0 || Object.keys(tableFilters).length > 0;\n const hasTrailingUtility = hasActions || hasDedicatedFilters;\n const sizingColumns = useMemo(() => getTableSizingColumns(columns), [columns]);\n const utilityTracks = useMemo(\n () => getTableUtilityTracks(hasTrailingUtility, hasBulkActions),\n [hasTrailingUtility, hasBulkActions],\n );\n const resizingEnabled = node.props?.resizableColumns === true;\n const resizeStorageIdentity = nodeIdentity(node);\n const { getResizeHandleProps, gridTemplateColumns, hasOverrides, resetColumns } =\n useColumnResizing({\n columns: sizingColumns,\n enabled: resizingEnabled,\n leadingTracks: utilityTracks.leadingTracks,\n showIndicator: node.props?.resizeIndicator === true,\n storageKey:\n resizingEnabled && resizeStorageIdentity\n ? `lattice:table-columns:${resizeStorageIdentity}`\n : undefined,\n trailingTracks: utilityTracks.trailingTracks,\n });\n\n return (\n <div data-lattice-component={node.id} className=\"relative\">\n {hasOverrides && (\n <button\n aria-label={t(\"table.resetColumnWidths\", \"Reset column widths\")}\n className=\"absolute right-1 top-1 z-10 hidden rounded-lt-sm p-1 text-lt-muted-fg hover:text-lt-fg md:inline-flex\"\n data-test=\"table-reset-columns\"\n onClick={resetColumns}\n title={t(\"table.resetColumnWidths\", \"Reset column widths\")}\n type=\"button\"\n >\n <Icon name=\"rotate-ccw\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n <div className=\"overflow-x-auto rounded-lt-sm border border-lt-border\">\n {hasDedicatedFilters && hasActiveFilters && (\n <FilterBar\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n hasActiveFilters={hasActiveFilters}\n onChange={setTableFilter}\n onReset={resetFilters}\n />\n )}\n {hasBulkActions && selection.active && (\n <BulkBar\n actions={bulkActions}\n selectedKeys={selection.selectedKeys}\n allMatching={selection.allMatching}\n total={pagination.total ?? undefined}\n query={getQueryParams(state)}\n canSelectAllMatching={\n selection.allVisibleSelected &&\n !selection.allMatching &&\n pagination.total != null &&\n pagination.total > selection.selectedKeys.length\n }\n onSelectAllMatching={selection.selectAllMatching}\n onCompleted={selection.clear}\n />\n )}\n {filters.length > 0 && (\n <FilterStackBar\n filters={filters}\n columnsByKey={columnsByKey}\n processing={processing}\n onRemove={removeFilter}\n />\n )}\n {state.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n state={state}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div className=\"min-w-full text-base\" role=\"table\">\n <div className=\"border-b border-lt-border bg-lt-muted/50\" role=\"rowgroup\">\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && (\n <div className=\"flex items-center px-4 py-3\" role=\"columnheader\">\n <Checkbox\n aria-label={t(\"table.selectAllRows\", \"Select all rows\")}\n data-test=\"select-all\"\n checked={selection.allSelected}\n onCheckedChange={() => selection.toggleAll()}\n />\n </div>\n )}\n {columns.map((column, index) => (\n <ColumnHeader\n column={column}\n key={column.key}\n processing={processing}\n resizeHandleProps={\n resizingEnabled ? getResizeHandleProps(sizingColumns[index]) : undefined\n }\n sort={sort}\n state={state}\n />\n ))}\n {hasTrailingUtility && (\n <div\n className=\"flex items-center justify-end gap-2 px-4 py-2 align-middle font-semibold text-lt-fg\"\n role=\"columnheader\"\n >\n {hasDedicatedFilters && (\n <FilterMenu\n filters={filterDefinitions}\n values={tableFilters}\n processing={processing}\n onChange={setTableFilter}\n onSearch={searchFilterOptions}\n />\n )}\n {hasActions && <span className=\"sr-only\">{node.props?.actionsLabel}</span>}\n </div>\n )}\n </div>\n {hasFilters && (\n <div\n className=\"hidden min-w-full border-t border-lt-border md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {columns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.filter?.enabled && (\n <ColumnFilterControl\n column={column}\n clauses={filterEntries.filter((entry) => entry.clause.field === column.key)}\n processing={processing}\n onAdd={addFilter}\n onUpdate={updateFilter}\n onRemove={removeFilter}\n onReplace={replaceColumnFilters}\n onSearch={(query) => searchFilterOptions(column.key, query)}\n />\n )}\n </div>\n ))}\n {hasTrailingUtility && <div className=\"px-4 py-2\" role=\"cell\" />}\n </div>\n )}\n </div>\n <div role=\"rowgroup\">\n {!hasLoaded ? (\n <div className=\"p-4 text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{t(\"table.loading\", \"Loading rows...\")}</div>\n </div>\n ) : rowEntries.length === 0 ? (\n <div className=\"p-8 text-center text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{node.props?.emptyLabel}</div>\n </div>\n ) : (\n rowEntries.map(({ row, actions, key }) => {\n return (\n <div\n key={key}\n className={`grid grid-cols-1 border-b border-lt-border last:border-b-0 md:grid-cols-[var(--lattice-table-columns)] ${\n striped ? \"odd:bg-lt-muted/30\" : \"\"\n }`}\n role=\"row\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n {hasBulkActions && (\n <div className=\"flex items-center p-4\" role=\"cell\">\n <Checkbox\n aria-label={t(\"table.selectRow\", \"Select row {{key}}\", { key })}\n data-test={`select-row-${key}`}\n checked={selection.isSelected(key)}\n onCheckedChange={() => selection.toggle(key)}\n />\n </div>\n )}\n {columns.map((column) => (\n <div\n key={column.key}\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden p-4 align-middle\",\n alignText(column.align),\n alignJustifyItems(column.align),\n )}\n role=\"cell\"\n >\n <span\n aria-hidden=\"true\"\n className=\"text-xs font-medium text-lt-muted-fg md:hidden\"\n >\n {column.label}\n </span>\n <div\n data-slot=\"table-cell-content\"\n className=\"min-w-0 max-w-full overflow-hidden truncate\"\n >\n <ColumnCell column={column} row={row} />\n </div>\n </div>\n ))}\n {hasTrailingUtility && (\n <div\n className={cn(\n \"items-center justify-start gap-2 p-4 md:justify-end\",\n actions.length > 0 ? \"flex\" : \"hidden md:flex\",\n )}\n role=\"cell\"\n >\n {actions.map((action, actionIndex) => (\n <TableActionNode\n key={action.key ?? action.id ?? actionIndex}\n node={action}\n />\n ))}\n </div>\n )}\n </div>\n );\n })\n )}\n </div>\n </div>\n {hasLoaded && (\n <TablePagination\n pagination={pagination}\n currentPage={currentPage}\n processing={processing}\n mode={mode}\n hasNextPage={hasNextPage}\n visiblePages={visiblePages}\n infiniteLoaderRef={infiniteLoaderRef}\n onPage={goToPage}\n onLoadMore={loadMore}\n />\n )}\n </div>\n </div>\n );\n};\n\nexport default TableComponent;\n"],"mappings":"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"}
@@ -91,7 +91,7 @@ var operatorLabels = {
91
91
  };
92
92
  var VALUELESS_FILTER_OPERATORS = new Set(["empty", "filled"]);
93
93
  function operatorLabel(operator) {
94
- return translate("lattice", `operators.${operator}`, operatorLabels[operator] ?? operator);
94
+ return translate("lattice", `table.operators.${operator}`, operatorLabels[operator] ?? operator);
95
95
  }
96
96
  function getSortDirectionLabel(direction) {
97
97
  return direction === "desc" ? "descending" : "ascending";
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","names":[],"sources":["../../resources/js/table/query.ts"],"sourcesContent":["import { translate } from \"@lattice-php/lattice/i18n\";\nimport { DEFAULT_COLUMN_WIDTH } from \"@lattice-php/lattice/core/column-sizing\";\nimport type { ColumnWidth } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyMember } from \"./filter-values\";\nimport type { TableColumn, TableSort, TableState } from \"./types\";\n\nexport function getColumnSort(state: TableState, column: TableColumn): TableSort | undefined {\n return state.sorts.find((currentSort) => currentSort.key === column.key);\n}\n\nexport function getColumnAriaSort(\n sort: TableSort | undefined,\n): \"ascending\" | \"descending\" | undefined {\n if (sort?.direction === \"asc\") {\n return \"ascending\";\n }\n\n if (sort?.direction === \"desc\") {\n return \"descending\";\n }\n\n return undefined;\n}\n\nexport function buildEndpoint(endpoint: string, state: TableState): string {\n const url = new URL(endpoint, window.location.origin);\n\n if (state.filters.length > 0) {\n url.searchParams.set(\"filter\", serializeFilters(state));\n }\n\n if (state.sorts.length > 0) {\n url.searchParams.set(\"sort\", serializeSorts(state));\n }\n\n appendTableFilters(url, state.tableFilters);\n\n url.searchParams.set(\"page\", String(state.page));\n url.searchParams.set(\"per_page\", String(state.perPage));\n\n return `${url.pathname}${url.search}`;\n}\n\n/**\n * Serialize the dedicated table filters as Laravel-native bracket params:\n * `tf[key]=v`, repeated `tf[key][]=v` for multi-value, and `tf[key][sub]=v`\n * for structured values (e.g. a date range's from/until). Empty values are\n * dropped so an unset filter never reaches the server.\n */\nfunction appendTableFilters(url: URL, tableFilters: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(getTableFilterParams(tableFilters))) {\n if (typeof value === \"string\") {\n url.searchParams.set(`tf[${key}]`, value);\n\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (!isEmptyMember(item)) {\n url.searchParams.append(`tf[${key}][]`, String(item));\n }\n }\n\n continue;\n }\n\n if (typeof value === \"object\" && value !== null) {\n for (const [subKey, subValue] of Object.entries(value as Record<string, unknown>)) {\n url.searchParams.set(`tf[${key}][${subKey}]`, String(subValue));\n }\n }\n }\n}\n\nfunction getTableFilterParams(tableFilters: Record<string, unknown>): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(tableFilters)) {\n const normalized = normalizeTableFilterValue(value);\n\n if (normalized !== undefined) {\n params[key] = normalized;\n }\n }\n\n return params;\n}\n\nfunction normalizeTableFilterValue(value: unknown): unknown | undefined {\n if (isEmptyMember(value)) {\n return undefined;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const items = value.filter((item) => !isEmptyMember(item)).map(String);\n\n return items.length > 0 ? items : undefined;\n }\n\n if (typeof value === \"object\") {\n const entries = Object.entries(value)\n .filter(([, subValue]) => !isEmptyMember(subValue))\n .map(([subKey, subValue]) => [subKey, String(subValue)]);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n }\n\n return String(value);\n}\n\nexport function getQueryParams(state: TableState): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (state.filters.length > 0) {\n params.filter = serializeFilters(state);\n }\n\n if (state.sorts.length > 0) {\n params.sort = serializeSorts(state);\n }\n\n const tableFilters = getTableFilterParams(state.tableFilters);\n\n if (Object.keys(tableFilters).length > 0) {\n params.tf = tableFilters;\n }\n\n return params;\n}\n\nfunction serializeFilters(state: TableState): string {\n return state.filters\n .map((clause) => `${clause.field}:${clause.operator}:${encodeURIComponent(clause.value)}`)\n .join(\",\");\n}\n\nfunction serializeSorts(state: TableState): string {\n return state.sorts\n .map((sort) => (sort.direction === \"desc\" ? `-${sort.key}` : sort.key))\n .join(\",\");\n}\n\nconst operatorLabels: Record<string, string> = {\n contains: \"contains\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n eq: \"equals\",\n neq: \"not equals\",\n gt: \">\",\n gte: \"≥\",\n lt: \"<\",\n lte: \"≤\",\n in: \"in\",\n not_in: \"not in\",\n before: \"before\",\n after: \"after\",\n empty: \"is empty\",\n filled: \"is not empty\",\n};\n\nexport const VALUELESS_FILTER_OPERATORS = new Set<string>([\"empty\", \"filled\"]);\n\nexport function operatorLabel(operator: string): string {\n return translate(\"lattice\", `operators.${operator}`, operatorLabels[operator] ?? operator);\n}\n\nexport function getSortDirectionLabel(direction: string): string {\n return direction === \"desc\" ? \"descending\" : \"ascending\";\n}\n\nexport function nextSort(sorts: TableSort[], column: TableColumn): TableSort[] {\n if (!column.sortable) {\n return sorts;\n }\n\n const currentSort = sorts.find((sort) => sort.key === column.key);\n const remainingSorts = sorts.filter((sort) => sort.key !== column.key);\n\n if (!currentSort) {\n return [...sorts, { key: column.key, direction: \"asc\" }];\n }\n\n if (currentSort.direction === \"asc\") {\n return [...remainingSorts, { key: column.key, direction: \"desc\" }];\n }\n\n return remainingSorts;\n}\n\nexport function getVisiblePages(currentPage: number, lastPage: number): number[] {\n if (lastPage <= 5) {\n return Array.from({ length: lastPage }, (_, index) => index + 1);\n }\n\n const start = Math.max(1, Math.min(currentPage - 2, lastPage - 4));\n\n return Array.from({ length: 5 }, (_, index) => start + index);\n}\n\nexport function getTableSizingColumns(columns: TableColumn[]) {\n return columns.map((column) => ({\n key: column.key,\n label: column.label,\n width: columnWidthOrDefault(column),\n }));\n}\n\nfunction columnWidthOrDefault(column: TableColumn): ColumnWidth {\n return (column.width ??\n (column.type === \"column.stack\" ? \"xl\" : DEFAULT_COLUMN_WIDTH)) as ColumnWidth;\n}\n\nexport function getTableUtilityTracks(hasActions: boolean, hasSelection: boolean) {\n // Utility tracks are fixed because the independent header/filter/body grids would drift with content-sized tracks.\n return {\n leadingTracks: hasSelection ? [\"3rem\"] : [],\n trailingTracks: hasActions ? [\"10rem\"] : [],\n };\n}\n"],"mappings":";;;;AAMA,SAAgB,cAAc,OAAmB,QAA4C;CAC3F,OAAO,MAAM,MAAM,MAAM,gBAAgB,YAAY,QAAQ,OAAO,GAAG;AACzE;AAEA,SAAgB,kBACd,MACwC;CACxC,IAAI,MAAM,cAAc,OACtB,OAAO;CAGT,IAAI,MAAM,cAAc,QACtB,OAAO;AAIX;AAEA,SAAgB,cAAc,UAAkB,OAA2B;CACzE,MAAM,MAAM,IAAI,IAAI,UAAU,OAAO,SAAS,MAAM;CAEpD,IAAI,MAAM,QAAQ,SAAS,GACzB,IAAI,aAAa,IAAI,UAAU,iBAAiB,KAAK,CAAC;CAGxD,IAAI,MAAM,MAAM,SAAS,GACvB,IAAI,aAAa,IAAI,QAAQ,eAAe,KAAK,CAAC;CAGpD,mBAAmB,KAAK,MAAM,YAAY;CAE1C,IAAI,aAAa,IAAI,QAAQ,OAAO,MAAM,IAAI,CAAC;CAC/C,IAAI,aAAa,IAAI,YAAY,OAAO,MAAM,OAAO,CAAC;CAEtD,OAAO,GAAG,IAAI,WAAW,IAAI;AAC/B;;;;;;;AAQA,SAAS,mBAAmB,KAAU,cAA6C;CACjF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,qBAAqB,YAAY,CAAC,GAAG;EAC7E,IAAI,OAAO,UAAU,UAAU;GAC7B,IAAI,aAAa,IAAI,MAAM,IAAI,IAAI,KAAK;GAExC;EACF;EAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,cAAc,IAAI,GACrB,IAAI,aAAa,OAAO,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;GAIxD;EACF;EAEA,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,KAAK,MAAM,CAAC,QAAQ,aAAa,OAAO,QAAQ,KAAgC,GAC9E,IAAI,aAAa,IAAI,MAAM,IAAI,IAAI,OAAO,IAAI,OAAO,QAAQ,CAAC;CAGpE;AACF;AAEA,SAAS,qBAAqB,cAAgE;CAC5F,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,GAAG;EACvD,MAAM,aAAa,0BAA0B,KAAK;EAElD,IAAI,eAAe,KAAA,GACjB,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;AAEA,SAAS,0BAA0B,OAAqC;CACtE,IAAI,cAAc,KAAK,GACrB;CAGF,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC,cAAc,IAAI,CAAC,EAAE,IAAI,MAAM;EAErE,OAAO,MAAM,SAAS,IAAI,QAAQ,KAAA;CACpC;CAEA,IAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,UAAU,OAAO,QAAQ,KAAK,EACjC,QAAQ,GAAG,cAAc,CAAC,cAAc,QAAQ,CAAC,EACjD,KAAK,CAAC,QAAQ,cAAc,CAAC,QAAQ,OAAO,QAAQ,CAAC,CAAC;EAEzD,OAAO,QAAQ,SAAS,IAAI,OAAO,YAAY,OAAO,IAAI,KAAA;CAC5D;CAEA,OAAO,OAAO,KAAK;AACrB;AAEA,SAAgB,eAAe,OAA4C;CACzE,MAAM,SAAkC,CAAC;CAEzC,IAAI,MAAM,QAAQ,SAAS,GACzB,OAAO,SAAS,iBAAiB,KAAK;CAGxC,IAAI,MAAM,MAAM,SAAS,GACvB,OAAO,OAAO,eAAe,KAAK;CAGpC,MAAM,eAAe,qBAAqB,MAAM,YAAY;CAE5D,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,OAAO,KAAK;CAGd,OAAO;AACT;AAEA,SAAS,iBAAiB,OAA2B;CACnD,OAAO,MAAM,QACV,KAAK,WAAW,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,mBAAmB,OAAO,KAAK,GAAG,EACxF,KAAK,GAAG;AACb;AAEA,SAAS,eAAe,OAA2B;CACjD,OAAO,MAAM,MACV,KAAK,SAAU,KAAK,cAAc,SAAS,IAAI,KAAK,QAAQ,KAAK,GAAI,EACrE,KAAK,GAAG;AACb;AAEA,IAAM,iBAAyC;CAC7C,UAAU;CACV,aAAa;CACb,WAAW;CACX,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,QAAQ;AACV;AAEA,IAAa,6BAA6B,IAAI,IAAY,CAAC,SAAS,QAAQ,CAAC;AAE7E,SAAgB,cAAc,UAA0B;CACtD,OAAO,UAAU,WAAW,aAAa,YAAY,eAAe,aAAa,QAAQ;AAC3F;AAEA,SAAgB,sBAAsB,WAA2B;CAC/D,OAAO,cAAc,SAAS,eAAe;AAC/C;AAEA,SAAgB,SAAS,OAAoB,QAAkC;CAC7E,IAAI,CAAC,OAAO,UACV,OAAO;CAGT,MAAM,cAAc,MAAM,MAAM,SAAS,KAAK,QAAQ,OAAO,GAAG;CAChE,MAAM,iBAAiB,MAAM,QAAQ,SAAS,KAAK,QAAQ,OAAO,GAAG;CAErE,IAAI,CAAC,aACH,OAAO,CAAC,GAAG,OAAO;EAAE,KAAK,OAAO;EAAK,WAAW;CAAM,CAAC;CAGzD,IAAI,YAAY,cAAc,OAC5B,OAAO,CAAC,GAAG,gBAAgB;EAAE,KAAK,OAAO;EAAK,WAAW;CAAO,CAAC;CAGnE,OAAO;AACT;AAEA,SAAgB,gBAAgB,aAAqB,UAA4B;CAC/E,IAAI,YAAY,GACd,OAAO,MAAM,KAAK,EAAE,QAAQ,SAAS,IAAI,GAAG,UAAU,QAAQ,CAAC;CAGjE,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,cAAc,GAAG,WAAW,CAAC,CAAC;CAEjE,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,UAAU,QAAQ,KAAK;AAC9D;AAEA,SAAgB,sBAAsB,SAAwB;CAC5D,OAAO,QAAQ,KAAK,YAAY;EAC9B,KAAK,OAAO;EACZ,OAAO,OAAO;EACd,OAAO,qBAAqB,MAAM;CACpC,EAAE;AACJ;AAEA,SAAS,qBAAqB,QAAkC;CAC9D,OAAQ,OAAO,UACZ,OAAO,SAAS,iBAAiB,OAAA;AACtC;AAEA,SAAgB,sBAAsB,YAAqB,cAAuB;CAEhF,OAAO;EACL,eAAe,eAAe,CAAC,MAAM,IAAI,CAAC;EAC1C,gBAAgB,aAAa,CAAC,OAAO,IAAI,CAAC;CAC5C;AACF"}
1
+ {"version":3,"file":"query.js","names":[],"sources":["../../resources/js/table/query.ts"],"sourcesContent":["import { translate } from \"@lattice-php/lattice/i18n\";\nimport { DEFAULT_COLUMN_WIDTH } from \"@lattice-php/lattice/core/column-sizing\";\nimport type { ColumnWidth } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyMember } from \"./filter-values\";\nimport type { TableColumn, TableSort, TableState } from \"./types\";\n\nexport function getColumnSort(state: TableState, column: TableColumn): TableSort | undefined {\n return state.sorts.find((currentSort) => currentSort.key === column.key);\n}\n\nexport function getColumnAriaSort(\n sort: TableSort | undefined,\n): \"ascending\" | \"descending\" | undefined {\n if (sort?.direction === \"asc\") {\n return \"ascending\";\n }\n\n if (sort?.direction === \"desc\") {\n return \"descending\";\n }\n\n return undefined;\n}\n\nexport function buildEndpoint(endpoint: string, state: TableState): string {\n const url = new URL(endpoint, window.location.origin);\n\n if (state.filters.length > 0) {\n url.searchParams.set(\"filter\", serializeFilters(state));\n }\n\n if (state.sorts.length > 0) {\n url.searchParams.set(\"sort\", serializeSorts(state));\n }\n\n appendTableFilters(url, state.tableFilters);\n\n url.searchParams.set(\"page\", String(state.page));\n url.searchParams.set(\"per_page\", String(state.perPage));\n\n return `${url.pathname}${url.search}`;\n}\n\n/**\n * Serialize the dedicated table filters as Laravel-native bracket params:\n * `tf[key]=v`, repeated `tf[key][]=v` for multi-value, and `tf[key][sub]=v`\n * for structured values (e.g. a date range's from/until). Empty values are\n * dropped so an unset filter never reaches the server.\n */\nfunction appendTableFilters(url: URL, tableFilters: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(getTableFilterParams(tableFilters))) {\n if (typeof value === \"string\") {\n url.searchParams.set(`tf[${key}]`, value);\n\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (!isEmptyMember(item)) {\n url.searchParams.append(`tf[${key}][]`, String(item));\n }\n }\n\n continue;\n }\n\n if (typeof value === \"object\" && value !== null) {\n for (const [subKey, subValue] of Object.entries(value as Record<string, unknown>)) {\n url.searchParams.set(`tf[${key}][${subKey}]`, String(subValue));\n }\n }\n }\n}\n\nfunction getTableFilterParams(tableFilters: Record<string, unknown>): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(tableFilters)) {\n const normalized = normalizeTableFilterValue(value);\n\n if (normalized !== undefined) {\n params[key] = normalized;\n }\n }\n\n return params;\n}\n\nfunction normalizeTableFilterValue(value: unknown): unknown | undefined {\n if (isEmptyMember(value)) {\n return undefined;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const items = value.filter((item) => !isEmptyMember(item)).map(String);\n\n return items.length > 0 ? items : undefined;\n }\n\n if (typeof value === \"object\") {\n const entries = Object.entries(value)\n .filter(([, subValue]) => !isEmptyMember(subValue))\n .map(([subKey, subValue]) => [subKey, String(subValue)]);\n\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n }\n\n return String(value);\n}\n\nexport function getQueryParams(state: TableState): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (state.filters.length > 0) {\n params.filter = serializeFilters(state);\n }\n\n if (state.sorts.length > 0) {\n params.sort = serializeSorts(state);\n }\n\n const tableFilters = getTableFilterParams(state.tableFilters);\n\n if (Object.keys(tableFilters).length > 0) {\n params.tf = tableFilters;\n }\n\n return params;\n}\n\nfunction serializeFilters(state: TableState): string {\n return state.filters\n .map((clause) => `${clause.field}:${clause.operator}:${encodeURIComponent(clause.value)}`)\n .join(\",\");\n}\n\nfunction serializeSorts(state: TableState): string {\n return state.sorts\n .map((sort) => (sort.direction === \"desc\" ? `-${sort.key}` : sort.key))\n .join(\",\");\n}\n\nconst operatorLabels: Record<string, string> = {\n contains: \"contains\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n eq: \"equals\",\n neq: \"not equals\",\n gt: \">\",\n gte: \"≥\",\n lt: \"<\",\n lte: \"≤\",\n in: \"in\",\n not_in: \"not in\",\n before: \"before\",\n after: \"after\",\n empty: \"is empty\",\n filled: \"is not empty\",\n};\n\nexport const VALUELESS_FILTER_OPERATORS = new Set<string>([\"empty\", \"filled\"]);\n\nexport function operatorLabel(operator: string): string {\n return translate(\"lattice\", `table.operators.${operator}`, operatorLabels[operator] ?? operator);\n}\n\nexport function getSortDirectionLabel(direction: string): string {\n return direction === \"desc\" ? \"descending\" : \"ascending\";\n}\n\nexport function nextSort(sorts: TableSort[], column: TableColumn): TableSort[] {\n if (!column.sortable) {\n return sorts;\n }\n\n const currentSort = sorts.find((sort) => sort.key === column.key);\n const remainingSorts = sorts.filter((sort) => sort.key !== column.key);\n\n if (!currentSort) {\n return [...sorts, { key: column.key, direction: \"asc\" }];\n }\n\n if (currentSort.direction === \"asc\") {\n return [...remainingSorts, { key: column.key, direction: \"desc\" }];\n }\n\n return remainingSorts;\n}\n\nexport function getVisiblePages(currentPage: number, lastPage: number): number[] {\n if (lastPage <= 5) {\n return Array.from({ length: lastPage }, (_, index) => index + 1);\n }\n\n const start = Math.max(1, Math.min(currentPage - 2, lastPage - 4));\n\n return Array.from({ length: 5 }, (_, index) => start + index);\n}\n\nexport function getTableSizingColumns(columns: TableColumn[]) {\n return columns.map((column) => ({\n key: column.key,\n label: column.label,\n width: columnWidthOrDefault(column),\n }));\n}\n\nfunction columnWidthOrDefault(column: TableColumn): ColumnWidth {\n return (column.width ??\n (column.type === \"column.stack\" ? \"xl\" : DEFAULT_COLUMN_WIDTH)) as ColumnWidth;\n}\n\nexport function getTableUtilityTracks(hasActions: boolean, hasSelection: boolean) {\n // Utility tracks are fixed because the independent header/filter/body grids would drift with content-sized tracks.\n return {\n leadingTracks: hasSelection ? [\"3rem\"] : [],\n trailingTracks: hasActions ? [\"10rem\"] : [],\n };\n}\n"],"mappings":"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"}
@@ -45,7 +45,7 @@ function Toaster({ duration = 4e3 }) {
45
45
  }) : null]
46
46
  }),
47
47
  toast.dismissible ? /* @__PURE__ */ jsx(Toast.Close, {
48
- "aria-label": t("a11y.dismiss", "Dismiss"),
48
+ "aria-label": t("common.dismiss", "Dismiss"),
49
49
  className: "shrink-0 rounded-lt-sm p-1 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg",
50
50
  "data-test": "toast-dismiss",
51
51
  children: /* @__PURE__ */ jsx(Icon, {