@lattice-php/lattice 0.19.0 → 0.20.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 (236) hide show
  1. package/dist/core/index.js +2 -2
  2. package/dist/core/types.d.ts +16 -4
  3. package/dist/create-app.d.ts +31 -3
  4. package/dist/create-app.js +48 -10
  5. package/dist/create-app.js.map +1 -1
  6. package/dist/effects/registry.d.ts +3 -3
  7. package/dist/effects/registry.js +4 -4
  8. package/dist/effects/registry.js.map +1 -1
  9. package/dist/form/components/base/field.d.ts +2 -2
  10. package/dist/form/components/base/field.js +2 -2
  11. package/dist/form/components/base/field.js.map +1 -1
  12. package/dist/form/components/fields/color-picker-field.d.ts +2 -0
  13. package/dist/form/components/fields/color-picker-field.js +57 -0
  14. package/dist/form/components/fields/color-picker-field.js.map +1 -0
  15. package/dist/form/components/fields/date-input.js +1 -1
  16. package/dist/form/components/fields/date-picker-field.js +1 -1
  17. package/dist/form/components/fields/date-time-input.js +1 -1
  18. package/dist/form/components/fields/file-upload.js +7 -12
  19. package/dist/form/components/fields/file-upload.js.map +1 -1
  20. package/dist/form/components/fields/number-input.js +1 -1
  21. package/dist/form/components/fields/rich-editor-field.js +35 -276
  22. package/dist/form/components/fields/rich-editor-field.js.map +1 -1
  23. package/dist/form/components/fields/row-action-menu.js +2 -2
  24. package/dist/form/components/fields/row-action-menu.js.map +1 -1
  25. package/dist/form/components/fields/row-actions.js +3 -1
  26. package/dist/form/components/fields/row-actions.js.map +1 -1
  27. package/dist/form/components/fields/select.js +59 -16
  28. package/dist/form/components/fields/select.js.map +1 -1
  29. package/dist/form/components/fields/table-rows.js +2 -2
  30. package/dist/form/components/fields/table-rows.js.map +1 -1
  31. package/dist/form/components/fields/text-input.js +8 -1
  32. package/dist/form/components/fields/text-input.js.map +1 -1
  33. package/dist/form/components/fields/time-input.js +1 -1
  34. package/dist/form/components/index.d.ts +1 -0
  35. package/dist/form/components/index.js +2 -1
  36. package/dist/form/embed.d.ts +1 -0
  37. package/dist/form/embed.js +2 -1
  38. package/dist/form/hooks/use-form-resolver.js.map +1 -1
  39. package/dist/form/index.js +2 -1
  40. package/dist/form/lib/conditions.d.ts +4 -10
  41. package/dist/form/lib/conditions.js.map +1 -1
  42. package/dist/form/lib/field-props.d.ts +4 -18
  43. package/dist/form/lib/field-props.js.map +1 -1
  44. package/dist/form/plugin.js +2 -0
  45. package/dist/form/plugin.js.map +1 -1
  46. package/dist/form/rich-editor/builtins.d.ts +6 -0
  47. package/dist/form/rich-editor/builtins.js +400 -0
  48. package/dist/form/rich-editor/builtins.js.map +1 -0
  49. package/dist/form/rich-editor/index.d.ts +7 -0
  50. package/dist/form/rich-editor/index.js +3 -0
  51. package/dist/form/rich-editor/registry.d.ts +67 -0
  52. package/dist/form/rich-editor/registry.js +79 -0
  53. package/dist/form/rich-editor/registry.js.map +1 -0
  54. package/dist/form/rich-editor/toolbar-button.d.ts +12 -0
  55. package/dist/form/rich-editor/toolbar-button.js +28 -0
  56. package/dist/form/rich-editor/toolbar-button.js.map +1 -0
  57. package/dist/form/types.d.ts +1 -6
  58. package/dist/format/date-time.d.ts +3 -2
  59. package/dist/format/date-time.js.map +1 -1
  60. package/dist/i18n/backend.js +1 -1
  61. package/dist/i18n/date-time.d.ts +3 -2
  62. package/dist/i18n/date-time.js.map +1 -1
  63. package/dist/i18n/index.js +3 -2
  64. package/dist/i18n/instance.js +1 -1
  65. package/dist/i18n/page-props.d.ts +3 -2
  66. package/dist/i18n/page-props.js +1 -15
  67. package/dist/i18n/page-props.js.map +1 -1
  68. package/dist/i18n/shared-props.d.ts +7 -0
  69. package/dist/i18n/shared-props.js +25 -0
  70. package/dist/i18n/shared-props.js.map +1 -0
  71. package/dist/index.d.ts +5 -3
  72. package/dist/index.js +7 -6
  73. package/dist/lattice.css +107 -47
  74. package/dist/layout/components/breadcrumbs.js +3 -1
  75. package/dist/layout/components/breadcrumbs.js.map +1 -1
  76. package/dist/layout/components/callouts.js +1 -1
  77. package/dist/lib/color.d.ts +9 -0
  78. package/dist/lib/color.js +48 -0
  79. package/dist/lib/color.js.map +1 -0
  80. package/dist/notifications/api.d.ts +6 -6
  81. package/dist/notifications/api.js.map +1 -1
  82. package/dist/notifications/types.d.ts +2 -10
  83. package/dist/provider-base.js +1 -1
  84. package/dist/realtime/build-effects.js +5 -5
  85. package/dist/realtime/build-effects.js.map +1 -1
  86. package/dist/realtime/listeners.d.ts +2 -2
  87. package/dist/realtime/listeners.js.map +1 -1
  88. package/dist/realtime/subscriptions.d.ts +2 -2
  89. package/dist/realtime/subscriptions.js.map +1 -1
  90. package/dist/table/components/bulk-bar.js +5 -5
  91. package/dist/table/components/bulk-bar.js.map +1 -1
  92. package/dist/table/components/cells/badge-cell.js +4 -1
  93. package/dist/table/components/cells/badge-cell.js.map +1 -1
  94. package/dist/table/components/cells/boolean-cell.js +3 -1
  95. package/dist/table/components/cells/boolean-cell.js.map +1 -1
  96. package/dist/table/components/cells/icon-cell.js +5 -2
  97. package/dist/table/components/cells/icon-cell.js.map +1 -1
  98. package/dist/table/components/cells/image-cell.js +8 -9
  99. package/dist/table/components/cells/image-cell.js.map +1 -1
  100. package/dist/table/components/cells/money-cell.js +9 -1
  101. package/dist/table/components/cells/money-cell.js.map +1 -1
  102. package/dist/table/components/cells/number-cell.js +9 -1
  103. package/dist/table/components/cells/number-cell.js.map +1 -1
  104. package/dist/table/components/cells/text-cell.js +4 -1
  105. package/dist/table/components/cells/text-cell.js.map +1 -1
  106. package/dist/table/components/column-filter-control.js +25 -32
  107. package/dist/table/components/column-filter-control.js.map +1 -1
  108. package/dist/table/components/column-header.d.ts +3 -3
  109. package/dist/table/components/column-header.js +5 -3
  110. package/dist/table/components/column-header.js.map +1 -1
  111. package/dist/table/components/column-visibility-menu.js +6 -11
  112. package/dist/table/components/column-visibility-menu.js.map +1 -1
  113. package/dist/table/components/filter-bar.d.ts +2 -2
  114. package/dist/table/components/filter-bar.js +13 -22
  115. package/dist/table/components/filter-bar.js.map +1 -1
  116. package/dist/table/components/filter-controls.d.ts +2 -1
  117. package/dist/table/components/filter-controls.js +36 -35
  118. package/dist/table/components/filter-controls.js.map +1 -1
  119. package/dist/table/components/filter-value-input.d.ts +0 -1
  120. package/dist/table/components/filter-value-input.js +21 -20
  121. package/dist/table/components/filter-value-input.js.map +1 -1
  122. package/dist/table/components/pagination.js +16 -20
  123. package/dist/table/components/pagination.js.map +1 -1
  124. package/dist/table/components/sort-bar.d.ts +3 -3
  125. package/dist/table/components/sort-bar.js +11 -12
  126. package/dist/table/components/sort-bar.js.map +1 -1
  127. package/dist/table/components/table-search.d.ts +9 -0
  128. package/dist/table/components/table-search.js +75 -0
  129. package/dist/table/components/table-search.js.map +1 -0
  130. package/dist/table/components/table.js +72 -19
  131. package/dist/table/components/table.js.map +1 -1
  132. package/dist/table/hooks/use-expanded-rows.d.ts +8 -0
  133. package/dist/table/hooks/use-expanded-rows.js +24 -0
  134. package/dist/table/hooks/use-expanded-rows.js.map +1 -0
  135. package/dist/table/hooks/use-table.d.ts +5 -3
  136. package/dist/table/hooks/use-table.js +56 -44
  137. package/dist/table/hooks/use-table.js.map +1 -1
  138. package/dist/table/lib/payload.d.ts +3 -2
  139. package/dist/table/lib/payload.js +16 -10
  140. package/dist/table/lib/payload.js.map +1 -1
  141. package/dist/table/lib/query.d.ts +5 -5
  142. package/dist/table/lib/query.js +20 -18
  143. package/dist/table/lib/query.js.map +1 -1
  144. package/dist/table/types.d.ts +3 -26
  145. package/dist/toast/callout.js +1 -3
  146. package/dist/toast/callout.js.map +1 -1
  147. package/dist/toast/toast.d.ts +1 -5
  148. package/dist/toast/toast.js +2 -7
  149. package/dist/toast/toast.js.map +1 -1
  150. package/dist/toast/toaster.js +2 -2
  151. package/dist/toast/toaster.js.map +1 -1
  152. package/dist/types/generated.d.ts +263 -188
  153. package/dist/ui/affix-group.d.ts +2 -1
  154. package/dist/ui/affix-group.js +9 -7
  155. package/dist/ui/affix-group.js.map +1 -1
  156. package/dist/ui/avatar.d.ts +3 -0
  157. package/dist/ui/avatar.js +52 -0
  158. package/dist/ui/avatar.js.map +1 -0
  159. package/dist/ui/button.d.ts +3 -1
  160. package/dist/ui/button.js +10 -3
  161. package/dist/ui/button.js.map +1 -1
  162. package/dist/ui/chart-view.js +161 -11
  163. package/dist/ui/chart-view.js.map +1 -1
  164. package/dist/ui/click-behavior.d.ts +1 -1
  165. package/dist/ui/click-behavior.js.map +1 -1
  166. package/dist/ui/color-picker.d.ts +8 -0
  167. package/dist/ui/color-picker.js +59 -0
  168. package/dist/ui/color-picker.js.map +1 -0
  169. package/dist/ui/combobox.d.ts +11 -2
  170. package/dist/ui/combobox.js +51 -8
  171. package/dist/ui/combobox.js.map +1 -1
  172. package/dist/ui/copyable-text.d.ts +7 -0
  173. package/dist/ui/copyable-text.js +21 -13
  174. package/dist/ui/copyable-text.js.map +1 -1
  175. package/dist/ui/fragment.js.map +1 -1
  176. package/dist/ui/heading.js +39 -21
  177. package/dist/ui/heading.js.map +1 -1
  178. package/dist/ui/icon-button.d.ts +22 -0
  179. package/dist/ui/icon-button.js +51 -0
  180. package/dist/ui/icon-button.js.map +1 -0
  181. package/dist/ui/icon.js +10 -11
  182. package/dist/ui/icon.js.map +1 -1
  183. package/dist/ui/image-preview.d.ts +12 -0
  184. package/dist/ui/image-preview.js +65 -0
  185. package/dist/ui/image-preview.js.map +1 -0
  186. package/dist/ui/image.d.ts +3 -0
  187. package/dist/ui/image.js +21 -0
  188. package/dist/ui/image.js.map +1 -0
  189. package/dist/ui/index.d.ts +2 -1
  190. package/dist/ui/index.js +4 -3
  191. package/dist/ui/info-tooltip.js +1 -1
  192. package/dist/ui/info-tooltip.js.map +1 -1
  193. package/dist/ui/input.d.ts +3 -1
  194. package/dist/ui/input.js +2 -2
  195. package/dist/ui/input.js.map +1 -1
  196. package/dist/ui/modal.js +14 -2
  197. package/dist/ui/modal.js.map +1 -1
  198. package/dist/ui/native-select.d.ts +10 -0
  199. package/dist/ui/native-select.js +23 -0
  200. package/dist/ui/native-select.js.map +1 -0
  201. package/dist/ui/plugin.js +11 -1
  202. package/dist/ui/plugin.js.map +1 -1
  203. package/dist/ui/progress.d.ts +3 -0
  204. package/dist/ui/progress.js +114 -0
  205. package/dist/ui/progress.js.map +1 -0
  206. package/dist/ui/separator.d.ts +3 -0
  207. package/dist/ui/separator.js +15 -0
  208. package/dist/ui/separator.js.map +1 -0
  209. package/dist/ui/text.js +5 -10
  210. package/dist/ui/text.js.map +1 -1
  211. package/dist/ui/tree-context.d.ts +33 -0
  212. package/dist/ui/tree-context.js +137 -0
  213. package/dist/ui/tree-context.js.map +1 -0
  214. package/dist/ui/tree.d.ts +19 -0
  215. package/dist/ui/tree.js +187 -0
  216. package/dist/ui/tree.js.map +1 -0
  217. package/dist-standalone/chunks/chart-view-wJmnVu7L.js +36 -0
  218. package/dist-standalone/chunks/date-picker-field-VbH9xrQO.js +1 -0
  219. package/dist-standalone/chunks/jsx-runtime-Drll_-DD.js +1 -0
  220. package/dist-standalone/chunks/locale-CXqr7LPR.js +1 -0
  221. package/dist-standalone/chunks/page-props-AIa5UR6n.js +1 -0
  222. package/dist-standalone/chunks/rich-editor-field-DLQTyt36.js +154 -0
  223. package/dist-standalone/chunks/{subscriptions-B3UuDBmx.js → subscriptions-DY2tj9Im.js} +1 -1
  224. package/dist-standalone/chunks/use-effect-dispatcher-feEs0GCP.js +97 -0
  225. package/dist-standalone/lattice.css +1 -1
  226. package/dist-standalone/lattice.js +15 -15
  227. package/dist-standalone/manifest.json +11 -9
  228. package/dist-standalone/sprite.svg +1 -1
  229. package/package.json +6 -1
  230. package/resources/icons/code-xml.svg +17 -0
  231. package/resources/icons/heading.svg +17 -0
  232. package/dist-standalone/chunks/chart-view-CK5fKIkR.js +0 -36
  233. package/dist-standalone/chunks/date-picker-field-BlCPFhZd.js +0 -1
  234. package/dist-standalone/chunks/jsx-runtime-CJ_btYLc.js +0 -1
  235. package/dist-standalone/chunks/rich-editor-field-DH5dS5c1.js +0 -154
  236. package/dist-standalone/chunks/use-effect-dispatcher-k98Nzf9M.js +0 -97
@@ -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/hooks/use-column-resizing\";\nimport { useColumnVisibility } from \"@lattice-php/lattice/table/hooks/use-column-visibility\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"@lattice-php/lattice/table/lib/align\";\nimport type { TableNode } from \"@lattice-php/lattice/table/types\";\nimport { getBulkActions } from \"@lattice-php/lattice/table/lib/bulk\";\nimport { getRowActions, getRowKey } from \"@lattice-php/lattice/table/lib/payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"@lattice-php/lattice/table/lib/query\";\nimport { useTable } from \"@lattice-php/lattice/table/hooks/use-table\";\nimport { useTableSelection } from \"@lattice-php/lattice/table/hooks/use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { ColumnVisibilityMenu } from \"./column-visibility-menu\";\nimport { FilterBar, FilterMenu } from \"./filter-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(columns.map((column) => [column.key, column])),\n [columns],\n );\n const visibilityIdentity = nodeIdentity(node);\n const {\n hasToggleableColumns,\n hasHidden,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n } = useColumnVisibility({\n columns,\n storageKey: visibilityIdentity\n ? `lattice:table-column-visibility:${visibilityIdentity}`\n : undefined,\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 = visibleColumns.some((column) => column.props.filter != null);\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 hasTrailingUtility = hasActions || hasDedicatedFilters || hasToggleableColumns;\n const sizingColumns = useMemo(() => getTableSizingColumns(visibleColumns), [visibleColumns]);\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, resizeRootRef, 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-slot=\"table\" 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\n data-slot=\"table-scroll\"\n className=\"overflow-x-auto rounded-lt-sm border border-lt-border\"\n >\n <FilterBar\n clauses={filters}\n columnsByKey={columnsByKey}\n indicators={state.tableFilterIndicators}\n processing={processing}\n onRemoveClause={removeFilter}\n onChange={setTableFilter}\n onReset={resetFilters}\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 {state.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n state={state}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div\n ref={resizeRootRef}\n className=\"min-w-full text-base\"\n role=\"table\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n <div\n data-slot=\"table-header\"\n className=\"border-b border-lt-border bg-lt-muted/50\"\n role=\"rowgroup\"\n >\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\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 {visibleColumns.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 {hasToggleableColumns && (\n <ColumnVisibilityMenu\n columns={toggleableColumns}\n isVisible={isVisible}\n visibleColumnCount={visibleColumns.length}\n hasHidden={hasHidden}\n onToggle={setColumnVisible}\n onReset={resetVisibility}\n processing={processing}\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 >\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {visibleColumns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.props.filter != null && (\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, signal) =>\n searchFilterOptions(`column:${column.key}`, query, signal)\n }\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 data-slot=\"table-empty\" 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 data-slot=\"table-row\"\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 >\n {hasBulkActions && (\n <div className=\"flex items-center px-lt-cell-x py-lt-cell-y\" 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 {visibleColumns.map((column) => (\n <div\n key={column.key}\n data-slot=\"table-cell\"\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden px-lt-cell-x py-lt-cell-y align-middle\",\n alignText(column.props.align),\n alignJustifyItems(column.props.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.props.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 px-lt-cell-x py-lt-cell-y 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, Fragment, useMemo } from \"react\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport { useColumnResizing } from \"@lattice-php/lattice/core/hooks/use-column-resizing\";\nimport { useColumnVisibility } from \"@lattice-php/lattice/table/hooks/use-column-visibility\";\nimport { useExpandedRows } from \"@lattice-php/lattice/table/hooks/use-expanded-rows\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { alignJustifyItems, alignText } from \"@lattice-php/lattice/table/lib/align\";\nimport type { TableNode } from \"@lattice-php/lattice/table/types\";\nimport { getBulkActions } from \"@lattice-php/lattice/table/lib/bulk\";\nimport { getRowActions, getRowDetail, getRowKey } from \"@lattice-php/lattice/table/lib/payload\";\nimport {\n getQueryParams,\n getTableSizingColumns,\n getTableUtilityTracks,\n getVisiblePages,\n} from \"@lattice-php/lattice/table/lib/query\";\nimport { useTable } from \"@lattice-php/lattice/table/hooks/use-table\";\nimport { useTableSelection } from \"@lattice-php/lattice/table/hooks/use-table-selection\";\nimport { BulkBar } from \"./bulk-bar\";\nimport { ColumnFilterControl } from \"./column-filter-control\";\nimport { ColumnHeader } from \"./column-header\";\nimport { ColumnVisibilityMenu } from \"./column-visibility-menu\";\nimport { FilterBar, FilterMenu } from \"./filter-bar\";\nimport { TablePagination } from \"./pagination\";\nimport { SortBar } from \"./sort-bar\";\nimport { TableSearch } from \"./table-search\";\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 query,\n filters,\n tableFilters,\n search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\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) => ({\n row,\n actions: getRowActions(row),\n detail: getRowDetail(row),\n key: getRowKey(row, index),\n })),\n [rows],\n );\n const selection = useTableSelection(rowEntries.map((entry) => entry.key));\n const { isExpanded, toggle: toggleRow } = useExpandedRows();\n const hasExpandable = rowEntries.some((entry) => entry.detail != null);\n\n const columnsByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n const visibilityIdentity = nodeIdentity(node);\n const {\n hasToggleableColumns,\n hasHidden,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n } = useColumnVisibility({\n columns,\n storageKey: visibilityIdentity\n ? `lattice:table-column-visibility:${visibilityIdentity}`\n : undefined,\n });\n const currentPage = pagination.currentPage ?? query.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 = visibleColumns.some((column) => column.props.filter != null);\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 hasTrailingUtility = hasActions || hasDedicatedFilters || hasToggleableColumns;\n const sizingColumns = useMemo(() => getTableSizingColumns(visibleColumns), [visibleColumns]);\n const utilityTracks = useMemo(\n () => getTableUtilityTracks(hasTrailingUtility, hasBulkActions, hasExpandable),\n [hasTrailingUtility, hasBulkActions, hasExpandable],\n );\n const resizingEnabled = node.props?.resizableColumns === true;\n const resizeStorageIdentity = nodeIdentity(node);\n const { getResizeHandleProps, gridTemplateColumns, hasOverrides, resizeRootRef, 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-slot=\"table\" data-lattice-component={node.id} className=\"relative\">\n {hasOverrides && (\n <button\n aria-label={t(\"table.reset-column-widths\", \"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.reset-column-widths\", \"Reset column widths\")}\n type=\"button\"\n >\n <Icon name=\"rotate-ccw\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n <div\n data-slot=\"table-scroll\"\n className=\"overflow-x-auto rounded-lt-sm border border-lt-border\"\n >\n {node.props?.searchable && (\n <div\n data-slot=\"table-toolbar\"\n className=\"flex items-center gap-2 border-b border-lt-border px-4 py-2\"\n >\n <TableSearch value={search} onSearch={setSearch} />\n </div>\n )}\n <FilterBar\n clauses={filters}\n columnsByKey={columnsByKey}\n indicators={query.tableFilterIndicators}\n processing={processing}\n onRemoveClause={removeFilter}\n onChange={setTableFilter}\n onReset={resetFilters}\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(query)}\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 {query.sorts.length > 0 && (\n <SortBar\n columnsByKey={columnsByKey}\n query={query}\n processing={processing}\n onClear={clearSort}\n />\n )}\n <div\n ref={resizeRootRef}\n className=\"min-w-full text-base\"\n role=\"table\"\n style={{ \"--lattice-table-columns\": gridTemplateColumns } as never}\n >\n <div\n data-slot=\"table-header\"\n className=\"border-b border-lt-border bg-lt-muted/50\"\n role=\"rowgroup\"\n >\n <div\n className=\"hidden min-w-full md:grid md:grid-cols-[var(--lattice-table-columns)]\"\n role=\"row\"\n >\n {hasExpandable && (\n <div className=\"px-2 py-3\" role=\"columnheader\" aria-hidden=\"true\" />\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-4 py-3\" role=\"columnheader\">\n <Checkbox\n aria-label={t(\"table.select-all-rows\", \"Select all rows\")}\n data-test=\"select-all\"\n checked={selection.allSelected}\n onCheckedChange={() => selection.toggleAll()}\n />\n </div>\n )}\n {visibleColumns.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 query={query}\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 {hasToggleableColumns && (\n <ColumnVisibilityMenu\n columns={toggleableColumns}\n isVisible={isVisible}\n visibleColumnCount={visibleColumns.length}\n hasHidden={hasHidden}\n onToggle={setColumnVisible}\n onReset={resetVisibility}\n processing={processing}\n />\n )}\n {hasActions && (\n <span className=\"sr-only\">\n {node.props?.actionsLabel ?? t(\"table.actions\", \"Actions\")}\n </span>\n )}\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 >\n {hasExpandable && <div className=\"px-2 py-2\" role=\"cell\" />}\n {hasBulkActions && <div className=\"px-4 py-2\" role=\"cell\" />}\n {visibleColumns.map((column) => (\n <div key={column.key} className=\"min-w-0 px-2 py-2\" role=\"cell\">\n {column.props.filter != null && (\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, signal) =>\n searchFilterOptions(`column:${column.key}`, query, signal)\n }\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 data-slot=\"table-empty\" className=\"p-8 text-center text-lt-muted-fg\" role=\"row\">\n <div role=\"cell\">{node.props?.emptyLabel ?? t(\"table.empty\", \"No results\")}</div>\n </div>\n ) : (\n rowEntries.map(({ row, actions, detail, key }) => {\n const expanded = detail != null && isExpanded(key);\n const detailId = `${nodeIdentity(node) ?? \"table\"}-row-detail-${key}`;\n\n return (\n <Fragment key={key}>\n <div\n data-slot=\"table-row\"\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 >\n {hasExpandable && (\n <div className=\"flex items-center px-2 py-lt-cell-y\" role=\"cell\">\n {detail && (\n <button\n type=\"button\"\n data-test={`row-expand-${key}`}\n aria-expanded={expanded}\n aria-controls={detailId}\n aria-label={t(\"table.row-detail.toggle\", \"Toggle detail\")}\n className=\"inline-flex size-6 items-center justify-center rounded-lt-sm text-lt-muted-fg hover:bg-lt-muted hover:text-lt-fg\"\n onClick={() => toggleRow(key)}\n >\n <Icon\n name=\"chevron-down\"\n aria-hidden=\"true\"\n className={cn(\n \"size-lt-icon-md transition-transform\",\n !expanded && \"-rotate-90\",\n )}\n />\n </button>\n )}\n </div>\n )}\n {hasBulkActions && (\n <div className=\"flex items-center px-lt-cell-x py-lt-cell-y\" role=\"cell\">\n <Checkbox\n aria-label={t(\"table.select-row\", \"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 {visibleColumns.map((column) => (\n <div\n key={column.key}\n data-slot=\"table-cell\"\n className={cn(\n \"grid min-w-0 gap-1 overflow-hidden px-lt-cell-x py-lt-cell-y align-middle\",\n alignText(column.props.align),\n alignJustifyItems(column.props.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.props.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 px-lt-cell-x py-lt-cell-y 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 {expanded && detail && (\n <div\n id={detailId}\n role=\"region\"\n data-slot=\"table-row-detail\"\n className=\"border-b border-lt-border bg-lt-muted/20 px-lt-cell-x py-lt-cell-y\"\n >\n <Renderer nodes={[detail]} />\n </div>\n )}\n </Fragment>\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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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Client-side expansion state for expandable table rows, keyed by row key.
3
+ * In-memory only: expansions reset when the table reloads or refetches.
4
+ */
5
+ export declare function useExpandedRows(): {
6
+ isExpanded: (key: string) => boolean;
7
+ toggle: (key: string) => void;
8
+ };
@@ -0,0 +1,24 @@
1
+ import { useCallback, useState } from "react";
2
+ //#region resources/js/table/hooks/use-expanded-rows.ts
3
+ /**
4
+ * Client-side expansion state for expandable table rows, keyed by row key.
5
+ * In-memory only: expansions reset when the table reloads or refetches.
6
+ */
7
+ function useExpandedRows() {
8
+ const [expanded, setExpanded] = useState(() => /* @__PURE__ */ new Set());
9
+ return {
10
+ isExpanded: useCallback((key) => expanded.has(key), [expanded]),
11
+ toggle: useCallback((key) => {
12
+ setExpanded((current) => {
13
+ const next = new Set(current);
14
+ if (next.has(key)) next.delete(key);
15
+ else next.add(key);
16
+ return next;
17
+ });
18
+ }, [])
19
+ };
20
+ }
21
+ //#endregion
22
+ export { useExpandedRows };
23
+
24
+ //# sourceMappingURL=use-expanded-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-expanded-rows.js","names":[],"sources":["../../../resources/js/table/hooks/use-expanded-rows.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\n\n/**\n * Client-side expansion state for expandable table rows, keyed by row key.\n * In-memory only: expansions reset when the table reloads or refetches.\n */\nexport function useExpandedRows() {\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(() => new Set());\n\n const isExpanded = useCallback((key: string): boolean => expanded.has(key), [expanded]);\n\n const toggle = useCallback((key: string): void => {\n setExpanded((current) => {\n const next = new Set(current);\n\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n\n return next;\n });\n }, []);\n\n return { isExpanded, toggle };\n}\n"],"mappings":";;;;;;AAMA,SAAgB,kBAAkB;CAChC,MAAM,CAAC,UAAU,eAAe,+BAAoC,IAAI,IAAI,CAAC;CAkB7E,OAAO;EAAE,YAhBU,aAAa,QAAyB,SAAS,IAAI,GAAG,GAAG,CAAC,QAAQ,CAgB5E;EAAY,QAdN,aAAa,QAAsB;GAChD,aAAa,YAAY;IACvB,MAAM,OAAO,IAAI,IAAI,OAAO;IAE5B,IAAI,KAAK,IAAI,GAAG,GACd,KAAK,OAAO,GAAG;SAEf,KAAK,IAAI,GAAG;IAGd,OAAO;GACT,CAAC;EACH,GAAG,CAAC,CAEiB;CAAO;AAC9B"}
@@ -1,19 +1,21 @@
1
1
  import { Option } from '../../types/generated.js';
2
- import { FilterClause, TableColumn, TableNode, TableSort, TableState } from '../types.js';
2
+ import { FilterClause, TableColumn, TableNode, TableSort, TableQuery } from '../types.js';
3
3
  export declare function useTable(node: TableNode): {
4
4
  columns: TableColumn[];
5
5
  rows: import('../types.js').TableRow[];
6
6
  pagination: import('../../types/generated.js').TablePagination;
7
- state: TableState;
7
+ query: TableQuery;
8
8
  filters: FilterClause[];
9
9
  tableFilters: Record<string, Record<string, unknown>>;
10
+ search: string;
10
11
  addFilter: (clause: FilterClause) => void;
11
12
  updateFilter: (index: number, clause: FilterClause) => void;
12
13
  removeFilter: (index: number) => void;
13
14
  replaceColumnFilters: (field: string, clauses: FilterClause[]) => void;
14
15
  setTableFilter: (key: string, value: unknown) => void;
15
16
  resetFilters: () => void;
16
- searchFilterOptions: (searchKey: string, query: string, signal?: AbortSignal) => Promise<Option[]>;
17
+ setSearch: (search: string) => void;
18
+ searchFilterOptions: (searchKey: string, search: string, signal?: AbortSignal) => Promise<Option[]>;
17
19
  processing: boolean;
18
20
  hasLoaded: boolean;
19
21
  infiniteLoaderRef: import('react').RefObject<HTMLDivElement | null>;
@@ -1,6 +1,6 @@
1
1
  import { LATTICE_EVENT } from "../../events/event-names.js";
2
2
  import { apiFetch, apiJson } from "../../core/api.js";
3
- import { getColumns, getPagination, getRows, getState } from "../lib/payload.js";
3
+ import { getColumns, getPagination, getQuery, getRows } from "../lib/payload.js";
4
4
  import { isEmptyFilterValue, isFilterValue } from "../lib/filter-values.js";
5
5
  import { buildEndpoint, nextSort } from "../lib/query.js";
6
6
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -10,27 +10,27 @@ function useTable(node) {
10
10
  const endpoint = typeof node.props?.endpoint === "string" ? node.props.endpoint : null;
11
11
  const componentRef = typeof node.props?.ref === "string" ? node.props.ref : "";
12
12
  const isLazy = node.props?.lazy === true;
13
- const initialState = useMemo(() => getState(node.props?.state), [node.props?.state]);
13
+ const initialQuery = useMemo(() => getQuery(node.props?.query), [node.props?.query]);
14
14
  const initialRows = useMemo(() => getRows(node.props?.data), [node.props?.data]);
15
15
  const initialPagination = useMemo(() => getPagination(node.props?.pagination), [node.props?.pagination]);
16
16
  const [rows, setRows] = useState(initialRows);
17
17
  const [pagination, setPagination] = useState(initialPagination);
18
- const [state, setState] = useState(initialState);
18
+ const [query, setQuery] = useState(initialQuery);
19
19
  const [processing, setProcessing] = useState(isLazy);
20
20
  const [hasLoaded, setHasLoaded] = useState(!isLazy);
21
21
  const infiniteLoaderRef = useRef(null);
22
- const currentPage = pagination.currentPage ?? state.page;
22
+ const currentPage = pagination.currentPage ?? query.page;
23
23
  const isInfinite = (pagination.mode ?? "table") === "infinite";
24
- const load = useCallback(async (nextState, append = false) => {
24
+ const load = useCallback(async (nextQuery, append = false) => {
25
25
  if (!endpoint) return;
26
26
  setProcessing(true);
27
27
  try {
28
- const result = await apiJson(buildEndpoint(endpoint, nextState), { ref: componentRef });
29
- const resultState = getState(result.state);
28
+ const result = await apiJson(buildEndpoint(endpoint, nextQuery), { ref: componentRef });
29
+ const resultQuery = getQuery(result.query);
30
30
  const resultRows = getRows(result.data);
31
31
  setRows((currentRows) => append ? [...currentRows, ...resultRows] : resultRows);
32
32
  setPagination(getPagination(result.pagination));
33
- setState(resultState);
33
+ setQuery(resultQuery);
34
34
  setHasLoaded(true);
35
35
  } finally {
36
36
  setProcessing(false);
@@ -38,68 +38,78 @@ function useTable(node) {
38
38
  }, [endpoint, componentRef]);
39
39
  function sort(column) {
40
40
  load({
41
- ...state,
41
+ ...query,
42
42
  page: 1,
43
- sorts: nextSort(state.sorts, column)
43
+ sorts: nextSort(query.sorts, column)
44
44
  });
45
45
  }
46
46
  function clearSort(sort) {
47
47
  load({
48
- ...state,
48
+ ...query,
49
49
  page: 1,
50
- sorts: state.sorts.filter((currentSort) => currentSort.key !== sort.key)
50
+ sorts: query.sorts.filter((currentSort) => currentSort.key !== sort.key)
51
51
  });
52
52
  }
53
53
  function applyFilters(next) {
54
- const nextState = {
55
- ...state,
54
+ const nextQuery = {
55
+ ...query,
56
56
  filters: next,
57
57
  page: 1
58
58
  };
59
- setState(nextState);
60
- load(nextState);
59
+ setQuery(nextQuery);
60
+ load(nextQuery);
61
61
  }
62
62
  function addFilter(clause) {
63
- applyFilters([...state.filters, clause]);
63
+ applyFilters([...query.filters, clause]);
64
64
  }
65
65
  function updateFilter(index, clause) {
66
- applyFilters(state.filters.map((current, position) => position === index ? clause : current));
66
+ applyFilters(query.filters.map((current, position) => position === index ? clause : current));
67
67
  }
68
68
  function removeFilter(index) {
69
- applyFilters(state.filters.filter((_, current) => current !== index));
69
+ applyFilters(query.filters.filter((_, current) => current !== index));
70
70
  }
71
71
  function replaceColumnFilters(field, clauses) {
72
- applyFilters([...state.filters.filter((clause) => clause.field !== field), ...clauses]);
72
+ applyFilters([...query.filters.filter((clause) => clause.field !== field), ...clauses]);
73
73
  }
74
74
  function setTableFilter(key, value) {
75
- const next = { ...state.tableFilters };
75
+ const next = { ...query.tableFilters };
76
76
  if (isEmptyFilterValue(value) || !isFilterValue(value)) delete next[key];
77
77
  else next[key] = value;
78
- const nextState = {
79
- ...state,
78
+ const nextQuery = {
79
+ ...query,
80
80
  tableFilters: next,
81
- tableFilterIndicators: state.tableFilterIndicators.filter((indicator) => indicator.filter !== key),
81
+ tableFilterIndicators: query.tableFilterIndicators.filter((indicator) => indicator.filter !== key),
82
82
  page: 1
83
83
  };
84
- setState(nextState);
85
- load(nextState);
84
+ setQuery(nextQuery);
85
+ load(nextQuery);
86
86
  }
87
87
  function resetFilters() {
88
- const nextState = {
89
- ...state,
88
+ const nextQuery = {
89
+ ...query,
90
90
  filters: [],
91
91
  tableFilters: {},
92
92
  tableFilterIndicators: [],
93
+ search: "",
93
94
  page: 1
94
95
  };
95
- setState(nextState);
96
- load(nextState);
96
+ setQuery(nextQuery);
97
+ load(nextQuery);
97
98
  }
98
- const searchFilterOptions = useCallback(async (searchKey, query, signal) => {
99
+ function setSearch(search) {
100
+ const nextQuery = {
101
+ ...query,
102
+ search,
103
+ page: 1
104
+ };
105
+ setQuery(nextQuery);
106
+ load(nextQuery);
107
+ }
108
+ const searchFilterOptions = useCallback(async (searchKey, search, signal) => {
99
109
  if (!endpoint) return [];
100
110
  const url = new URL(endpoint, window.location.origin);
101
111
  url.searchParams.set("_search", searchKey);
102
- url.searchParams.set("q", query);
112
+ url.searchParams.set("_q", search);
103
113
  const response = await apiFetch(`${url.pathname}${url.search}`, {
104
114
  ref: componentRef,
105
115
  signal,
@@ -110,14 +120,14 @@ function useTable(node) {
110
120
  }, [endpoint, componentRef]);
111
121
  function goToPage(page) {
112
122
  load({
113
- ...state,
123
+ ...query,
114
124
  page
115
125
  });
116
126
  }
117
127
  const loadMore = useCallback(() => {
118
128
  if (processing || !pagination.hasMore) return;
119
129
  load({
120
- ...state,
130
+ ...query,
121
131
  page: pagination.nextPage ?? currentPage + 1
122
132
  }, true);
123
133
  }, [
@@ -126,40 +136,40 @@ function useTable(node) {
126
136
  pagination.hasMore,
127
137
  pagination.nextPage,
128
138
  processing,
129
- state
139
+ query
130
140
  ]);
131
141
  useEffect(() => {
132
142
  setRows(initialRows);
133
143
  setPagination(initialPagination);
134
- setState(initialState);
144
+ setQuery(initialQuery);
135
145
  setProcessing(isLazy);
136
146
  setHasLoaded(!isLazy);
137
147
  }, [
138
148
  initialRows,
139
149
  initialPagination,
140
- initialState,
150
+ initialQuery,
141
151
  isLazy
142
152
  ]);
143
153
  useEffect(() => {
144
154
  if (!isLazy || hasLoaded) return;
145
- load(state);
155
+ load(query);
146
156
  }, [
147
157
  hasLoaded,
148
158
  isLazy,
149
159
  load,
150
- state
160
+ query
151
161
  ]);
152
162
  useEffect(() => {
153
163
  function reload(event) {
154
164
  if (event.detail?.component !== node.id) return;
155
- load(state);
165
+ load(query);
156
166
  }
157
167
  window.addEventListener(LATTICE_EVENT.reloadComponent, reload);
158
168
  return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);
159
169
  }, [
160
170
  load,
161
171
  node.id,
162
- state
172
+ query
163
173
  ]);
164
174
  useEffect(() => {
165
175
  if (!isInfinite || !pagination.hasMore || processing || !infiniteLoaderRef.current || typeof IntersectionObserver === "undefined") return;
@@ -178,15 +188,17 @@ function useTable(node) {
178
188
  columns,
179
189
  rows,
180
190
  pagination,
181
- state,
182
- filters: state.filters,
183
- tableFilters: state.tableFilters,
191
+ query,
192
+ filters: query.filters,
193
+ tableFilters: query.tableFilters,
194
+ search: query.search,
184
195
  addFilter,
185
196
  updateFilter,
186
197
  removeFilter,
187
198
  replaceColumnFilters,
188
199
  setTableFilter,
189
200
  resetFilters,
201
+ setSearch,
190
202
  searchFilterOptions,
191
203
  processing,
192
204
  hasLoaded,
@@ -1 +1 @@
1
- {"version":3,"file":"use-table.js","names":[],"sources":["../../../resources/js/table/hooks/use-table.ts"],"sourcesContent":["import { apiFetch, apiJson } from \"@lattice-php/lattice/core/api\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/events/event-names\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyFilterValue, isFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport {\n getColumns,\n getPagination,\n getRows,\n getState,\n} from \"@lattice-php/lattice/table/lib/payload\";\nimport { buildEndpoint, nextSort } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n TableColumn,\n TableNode,\n TableResponse,\n TableSort,\n TableState,\n} from \"@lattice-php/lattice/table/types\";\n\nexport function useTable(node: TableNode) {\n const columns = useMemo(() => getColumns(node.props?.columns), [node.props?.columns]);\n const endpoint = typeof node.props?.endpoint === \"string\" ? node.props.endpoint : null;\n const componentRef = typeof node.props?.ref === \"string\" ? node.props.ref : \"\";\n const isLazy = node.props?.lazy === true;\n const initialState = useMemo(() => getState(node.props?.state), [node.props?.state]);\n const initialRows = useMemo(() => getRows(node.props?.data), [node.props?.data]);\n const initialPagination = useMemo(\n () => getPagination(node.props?.pagination),\n [node.props?.pagination],\n );\n const [rows, setRows] = useState(initialRows);\n const [pagination, setPagination] = useState(initialPagination);\n const [state, setState] = useState(initialState);\n const [processing, setProcessing] = useState(isLazy);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const infiniteLoaderRef = useRef<HTMLDivElement | null>(null);\n const currentPage = pagination.currentPage ?? state.page;\n const isInfinite = (pagination.mode ?? \"table\") === \"infinite\";\n\n const load = useCallback(\n async (nextState: TableState, append = false): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<TableResponse>(buildEndpoint(endpoint, nextState), {\n ref: componentRef,\n });\n const resultState = getState(result.state);\n const resultRows = getRows(result.data);\n\n setRows((currentRows) => (append ? [...currentRows, ...resultRows] : resultRows));\n setPagination(getPagination(result.pagination));\n setState(resultState);\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n },\n [endpoint, componentRef],\n );\n\n function sort(column: TableColumn): void {\n void load({\n ...state,\n page: 1,\n sorts: nextSort(state.sorts, column),\n });\n }\n\n function clearSort(sort: TableSort): void {\n void load({\n ...state,\n page: 1,\n sorts: state.sorts.filter((currentSort) => currentSort.key !== sort.key),\n });\n }\n\n function applyFilters(next: FilterClause[]): void {\n const nextState = { ...state, filters: next, page: 1 };\n\n setState(nextState);\n void load(nextState);\n }\n\n function addFilter(clause: FilterClause): void {\n applyFilters([...state.filters, clause]);\n }\n\n function updateFilter(index: number, clause: FilterClause): void {\n applyFilters(state.filters.map((current, position) => (position === index ? clause : current)));\n }\n\n function removeFilter(index: number): void {\n applyFilters(state.filters.filter((_, current) => current !== index));\n }\n\n function replaceColumnFilters(field: string, clauses: FilterClause[]): void {\n applyFilters([...state.filters.filter((clause) => clause.field !== field), ...clauses]);\n }\n\n function setTableFilter(key: string, value: unknown): void {\n const next = { ...state.tableFilters };\n\n if (isEmptyFilterValue(value) || !isFilterValue(value)) {\n delete next[key];\n } else {\n next[key] = value;\n }\n\n const nextState = {\n ...state,\n tableFilters: next,\n tableFilterIndicators: state.tableFilterIndicators.filter(\n (indicator) => indicator.filter !== key,\n ),\n page: 1,\n };\n\n setState(nextState);\n void load(nextState);\n }\n\n function resetFilters(): void {\n const nextState = {\n ...state,\n filters: [],\n tableFilters: {},\n tableFilterIndicators: [],\n page: 1,\n };\n\n setState(nextState);\n void load(nextState);\n }\n\n const searchFilterOptions = useCallback(\n async (searchKey: string, query: string, signal?: AbortSignal): Promise<Option[]> => {\n if (!endpoint) {\n return [];\n }\n\n const url = new URL(endpoint, window.location.origin);\n url.searchParams.set(\"_search\", searchKey);\n url.searchParams.set(\"q\", query);\n\n const response = await apiFetch(`${url.pathname}${url.search}`, {\n ref: componentRef,\n signal,\n throwOnError: false,\n });\n\n if (!response.ok) {\n return [];\n }\n\n const result = (await response.json()) as { options?: Option[] };\n\n return result.options ?? [];\n },\n [endpoint, componentRef],\n );\n\n function goToPage(page: number): void {\n void load({\n ...state,\n page,\n });\n }\n\n const loadMore = useCallback((): void => {\n if (processing || !pagination.hasMore) {\n return;\n }\n\n void load(\n {\n ...state,\n page: pagination.nextPage ?? currentPage + 1,\n },\n true,\n );\n }, [currentPage, load, pagination.hasMore, pagination.nextPage, processing, state]);\n\n useEffect(() => {\n setRows(initialRows);\n setPagination(initialPagination);\n setState(initialState);\n setProcessing(isLazy);\n setHasLoaded(!isLazy);\n }, [initialRows, initialPagination, initialState, isLazy]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load(state);\n }, [hasLoaded, isLazy, load, state]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load(state);\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id, state]);\n\n useEffect(() => {\n if (\n !isInfinite ||\n !pagination.hasMore ||\n processing ||\n !infiniteLoaderRef.current ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore();\n }\n },\n {\n rootMargin: \"240px\",\n },\n );\n\n observer.observe(infiniteLoaderRef.current);\n\n return () => observer.disconnect();\n }, [isInfinite, loadMore, pagination.hasMore, processing]);\n\n return {\n columns,\n rows,\n pagination,\n state,\n filters: state.filters,\n tableFilters: state.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 };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-table.js","names":[],"sources":["../../../resources/js/table/hooks/use-table.ts"],"sourcesContent":["import { apiFetch, apiJson } from \"@lattice-php/lattice/core/api\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/lattice/events/event-names\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/types/generated\";\nimport { isEmptyFilterValue, isFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport {\n getColumns,\n getPagination,\n getRows,\n getQuery,\n} from \"@lattice-php/lattice/table/lib/payload\";\nimport { buildEndpoint, nextSort } from \"@lattice-php/lattice/table/lib/query\";\nimport type {\n FilterClause,\n TableColumn,\n TableNode,\n TableResult,\n TableSort,\n TableQuery,\n} from \"@lattice-php/lattice/table/types\";\n\nexport function useTable(node: TableNode) {\n const columns = useMemo(() => getColumns(node.props?.columns), [node.props?.columns]);\n const endpoint = typeof node.props?.endpoint === \"string\" ? node.props.endpoint : null;\n const componentRef = typeof node.props?.ref === \"string\" ? node.props.ref : \"\";\n const isLazy = node.props?.lazy === true;\n const initialQuery = useMemo(() => getQuery(node.props?.query), [node.props?.query]);\n const initialRows = useMemo(() => getRows(node.props?.data), [node.props?.data]);\n const initialPagination = useMemo(\n () => getPagination(node.props?.pagination),\n [node.props?.pagination],\n );\n const [rows, setRows] = useState(initialRows);\n const [pagination, setPagination] = useState(initialPagination);\n const [query, setQuery] = useState(initialQuery);\n const [processing, setProcessing] = useState(isLazy);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const infiniteLoaderRef = useRef<HTMLDivElement | null>(null);\n const currentPage = pagination.currentPage ?? query.page;\n const isInfinite = (pagination.mode ?? \"table\") === \"infinite\";\n\n const load = useCallback(\n async (nextQuery: TableQuery, append = false): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<TableResult>(buildEndpoint(endpoint, nextQuery), {\n ref: componentRef,\n });\n const resultQuery = getQuery(result.query);\n const resultRows = getRows(result.data);\n\n setRows((currentRows) => (append ? [...currentRows, ...resultRows] : resultRows));\n setPagination(getPagination(result.pagination));\n setQuery(resultQuery);\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n },\n [endpoint, componentRef],\n );\n\n function sort(column: TableColumn): void {\n void load({\n ...query,\n page: 1,\n sorts: nextSort(query.sorts, column),\n });\n }\n\n function clearSort(sort: TableSort): void {\n void load({\n ...query,\n page: 1,\n sorts: query.sorts.filter((currentSort) => currentSort.key !== sort.key),\n });\n }\n\n function applyFilters(next: FilterClause[]): void {\n const nextQuery = { ...query, filters: next, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function addFilter(clause: FilterClause): void {\n applyFilters([...query.filters, clause]);\n }\n\n function updateFilter(index: number, clause: FilterClause): void {\n applyFilters(query.filters.map((current, position) => (position === index ? clause : current)));\n }\n\n function removeFilter(index: number): void {\n applyFilters(query.filters.filter((_, current) => current !== index));\n }\n\n function replaceColumnFilters(field: string, clauses: FilterClause[]): void {\n applyFilters([...query.filters.filter((clause) => clause.field !== field), ...clauses]);\n }\n\n function setTableFilter(key: string, value: unknown): void {\n const next = { ...query.tableFilters };\n\n if (isEmptyFilterValue(value) || !isFilterValue(value)) {\n delete next[key];\n } else {\n next[key] = value;\n }\n\n const nextQuery = {\n ...query,\n tableFilters: next,\n tableFilterIndicators: query.tableFilterIndicators.filter(\n (indicator) => indicator.filter !== key,\n ),\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function resetFilters(): void {\n const nextQuery = {\n ...query,\n filters: [],\n tableFilters: {},\n tableFilterIndicators: [],\n search: \"\",\n page: 1,\n };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n function setSearch(search: string): void {\n const nextQuery = { ...query, search, page: 1 };\n\n setQuery(nextQuery);\n void load(nextQuery);\n }\n\n const searchFilterOptions = useCallback(\n async (searchKey: string, search: string, signal?: AbortSignal): Promise<Option[]> => {\n if (!endpoint) {\n return [];\n }\n\n const url = new URL(endpoint, window.location.origin);\n url.searchParams.set(\"_search\", searchKey);\n url.searchParams.set(\"_q\", search);\n\n const response = await apiFetch(`${url.pathname}${url.search}`, {\n ref: componentRef,\n signal,\n throwOnError: false,\n });\n\n if (!response.ok) {\n return [];\n }\n\n const result = (await response.json()) as { options?: Option[] };\n\n return result.options ?? [];\n },\n [endpoint, componentRef],\n );\n\n function goToPage(page: number): void {\n void load({\n ...query,\n page,\n });\n }\n\n const loadMore = useCallback((): void => {\n if (processing || !pagination.hasMore) {\n return;\n }\n\n void load(\n {\n ...query,\n page: pagination.nextPage ?? currentPage + 1,\n },\n true,\n );\n }, [currentPage, load, pagination.hasMore, pagination.nextPage, processing, query]);\n\n useEffect(() => {\n setRows(initialRows);\n setPagination(initialPagination);\n setQuery(initialQuery);\n setProcessing(isLazy);\n setHasLoaded(!isLazy);\n }, [initialRows, initialPagination, initialQuery, isLazy]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load(query);\n }, [hasLoaded, isLazy, load, query]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load(query);\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id, query]);\n\n useEffect(() => {\n if (\n !isInfinite ||\n !pagination.hasMore ||\n processing ||\n !infiniteLoaderRef.current ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n loadMore();\n }\n },\n {\n rootMargin: \"240px\",\n },\n );\n\n observer.observe(infiniteLoaderRef.current);\n\n return () => observer.disconnect();\n }, [isInfinite, loadMore, pagination.hasMore, processing]);\n\n return {\n columns,\n rows,\n pagination,\n query,\n filters: query.filters,\n tableFilters: query.tableFilters,\n search: query.search,\n addFilter,\n updateFilter,\n removeFilter,\n replaceColumnFilters,\n setTableFilter,\n resetFilters,\n setSearch,\n searchFilterOptions,\n processing,\n hasLoaded,\n infiniteLoaderRef,\n sort,\n clearSort,\n goToPage,\n loadMore,\n };\n}\n"],"mappings":";;;;;;;AAqBA,SAAgB,SAAS,MAAiB;CACxC,MAAM,UAAU,cAAc,WAAW,KAAK,OAAO,OAAO,GAAG,CAAC,KAAK,OAAO,OAAO,CAAC;CACpF,MAAM,WAAW,OAAO,KAAK,OAAO,aAAa,WAAW,KAAK,MAAM,WAAW;CAClF,MAAM,eAAe,OAAO,KAAK,OAAO,QAAQ,WAAW,KAAK,MAAM,MAAM;CAC5E,MAAM,SAAS,KAAK,OAAO,SAAS;CACpC,MAAM,eAAe,cAAc,SAAS,KAAK,OAAO,KAAK,GAAG,CAAC,KAAK,OAAO,KAAK,CAAC;CACnF,MAAM,cAAc,cAAc,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC;CAC/E,MAAM,oBAAoB,cAClB,cAAc,KAAK,OAAO,UAAU,GAC1C,CAAC,KAAK,OAAO,UAAU,CACzB;CACA,MAAM,CAAC,MAAM,WAAW,SAAS,WAAW;CAC5C,MAAM,CAAC,YAAY,iBAAiB,SAAS,iBAAiB;CAC9D,MAAM,CAAC,OAAO,YAAY,SAAS,YAAY;CAC/C,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC,MAAM;CAClD,MAAM,oBAAoB,OAA8B,IAAI;CAC5D,MAAM,cAAc,WAAW,eAAe,MAAM;CACpD,MAAM,cAAc,WAAW,QAAQ,aAAa;CAEpD,MAAM,OAAO,YACX,OAAO,WAAuB,SAAS,UAAyB;EAC9D,IAAI,CAAC,UACH;EAGF,cAAc,IAAI;EAElB,IAAI;GACF,MAAM,SAAS,MAAM,QAAqB,cAAc,UAAU,SAAS,GAAG,EAC5E,KAAK,aACP,CAAC;GACD,MAAM,cAAc,SAAS,OAAO,KAAK;GACzC,MAAM,aAAa,QAAQ,OAAO,IAAI;GAEtC,SAAS,gBAAiB,SAAS,CAAC,GAAG,aAAa,GAAG,UAAU,IAAI,UAAW;GAChF,cAAc,cAAc,OAAO,UAAU,CAAC;GAC9C,SAAS,WAAW;GACpB,aAAa,IAAI;EACnB,UAAU;GACR,cAAc,KAAK;EACrB;CACF,GACA,CAAC,UAAU,YAAY,CACzB;CAEA,SAAS,KAAK,QAA2B;EACvC,KAAU;GACR,GAAG;GACH,MAAM;GACN,OAAO,SAAS,MAAM,OAAO,MAAM;EACrC,CAAC;CACH;CAEA,SAAS,UAAU,MAAuB;EACxC,KAAU;GACR,GAAG;GACH,MAAM;GACN,OAAO,MAAM,MAAM,QAAQ,gBAAgB,YAAY,QAAQ,KAAK,GAAG;EACzE,CAAC;CACH;CAEA,SAAS,aAAa,MAA4B;EAChD,MAAM,YAAY;GAAE,GAAG;GAAO,SAAS;GAAM,MAAM;EAAE;EAErD,SAAS,SAAS;EAClB,KAAU,SAAS;CACrB;CAEA,SAAS,UAAU,QAA4B;EAC7C,aAAa,CAAC,GAAG,MAAM,SAAS,MAAM,CAAC;CACzC;CAEA,SAAS,aAAa,OAAe,QAA4B;EAC/D,aAAa,MAAM,QAAQ,KAAK,SAAS,aAAc,aAAa,QAAQ,SAAS,OAAQ,CAAC;CAChG;CAEA,SAAS,aAAa,OAAqB;EACzC,aAAa,MAAM,QAAQ,QAAQ,GAAG,YAAY,YAAY,KAAK,CAAC;CACtE;CAEA,SAAS,qBAAqB,OAAe,SAA+B;EAC1E,aAAa,CAAC,GAAG,MAAM,QAAQ,QAAQ,WAAW,OAAO,UAAU,KAAK,GAAG,GAAG,OAAO,CAAC;CACxF;CAEA,SAAS,eAAe,KAAa,OAAsB;EACzD,MAAM,OAAO,EAAE,GAAG,MAAM,aAAa;EAErC,IAAI,mBAAmB,KAAK,KAAK,CAAC,cAAc,KAAK,GACnD,OAAO,KAAK;OAEZ,KAAK,OAAO;EAGd,MAAM,YAAY;GAChB,GAAG;GACH,cAAc;GACd,uBAAuB,MAAM,sBAAsB,QAChD,cAAc,UAAU,WAAW,GACtC;GACA,MAAM;EACR;EAEA,SAAS,SAAS;EAClB,KAAU,SAAS;CACrB;CAEA,SAAS,eAAqB;EAC5B,MAAM,YAAY;GAChB,GAAG;GACH,SAAS,CAAC;GACV,cAAc,CAAC;GACf,uBAAuB,CAAC;GACxB,QAAQ;GACR,MAAM;EACR;EAEA,SAAS,SAAS;EAClB,KAAU,SAAS;CACrB;CAEA,SAAS,UAAU,QAAsB;EACvC,MAAM,YAAY;GAAE,GAAG;GAAO;GAAQ,MAAM;EAAE;EAE9C,SAAS,SAAS;EAClB,KAAU,SAAS;CACrB;CAEA,MAAM,sBAAsB,YAC1B,OAAO,WAAmB,QAAgB,WAA4C;EACpF,IAAI,CAAC,UACH,OAAO,CAAC;EAGV,MAAM,MAAM,IAAI,IAAI,UAAU,OAAO,SAAS,MAAM;EACpD,IAAI,aAAa,IAAI,WAAW,SAAS;EACzC,IAAI,aAAa,IAAI,MAAM,MAAM;EAEjC,MAAM,WAAW,MAAM,SAAS,GAAG,IAAI,WAAW,IAAI,UAAU;GAC9D,KAAK;GACL;GACA,cAAc;EAChB,CAAC;EAED,IAAI,CAAC,SAAS,IACZ,OAAO,CAAC;EAKV,QAAO,MAFe,SAAS,KAAK,GAEtB,WAAW,CAAC;CAC5B,GACA,CAAC,UAAU,YAAY,CACzB;CAEA,SAAS,SAAS,MAAoB;EACpC,KAAU;GACR,GAAG;GACH;EACF,CAAC;CACH;CAEA,MAAM,WAAW,kBAAwB;EACvC,IAAI,cAAc,CAAC,WAAW,SAC5B;EAGF,KACE;GACE,GAAG;GACH,MAAM,WAAW,YAAY,cAAc;EAC7C,GACA,IACF;CACF,GAAG;EAAC;EAAa;EAAM,WAAW;EAAS,WAAW;EAAU;EAAY;CAAK,CAAC;CAElF,gBAAgB;EACd,QAAQ,WAAW;EACnB,cAAc,iBAAiB;EAC/B,SAAS,YAAY;EACrB,cAAc,MAAM;EACpB,aAAa,CAAC,MAAM;CACtB,GAAG;EAAC;EAAa;EAAmB;EAAc;CAAM,CAAC;CAEzD,gBAAgB;EACd,IAAI,CAAC,UAAU,WACb;EAGF,KAAU,KAAK;CACjB,GAAG;EAAC;EAAW;EAAQ;EAAM;CAAK,CAAC;CAEnC,gBAAgB;EACd,SAAS,OAAO,OAAoB;GAGlC,IAFgB,MAA+B,QAEnC,cAAc,KAAK,IAC7B;GAGF,KAAU,KAAK;EACjB;EAEA,OAAO,iBAAiB,cAAc,iBAAiB,MAAM;EAE7D,aAAa,OAAO,oBAAoB,cAAc,iBAAiB,MAAM;CAC/E,GAAG;EAAC;EAAM,KAAK;EAAI;CAAK,CAAC;CAEzB,gBAAgB;EACd,IACE,CAAC,cACD,CAAC,WAAW,WACZ,cACA,CAAC,kBAAkB,WACnB,OAAO,yBAAyB,aAEhC;EAGF,MAAM,WAAW,IAAI,sBAClB,YAAY;GACX,IAAI,QAAQ,MAAM,UAAU,MAAM,cAAc,GAC9C,SAAS;EAEb,GACA,EACE,YAAY,QACd,CACF;EAEA,SAAS,QAAQ,kBAAkB,OAAO;EAE1C,aAAa,SAAS,WAAW;CACnC,GAAG;EAAC;EAAY;EAAU,WAAW;EAAS;CAAU,CAAC;CAEzD,OAAO;EACL;EACA;EACA;EACA;EACA,SAAS,MAAM;EACf,cAAc,MAAM;EACpB,QAAQ,MAAM;EACd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -1,8 +1,9 @@
1
1
  import { Node } from '../../core/types.js';
2
- import { TableColumn, TablePagination, TableRow, TableState } from '../types.js';
2
+ import { TableColumn, TablePagination, TableRow, TableQuery } from '../types.js';
3
3
  export declare function getColumns(value: unknown): TableColumn[];
4
4
  export declare function getRows(value: unknown): TableRow[];
5
5
  export declare function getPagination(value: unknown): TablePagination;
6
- export declare function getState(value: unknown): TableState;
6
+ export declare function getQuery(value: unknown): TableQuery;
7
7
  export declare function getRowKey(row: TableRow, index: number): string;
8
8
  export declare function getRowActions(row: TableRow): Node[];
9
+ export declare function getRowDetail(row: TableRow): Node | null;
@@ -26,23 +26,25 @@ function getPagination(value) {
26
26
  if (typeof value !== "object" || value === null || Array.isArray(value)) return EMPTY_PAGINATION;
27
27
  return value;
28
28
  }
29
- function getState(value) {
29
+ function getQuery(value) {
30
30
  if (typeof value !== "object" || value === null || Array.isArray(value)) return {
31
31
  filters: [],
32
32
  sorts: [],
33
33
  page: 1,
34
34
  perPage: 25,
35
35
  tableFilters: {},
36
- tableFilterIndicators: []
36
+ tableFilterIndicators: [],
37
+ search: ""
37
38
  };
38
- const state = value;
39
+ const query = value;
39
40
  return {
40
- filters: getFilters(state.filters),
41
- sorts: Array.isArray(state.sorts) ? state.sorts : [],
42
- page: typeof state.page === "number" ? state.page : 1,
43
- perPage: typeof state.perPage === "number" ? state.perPage : 25,
44
- tableFilters: getTableFilters(state.tableFilters),
45
- tableFilterIndicators: getTableFilterIndicators(state.tableFilterIndicators)
41
+ filters: getFilters(query.filters),
42
+ sorts: Array.isArray(query.sorts) ? query.sorts : [],
43
+ page: typeof query.page === "number" ? query.page : 1,
44
+ perPage: typeof query.perPage === "number" ? query.perPage : 25,
45
+ tableFilters: getTableFilters(query.tableFilters),
46
+ tableFilterIndicators: getTableFilterIndicators(query.tableFilterIndicators),
47
+ search: typeof query.search === "string" ? query.search : ""
46
48
  };
47
49
  }
48
50
  /**
@@ -64,7 +66,11 @@ function getRowKey(row, index) {
64
66
  function getRowActions(row) {
65
67
  return Array.isArray(row.actions) ? row.actions : [];
66
68
  }
69
+ function getRowDetail(row) {
70
+ const detail = row.detail;
71
+ return typeof detail === "object" && detail !== null && !Array.isArray(detail) ? detail : null;
72
+ }
67
73
  //#endregion
68
- export { getColumns, getPagination, getRowActions, getRowKey, getRows, getState };
74
+ export { getColumns, getPagination, getQuery, getRowActions, getRowDetail, getRowKey, getRows };
69
75
 
70
76
  //# sourceMappingURL=payload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payload.js","names":[],"sources":["../../../resources/js/table/lib/payload.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type {\n FilterClause,\n TableColumn,\n TableFilterIndicator,\n TablePagination,\n TableRow,\n TableState,\n} from \"@lattice-php/lattice/table/types\";\n\nfunction getFilters(value: unknown): FilterClause[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (clause): clause is FilterClause =>\n typeof clause === \"object\" &&\n clause !== null &&\n typeof clause.field === \"string\" &&\n typeof clause.operator === \"string\" &&\n typeof clause.value === \"string\",\n );\n}\n\nexport function getColumns(value: unknown): TableColumn[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (column): column is TableColumn =>\n typeof column === \"object\" &&\n column !== null &&\n \"key\" in column &&\n \"props\" in column &&\n typeof column.key === \"string\" &&\n typeof column.props === \"object\" &&\n column.props !== null &&\n typeof (column.props as Record<string, unknown>).label === \"string\",\n );\n}\n\nexport function getRows(value: unknown): TableRow[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (row): row is TableRow => typeof row === \"object\" && row !== null && !Array.isArray(row),\n );\n}\n\nconst EMPTY_PAGINATION: TablePagination = {\n mode: \"none\",\n currentPage: null,\n lastPage: null,\n perPage: null,\n total: null,\n from: null,\n to: null,\n hasMore: false,\n nextPage: null,\n};\n\nexport function getPagination(value: unknown): TablePagination {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return EMPTY_PAGINATION;\n }\n\n return value as TablePagination;\n}\n\nexport function getState(value: unknown): TableState {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {\n filters: [],\n sorts: [],\n page: 1,\n perPage: 25,\n tableFilters: {},\n tableFilterIndicators: [],\n };\n }\n\n const state = value as Partial<TableState>;\n\n return {\n filters: getFilters(state.filters),\n sorts: Array.isArray(state.sorts) ? state.sorts : [],\n page: typeof state.page === \"number\" ? state.page : 1,\n perPage: typeof state.perPage === \"number\" ? state.perPage : 25,\n tableFilters: getTableFilters(state.tableFilters),\n tableFilterIndicators: getTableFilterIndicators(state.tableFilterIndicators),\n };\n}\n\n/**\n * The wire serializes an empty filter map as `[]` and a populated one as an\n * object, so coerce both to a plain `key => value` record.\n */\nfunction getTableFilters(value: unknown): Record<string, Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(value).filter(\n (entry): entry is [string, Record<string, unknown>] =>\n typeof entry[1] === \"object\" && entry[1] !== null && !Array.isArray(entry[1]),\n ),\n );\n}\n\nfunction getTableFilterIndicators(value: unknown): TableFilterIndicator[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (indicator): indicator is TableFilterIndicator =>\n typeof indicator === \"object\" &&\n indicator !== null &&\n typeof indicator.filter === \"string\" &&\n typeof indicator.label === \"string\" &&\n typeof indicator.value === \"string\",\n );\n}\n\nexport function getRowKey(row: TableRow, index: number): string {\n const key = row.id ?? row.uuid ?? row.key ?? index;\n\n return String(key);\n}\n\nexport function getRowActions(row: TableRow): Node[] {\n return Array.isArray(row.actions) ? (row.actions as Node[]) : [];\n}\n"],"mappings":";AAUA,SAAS,WAAW,OAAgC;CAClD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,WACC,OAAO,WAAW,YAClB,WAAW,QACX,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,aAAa,YAC3B,OAAO,OAAO,UAAU,QAC5B;AACF;AAEA,SAAgB,WAAW,OAA+B;CACxD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,WACC,OAAO,WAAW,YAClB,WAAW,QACX,SAAS,UACT,WAAW,UACX,OAAO,OAAO,QAAQ,YACtB,OAAO,OAAO,UAAU,YACxB,OAAO,UAAU,QACjB,OAAQ,OAAO,MAAkC,UAAU,QAC/D;AACF;AAEA,SAAgB,QAAQ,OAA4B;CAClD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,QAAyB,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,GAAG,CACzF;AACF;AAEA,IAAM,mBAAoC;CACxC,MAAM;CACN,aAAa;CACb,UAAU;CACV,SAAS;CACT,OAAO;CACP,MAAM;CACN,IAAI;CACJ,SAAS;CACT,UAAU;AACZ;AAEA,SAAgB,cAAc,OAAiC;CAC7D,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO;CAGT,OAAO;AACT;AAEA,SAAgB,SAAS,OAA4B;CACnD,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO;EACL,SAAS,CAAC;EACV,OAAO,CAAC;EACR,MAAM;EACN,SAAS;EACT,cAAc,CAAC;EACf,uBAAuB,CAAC;CAC1B;CAGF,MAAM,QAAQ;CAEd,OAAO;EACL,SAAS,WAAW,MAAM,OAAO;EACjC,OAAO,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC;EACnD,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;EACpD,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;EAC7D,cAAc,gBAAgB,MAAM,YAAY;EAChD,uBAAuB,yBAAyB,MAAM,qBAAqB;CAC7E;AACF;;;;;AAMA,SAAS,gBAAgB,OAAyD;CAChF,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO,CAAC;CAGV,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,EAAE,QACnB,UACC,OAAO,MAAM,OAAO,YAAY,MAAM,OAAO,QAAQ,CAAC,MAAM,QAAQ,MAAM,EAAE,CAChF,CACF;AACF;AAEA,SAAS,yBAAyB,OAAwC;CACxE,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,cACC,OAAO,cAAc,YACrB,cAAc,QACd,OAAO,UAAU,WAAW,YAC5B,OAAO,UAAU,UAAU,YAC3B,OAAO,UAAU,UAAU,QAC/B;AACF;AAEA,SAAgB,UAAU,KAAe,OAAuB;CAC9D,MAAM,MAAM,IAAI,MAAM,IAAI,QAAQ,IAAI,OAAO;CAE7C,OAAO,OAAO,GAAG;AACnB;AAEA,SAAgB,cAAc,KAAuB;CACnD,OAAO,MAAM,QAAQ,IAAI,OAAO,IAAK,IAAI,UAAqB,CAAC;AACjE"}
1
+ {"version":3,"file":"payload.js","names":[],"sources":["../../../resources/js/table/lib/payload.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport type {\n FilterClause,\n FilterIndicator,\n TableColumn,\n TablePagination,\n TableRow,\n TableQuery,\n} from \"@lattice-php/lattice/table/types\";\n\nfunction getFilters(value: unknown): FilterClause[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (clause): clause is FilterClause =>\n typeof clause === \"object\" &&\n clause !== null &&\n typeof clause.field === \"string\" &&\n typeof clause.operator === \"string\" &&\n typeof clause.value === \"string\",\n );\n}\n\nexport function getColumns(value: unknown): TableColumn[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (column): column is TableColumn =>\n typeof column === \"object\" &&\n column !== null &&\n \"key\" in column &&\n \"props\" in column &&\n typeof column.key === \"string\" &&\n typeof column.props === \"object\" &&\n column.props !== null &&\n typeof (column.props as Record<string, unknown>).label === \"string\",\n );\n}\n\nexport function getRows(value: unknown): TableRow[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (row): row is TableRow => typeof row === \"object\" && row !== null && !Array.isArray(row),\n );\n}\n\nconst EMPTY_PAGINATION: TablePagination = {\n mode: \"none\",\n currentPage: null,\n lastPage: null,\n perPage: null,\n total: null,\n from: null,\n to: null,\n hasMore: false,\n nextPage: null,\n};\n\nexport function getPagination(value: unknown): TablePagination {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return EMPTY_PAGINATION;\n }\n\n return value as TablePagination;\n}\n\nexport function getQuery(value: unknown): TableQuery {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {\n filters: [],\n sorts: [],\n page: 1,\n perPage: 25,\n tableFilters: {},\n tableFilterIndicators: [],\n search: \"\",\n };\n }\n\n const query = value as Partial<TableQuery>;\n\n return {\n filters: getFilters(query.filters),\n sorts: Array.isArray(query.sorts) ? query.sorts : [],\n page: typeof query.page === \"number\" ? query.page : 1,\n perPage: typeof query.perPage === \"number\" ? query.perPage : 25,\n tableFilters: getTableFilters(query.tableFilters),\n tableFilterIndicators: getTableFilterIndicators(query.tableFilterIndicators),\n search: typeof query.search === \"string\" ? query.search : \"\",\n };\n}\n\n/**\n * The wire serializes an empty filter map as `[]` and a populated one as an\n * object, so coerce both to a plain `key => value` record.\n */\nfunction getTableFilters(value: unknown): Record<string, Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(value).filter(\n (entry): entry is [string, Record<string, unknown>] =>\n typeof entry[1] === \"object\" && entry[1] !== null && !Array.isArray(entry[1]),\n ),\n );\n}\n\nfunction getTableFilterIndicators(value: unknown): FilterIndicator[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value.filter(\n (indicator): indicator is FilterIndicator =>\n typeof indicator === \"object\" &&\n indicator !== null &&\n typeof indicator.filter === \"string\" &&\n typeof indicator.label === \"string\" &&\n typeof indicator.value === \"string\",\n );\n}\n\nexport function getRowKey(row: TableRow, index: number): string {\n const key = row.id ?? row.uuid ?? row.key ?? index;\n\n return String(key);\n}\n\nexport function getRowActions(row: TableRow): Node[] {\n return Array.isArray(row.actions) ? (row.actions as Node[]) : [];\n}\n\nexport function getRowDetail(row: TableRow): Node | null {\n const detail = row.detail;\n\n return typeof detail === \"object\" && detail !== null && !Array.isArray(detail)\n ? (detail as Node)\n : null;\n}\n"],"mappings":";AAUA,SAAS,WAAW,OAAgC;CAClD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,WACC,OAAO,WAAW,YAClB,WAAW,QACX,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,aAAa,YAC3B,OAAO,OAAO,UAAU,QAC5B;AACF;AAEA,SAAgB,WAAW,OAA+B;CACxD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,WACC,OAAO,WAAW,YAClB,WAAW,QACX,SAAS,UACT,WAAW,UACX,OAAO,OAAO,QAAQ,YACtB,OAAO,OAAO,UAAU,YACxB,OAAO,UAAU,QACjB,OAAQ,OAAO,MAAkC,UAAU,QAC/D;AACF;AAEA,SAAgB,QAAQ,OAA4B;CAClD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,QAAyB,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,GAAG,CACzF;AACF;AAEA,IAAM,mBAAoC;CACxC,MAAM;CACN,aAAa;CACb,UAAU;CACV,SAAS;CACT,OAAO;CACP,MAAM;CACN,IAAI;CACJ,SAAS;CACT,UAAU;AACZ;AAEA,SAAgB,cAAc,OAAiC;CAC7D,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO;CAGT,OAAO;AACT;AAEA,SAAgB,SAAS,OAA4B;CACnD,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO;EACL,SAAS,CAAC;EACV,OAAO,CAAC;EACR,MAAM;EACN,SAAS;EACT,cAAc,CAAC;EACf,uBAAuB,CAAC;EACxB,QAAQ;CACV;CAGF,MAAM,QAAQ;CAEd,OAAO;EACL,SAAS,WAAW,MAAM,OAAO;EACjC,OAAO,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC;EACnD,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;EACpD,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;EAC7D,cAAc,gBAAgB,MAAM,YAAY;EAChD,uBAAuB,yBAAyB,MAAM,qBAAqB;EAC3E,QAAQ,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;CAC5D;AACF;;;;;AAMA,SAAS,gBAAgB,OAAyD;CAChF,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,OAAO,CAAC;CAGV,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,EAAE,QACnB,UACC,OAAO,MAAM,OAAO,YAAY,MAAM,OAAO,QAAQ,CAAC,MAAM,QAAQ,MAAM,EAAE,CAChF,CACF;AACF;AAEA,SAAS,yBAAyB,OAAmC;CACnE,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO,CAAC;CAGV,OAAO,MAAM,QACV,cACC,OAAO,cAAc,YACrB,cAAc,QACd,OAAO,UAAU,WAAW,YAC5B,OAAO,UAAU,UAAU,YAC3B,OAAO,UAAU,UAAU,QAC/B;AACF;AAEA,SAAgB,UAAU,KAAe,OAAuB;CAC9D,MAAM,MAAM,IAAI,MAAM,IAAI,QAAQ,IAAI,OAAO;CAE7C,OAAO,OAAO,GAAG;AACnB;AAEA,SAAgB,cAAc,KAAuB;CACnD,OAAO,MAAM,QAAQ,IAAI,OAAO,IAAK,IAAI,UAAqB,CAAC;AACjE;AAEA,SAAgB,aAAa,KAA4B;CACvD,MAAM,SAAS,IAAI;CAEnB,OAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,CAAC,MAAM,QAAQ,MAAM,IACxE,SACD;AACN"}
@@ -1,9 +1,9 @@
1
1
  import { ColumnWidth } from '../../types/generated.js';
2
- import { TableColumn, TableSort, TableState } from '../types.js';
3
- export declare function getColumnSort(state: TableState, column: TableColumn): TableSort | undefined;
2
+ import { TableColumn, TableSort, TableQuery } from '../types.js';
3
+ export declare function getColumnSort(query: TableQuery, column: TableColumn): TableSort | undefined;
4
4
  export declare function getColumnAriaSort(sort: TableSort | undefined): "ascending" | "descending" | undefined;
5
- export declare function buildEndpoint(endpoint: string, state: TableState): string;
6
- export declare function getQueryParams(state: TableState): Record<string, unknown>;
5
+ export declare function buildEndpoint(endpoint: string, query: TableQuery): string;
6
+ export declare function getQueryParams(query: TableQuery): Record<string, unknown>;
7
7
  export declare const VALUELESS_FILTER_OPERATORS: Set<string>;
8
8
  export declare function operatorLabel(operator: string): string;
9
9
  export declare function getSortDirectionLabel(direction: string): string;
@@ -14,7 +14,7 @@ export declare function getTableSizingColumns(columns: TableColumn[]): {
14
14
  label: string | null;
15
15
  width: ColumnWidth;
16
16
  }[];
17
- export declare function getTableUtilityTracks(hasActions: boolean, hasSelection: boolean): {
17
+ export declare function getTableUtilityTracks(hasActions: boolean, hasSelection: boolean, hasExpander?: boolean): {
18
18
  leadingTracks: string[];
19
19
  trailingTracks: string[];
20
20
  };