@12-apps/ui 6.13.0 → 6.13.2

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 (123) hide show
  1. package/dist/_internal/components/data-display/Carousel/Carousel.js +2 -2
  2. package/dist/_internal/components/data-display/Chart/Chart.js +3 -3
  3. package/dist/_internal/components/data-display/Chart/SpecChart.js +6 -6
  4. package/dist/_internal/components/data-display/Chart/chart-renderers.js +2 -2
  5. package/dist/_internal/components/data-display/Chart/chart-spec.js +2 -2
  6. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +1 -1
  7. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +21 -20
  8. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +27 -26
  9. package/dist/_internal/components/data-display/DataViews/base-card.js +2 -2
  10. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +5 -5
  11. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +4 -4
  12. package/dist/_internal/components/data-display/DataViews/base-list-card.js +6 -6
  13. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +4 -4
  14. package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +3 -3
  15. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +3 -3
  16. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +5 -5
  17. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +17 -17
  18. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +5 -5
  19. package/dist/_internal/components/data-display/DataViews/data-views-layout-context.js +2 -2
  20. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +3 -3
  21. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +4 -4
  22. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +2 -2
  23. package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +3 -3
  24. package/dist/_internal/components/data-display/DataViews/data-views-selection.js +1 -1
  25. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +6 -6
  26. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +2 -2
  27. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +5 -5
  28. package/dist/_internal/components/data-display/DataViews/data-views-types.js +1 -1
  29. package/dist/_internal/components/data-display/DataViews/data-views-writers.js +9 -0
  30. package/dist/_internal/components/data-display/DataViews/data-views-writers.js.map +1 -0
  31. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +3 -3
  32. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +4 -3
  33. package/dist/_internal/components/data-display/DataViews/use-saved-views-controller.js +2 -2
  34. package/dist/_internal/components/data-display/index.js +14 -14
  35. package/dist/_internal/components/index.js +14 -14
  36. package/dist/charts.js +11 -11
  37. package/dist/{chunk-TOUSE63W.js → chunk-2UCJJACD.js} +8 -10
  38. package/dist/chunk-2UCJJACD.js.map +1 -0
  39. package/dist/{chunk-QRKBBOSY.js → chunk-4KSOSI3U.js} +4 -4
  40. package/dist/{chunk-IN642YHK.js → chunk-4VNUOSTQ.js} +2 -2
  41. package/dist/{chunk-XPS7FWZS.js → chunk-4ZEU22L2.js} +4 -4
  42. package/dist/{chunk-NC2AATCC.js → chunk-6PFBYCBU.js} +2 -2
  43. package/dist/{chunk-WXHJG2UU.js → chunk-6U7NA74A.js} +2 -2
  44. package/dist/{chunk-CXA6UNFF.js → chunk-AP3PVR3T.js} +5 -5
  45. package/dist/{chunk-FZHKKLOO.js → chunk-AWTERXCW.js} +2 -2
  46. package/dist/{chunk-XULTDO56.js → chunk-BVGR7OYA.js} +4 -4
  47. package/dist/{chunk-YQJMVUBG.js → chunk-CZPU5TW3.js} +2 -2
  48. package/dist/{chunk-ZQPG57GA.js → chunk-EICVL6GS.js} +2 -2
  49. package/dist/{chunk-P55UFXYW.js → chunk-HGBZZDP6.js} +2 -2
  50. package/dist/{chunk-JHBQZZHT.js → chunk-HNDUCGM3.js} +3 -3
  51. package/dist/{chunk-WIEXYVMU.js → chunk-HR7YTBR7.js} +2 -2
  52. package/dist/{chunk-NPEKJXVV.js → chunk-HRJ27X5B.js} +4 -4
  53. package/dist/{chunk-QEPGWTJT.js → chunk-LHHAYZ55.js} +1 -1
  54. package/dist/chunk-LHHAYZ55.js.map +1 -0
  55. package/dist/chunk-LLZWB32X.js +36 -0
  56. package/dist/chunk-LLZWB32X.js.map +1 -0
  57. package/dist/{chunk-ZHPKFV7Y.js → chunk-N6JGYVRY.js} +2 -2
  58. package/dist/{chunk-E2H7MBPM.js → chunk-OGGHD64H.js} +2 -2
  59. package/dist/{chunk-JPDKRGYI.js → chunk-PDGAFQ6Z.js} +3 -3
  60. package/dist/{chunk-W3UM2KEW.js → chunk-Q4ITS2EP.js} +11 -10
  61. package/dist/chunk-Q4ITS2EP.js.map +1 -0
  62. package/dist/{chunk-XIYPVNEB.js → chunk-QQE2PVLO.js} +3 -3
  63. package/dist/{chunk-GOWBYHYW.js → chunk-R6SBP5M5.js} +4 -4
  64. package/dist/{chunk-XYRS4JOF.js → chunk-RDYBS45D.js} +4 -4
  65. package/dist/{chunk-BMAOQDVY.js → chunk-RRYQG5Y6.js} +4 -4
  66. package/dist/{chunk-WLCVOQCJ.js → chunk-RUO4D4N6.js} +3 -3
  67. package/dist/{chunk-YRFKPRV2.js → chunk-SCGVB7DS.js} +2 -2
  68. package/dist/chunk-U5FOJBLG.js +19 -0
  69. package/dist/chunk-U5FOJBLG.js.map +1 -0
  70. package/dist/{chunk-WKRSVGT6.js → chunk-WXBBWSNU.js} +2 -2
  71. package/dist/{chunk-BZTFPSWT.js → chunk-XEE7PLDR.js} +4 -4
  72. package/dist/{chunk-ZIPCGZA3.js → chunk-ZPIMPOHV.js} +2 -2
  73. package/dist/data-display/CardKit.js +3 -3
  74. package/dist/data-display/Carousel.js +2 -2
  75. package/dist/data-display/Chart.js +11 -11
  76. package/dist/data-display/DataGrid.js +1 -1
  77. package/dist/data-display/DataViews.js +32 -31
  78. package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts.map +1 -1
  79. package/dist/types/components/data-display/DataViews/data-views-selection.d.ts +31 -2
  80. package/dist/types/components/data-display/DataViews/data-views-selection.d.ts.map +1 -1
  81. package/dist/types/components/data-display/DataViews/data-views-types.d.ts +8 -0
  82. package/dist/types/components/data-display/DataViews/data-views-types.d.ts.map +1 -1
  83. package/dist/types/components/data-display/DataViews/data-views-writers.d.ts +20 -0
  84. package/dist/types/components/data-display/DataViews/data-views-writers.d.ts.map +1 -0
  85. package/dist/types/components/data-display/DataViews/use-data-views-state.d.ts +10 -2
  86. package/dist/types/components/data-display/DataViews/use-data-views-state.d.ts.map +1 -1
  87. package/package.json +1 -1
  88. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +2 -1
  89. package/src/components/data-display/DataViews/data-views-selection.ts +61 -6
  90. package/src/components/data-display/DataViews/data-views-types.ts +11 -0
  91. package/src/components/data-display/DataViews/data-views-writers.ts +45 -0
  92. package/src/components/data-display/DataViews/use-data-views-state.ts +15 -12
  93. package/dist/chunk-QEPGWTJT.js.map +0 -1
  94. package/dist/chunk-TOUSE63W.js.map +0 -1
  95. package/dist/chunk-W3UM2KEW.js.map +0 -1
  96. package/dist/chunk-WTOTWP6A.js +0 -27
  97. package/dist/chunk-WTOTWP6A.js.map +0 -1
  98. /package/dist/{chunk-QRKBBOSY.js.map → chunk-4KSOSI3U.js.map} +0 -0
  99. /package/dist/{chunk-IN642YHK.js.map → chunk-4VNUOSTQ.js.map} +0 -0
  100. /package/dist/{chunk-XPS7FWZS.js.map → chunk-4ZEU22L2.js.map} +0 -0
  101. /package/dist/{chunk-NC2AATCC.js.map → chunk-6PFBYCBU.js.map} +0 -0
  102. /package/dist/{chunk-WXHJG2UU.js.map → chunk-6U7NA74A.js.map} +0 -0
  103. /package/dist/{chunk-CXA6UNFF.js.map → chunk-AP3PVR3T.js.map} +0 -0
  104. /package/dist/{chunk-FZHKKLOO.js.map → chunk-AWTERXCW.js.map} +0 -0
  105. /package/dist/{chunk-XULTDO56.js.map → chunk-BVGR7OYA.js.map} +0 -0
  106. /package/dist/{chunk-YQJMVUBG.js.map → chunk-CZPU5TW3.js.map} +0 -0
  107. /package/dist/{chunk-ZQPG57GA.js.map → chunk-EICVL6GS.js.map} +0 -0
  108. /package/dist/{chunk-P55UFXYW.js.map → chunk-HGBZZDP6.js.map} +0 -0
  109. /package/dist/{chunk-JHBQZZHT.js.map → chunk-HNDUCGM3.js.map} +0 -0
  110. /package/dist/{chunk-WIEXYVMU.js.map → chunk-HR7YTBR7.js.map} +0 -0
  111. /package/dist/{chunk-NPEKJXVV.js.map → chunk-HRJ27X5B.js.map} +0 -0
  112. /package/dist/{chunk-ZHPKFV7Y.js.map → chunk-N6JGYVRY.js.map} +0 -0
  113. /package/dist/{chunk-E2H7MBPM.js.map → chunk-OGGHD64H.js.map} +0 -0
  114. /package/dist/{chunk-JPDKRGYI.js.map → chunk-PDGAFQ6Z.js.map} +0 -0
  115. /package/dist/{chunk-XIYPVNEB.js.map → chunk-QQE2PVLO.js.map} +0 -0
  116. /package/dist/{chunk-GOWBYHYW.js.map → chunk-R6SBP5M5.js.map} +0 -0
  117. /package/dist/{chunk-XYRS4JOF.js.map → chunk-RDYBS45D.js.map} +0 -0
  118. /package/dist/{chunk-BMAOQDVY.js.map → chunk-RRYQG5Y6.js.map} +0 -0
  119. /package/dist/{chunk-WLCVOQCJ.js.map → chunk-RUO4D4N6.js.map} +0 -0
  120. /package/dist/{chunk-YRFKPRV2.js.map → chunk-SCGVB7DS.js.map} +0 -0
  121. /package/dist/{chunk-WKRSVGT6.js.map → chunk-WXBBWSNU.js.map} +0 -0
  122. /package/dist/{chunk-BZTFPSWT.js.map → chunk-XEE7PLDR.js.map} +0 -0
  123. /package/dist/{chunk-ZIPCGZA3.js.map → chunk-ZPIMPOHV.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/use-data-views-state.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { type GridColumn } from \"../DataGrid\";\nimport { type SortFieldDefinition } from \"../../layout/ContentToolbar\";\n\nimport { filterRows } from \"./data-views-filter\";\nimport {\n useColumnsWithActions,\n useRenderedColumns,\n type HideableColumn,\n} from \"./data-views-columns\";\nimport { computeActiveFilterCount, defaultSortFields } from \"./data-views-grid-helpers\";\nimport { resolveScope, useScopeConfigChecks, type ScopeConfig } from \"./data-views-scopes\";\nimport { serverDerived, useServerQuery } from \"./data-views-server-query\";\nimport { useSelection } from \"./data-views-selection\";\nimport {\n emptyViewState,\n type DataViewColumn,\n type DataViewServer,\n type DataViewState,\n type DataViewSyncState,\n type FilterFieldConfig,\n type RangeFieldConfig,\n type DataViewQuery,\n type RangeValue,\n type RowAction,\n} from \"./data-views-types\";\n\nexport type { HideableColumn };\n\n/** Inputs the hook needs to own the view state + derived data. */\ninterface UseDataViewsStateArgs<T extends Record<string, unknown>> {\n rows: T[];\n columns: DataViewColumn<T>[];\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n onRowClick?: (row: T) => void;\n appliedState?: DataViewState;\n /**\n * URL-driven controls (search/pills/ranges/sort) that re-apply on reference\n * change while preserving column visibility — see {@link DataViewSyncState}.\n */\n syncState?: DataViewSyncState;\n onStateChange?: (state: DataViewState) => void;\n testIdPrefix: string;\n sortFields?: SortFieldDefinition[];\n rowActions?: RowAction<T>[];\n rowActionsLeading?: (row: T) => React.ReactNode;\n /** Bespoke per-row menu rendered in the actions column instead of the auto kebab. */\n renderRowMenu?: (row: T) => React.ReactNode;\n /**\n * When present, the table is BACKEND-driven: `rows` is already the current\n * page (no in-browser filter/sort/paginate), and query changes re-fetch via\n * `server.onQueryChange`. Omit for the legacy client-side behaviour.\n */\n server?: DataViewServer;\n /**\n * The page-level partition rendered as tabs under the toolbar. Requires server\n * mode: a scope is applied at the BACKEND, never in the browser.\n */\n scopes?: ScopeConfig[];\n /**\n * The row field the scopes partition by, when the host knows it — used only to\n * reject the pill/scope clash at setup. See `assertNoScopePillOverlap`.\n */\n scopeFieldId?: string;\n}\n\n/** Everything the DataViewsGrid render needs; keeps the component itself thin. */\nexport interface DataViewsController<T extends Record<string, unknown>> {\n state: DataViewState;\n ranges: Record<string, RangeValue>;\n patch: (next: Partial<DataViewState>) => void;\n matched: T[];\n gridColumns: GridColumn<T>[];\n /** Columns eligible for the show/hide menu (hideable, with a text header). */\n hideableColumns: HideableColumn[];\n /** Every column id in reading order — what the Colunas tab reorders. */\n columnOrder: string[];\n /** Toggle one column's visibility in the current view state. */\n toggleColumn: (id: string, visible: boolean) => void;\n selectedIds: Set<string | number>;\n setSelectedIds: (ids: Set<string | number>) => void;\n /**\n * Add/remove ONE id from the selection. The card and board bodies both need\n * it, so it lives here rather than being written out twice at the call sites —\n * one selection model, one toggle, identical in every layout.\n */\n toggleId: (id: string | number) => void;\n selectedRows: T[];\n clearSelection: () => void;\n selectAll: () => void;\n filterOpen: boolean;\n setFilterOpen: (open: boolean) => void;\n resolvedSortFields: SortFieldDefinition[];\n activeSortField: string;\n activeSortOrder: \"asc\" | \"desc\";\n activeFilterCount: number;\n /** True when the table is backend-driven (server mode). */\n serverMode: boolean;\n /** Server-mode pagination: 1-based current page (1 when client mode). */\n serverPage: number;\n /** Server-mode pagination: total pages (1 when client mode). */\n serverPageCount: number;\n /** Server-mode: total matched rows across all pages (drives the counter). */\n serverTotalCount: number;\n /** Server-mode: request a specific 1-based page (re-fetches via onQueryChange). */\n changePage: (page: number) => void;\n /**\n * The active scope id, RESOLVED against the declared scopes (see\n * `resolveScope`). `undefined` when the table declares none — which is what\n * keeps `scope` out of the emitted query for every table that never opted in.\n */\n scope: string | undefined;\n /** Select a scope: re-fetches from page 1 and drops the selection. */\n setScope: (id: string) => void;\n /**\n * The query the grid is currently showing. Read by Export, which hands it\n * back to the host UNPAGINATED — so an export follows the filters rather\n * than the 25 rows that happen to be loaded.\n */\n currentQuery: DataViewQuery;\n /**\n * Server-supplied per-scope totals, passed through verbatim, or `undefined`\n * when the server omits them. NEVER falls back to counting `matched`: a count\n * off the loaded page is wrong under pagination, which is the bug scopes fix.\n */\n scopeCounts?: Record<string, number>;\n}\n\n/**\n * The rows to render: in server mode `rows` is already the current page (the\n * backend filtered/sorted/paginated), so it passes through untouched; otherwise\n * the client search/pill/range filter narrows it.\n */\nfunction useMatchedRows<T extends Record<string, unknown>>(\n server: DataViewServer | undefined,\n rows: T[],\n columns: DataViewColumn<T>[],\n fields: FilterFieldConfig<T>[],\n rangeFields: RangeFieldConfig<T>[],\n state: DataViewState,\n): T[] {\n return useMemo(\n () =>\n server\n ? rows\n : filterRows(\n rows,\n columns,\n fields,\n { search: state.search, pills: state.pills, ranges: state.ranges },\n rangeFields,\n ),\n [server, rows, columns, fields, rangeFields, state.search, state.pills, state.ranges],\n );\n}\n\n/** Add or remove one column id from the visible-columns list. */\nfunction nextVisibleColumns(current: string[], id: string, visible: boolean): string[] {\n const without = current.filter((colId) => colId !== id);\n return visible ? [...without, id] : without;\n}\n\n/**\n * Reconcile external state changes and surface every change to the caller:\n * - `appliedState` (a saved view) fully REPLACES the state — it is columns-\n * authoritative, so applying a view restores its filters, sort AND columns.\n * - `syncState` (URL-driven controls) MERGES over the current state, leaving\n * `visibleColumns` untouched — so browser back/forward or a same-route\n * deep-link re-applies search/pills/sort without wiping a user's hidden columns.\n * Each channel only fires when its own reference changes (after the first run).\n */\nfunction useStateSyncEffects(\n appliedState: DataViewState | undefined,\n syncState: DataViewSyncState | undefined,\n state: DataViewState,\n onStateChange: ((state: DataViewState) => void) | undefined,\n setState: React.Dispatch<React.SetStateAction<DataViewState>>,\n): void {\n const firstApplied = useRef(true);\n useEffect(() => {\n if (firstApplied.current) {\n firstApplied.current = false;\n return;\n }\n if (appliedState) setState(appliedState);\n // `setState` is a stable useState setter (passed in), included to satisfy\n // exhaustive-deps; the effect still only re-applies when `appliedState` changes.\n }, [appliedState, setState]);\n const firstSync = useRef(true);\n useEffect(() => {\n if (firstSync.current) {\n firstSync.current = false;\n return;\n }\n // Merge — keep the current `visibleColumns` (never URL-carried); only the\n // URL-driven controls change.\n if (syncState) setState((prev) => ({ ...prev, ...syncState }));\n }, [syncState, setState]);\n useEffect(() => {\n onStateChange?.(state);\n }, [state, onStateChange]);\n}\n\n/**\n * The seed view state: a saved view (`appliedState`) or a pristine all-columns\n * one, with the URL-driven controls (`syncState`) merged over it so a deep-linked\n * filter or scope is reflected on the FIRST render. Column visibility is never\n * URL-carried, so the merge cannot wipe it.\n */\nfunction seedState(\n appliedState: DataViewState | undefined,\n syncState: DataViewSyncState | undefined,\n allColumnIds: string[],\n): DataViewState {\n const seed = appliedState ?? emptyViewState(allColumnIds);\n return syncState ? { ...seed, ...syncState } : seed;\n}\n\n/**\n * Selecting a scope: record it, then DROP the selection.\n *\n * A scope change renders a different result set. A selection that survived it\n * would let a bulk action run against rows the user can no longer see — the\n * same reason changing any other part of the query clears it.\n */\nfunction makeSetScope(\n patch: (next: Partial<DataViewState>) => void,\n clearSelection: () => void,\n): (id: string) => void {\n return (id) => {\n patch({ scope: id });\n clearSelection();\n };\n}\n\n/**\n * The declared column ids in the stored reading order — the same tolerance\n * `applyOrder` uses, so the Colunas tab lists exactly what the grid renders.\n */\nfunction orderedColumnIds(allColumnIds: string[], order: string[] | undefined): string[] {\n if (!order || order.length === 0) return allColumnIds;\n const declared = new Set(allColumnIds);\n const kept = order.filter((id) => declared.has(id));\n const seen = new Set(kept);\n return [...kept, ...allColumnIds.filter((id) => !seen.has(id))];\n}\n\n/**\n * The query the grid is currently SHOWING — the same shape `onQueryChange`\n * emits, kept as a value so a host control (Exportar) can re-run it against the\n * backend rather than reading the loaded rows.\n */\nfunction liveQuery(\n state: DataViewState,\n scope: string | undefined,\n server: DataViewServer | undefined,\n matchedCount: number,\n): DataViewQuery {\n return {\n search: state.search,\n pills: state.pills,\n ranges: state.ranges ?? {},\n sortBy: state.sortBy,\n // Absent, not undefined, when the table declares no scopes.\n ...(scope !== undefined ? { scope } : {}),\n page: server?.page ?? 1,\n // Client mode has one page, and it is everything that matched.\n pageSize: server?.pageSize ?? matchedCount,\n };\n}\n\n/** The toolbar's active sort, read off the state's FIRST sort entry. */\nfunction activeSortOf(\n state: DataViewState,\n resolvedSortFields: SortFieldDefinition[],\n): { activeSortField: string; activeSortOrder: \"asc\" | \"desc\" } {\n const active = state.sortBy?.[0];\n return {\n activeSortField: active?.id ?? resolvedSortFields[0]?.value ?? \"\",\n activeSortOrder: active?.dir === \"desc\" ? \"desc\" : \"asc\",\n };\n}\n\n/**\n * Owns the DataViews view state (search/pills/ranges/sort/visibleColumns),\n * multi-select, the filter-panel toggle, and every derived value (filtered rows,\n * grid columns, active sort/filter counts). Extracted from the component so the\n * render stays within the size/complexity budget.\n */\nexport function useDataViewsState<T extends Record<string, unknown>>({\n rows,\n columns,\n fields,\n rangeFields,\n getRowId,\n onRowClick,\n appliedState,\n syncState,\n onStateChange,\n testIdPrefix,\n sortFields,\n rowActions,\n rowActionsLeading,\n renderRowMenu,\n server,\n scopes = [],\n scopeFieldId,\n}: UseDataViewsStateArgs<T>): DataViewsController<T> {\n useScopeConfigChecks(scopes, fields.map((field) => field.id), scopeFieldId, server !== undefined);\n const { columnsWithActions, allColumnIds } = useColumnsWithActions(columns, {\n rowActions,\n rowActionsLeading,\n renderRowMenu,\n testIdPrefix,\n getRowId,\n });\n // Seed once — see {@link seedState}.\n const [state, setState] = useState<DataViewState>(() =>\n seedState(appliedState, syncState, allColumnIds),\n );\n const [filterOpen, setFilterOpen] = useState(false);\n\n useStateSyncEffects(appliedState, syncState, state, onStateChange, setState);\n\n const patch = (next: Partial<DataViewState>): void => setState((prev) => ({ ...prev, ...next }));\n const matched = useMatchedRows(server, rows, columns, fields, rangeFields, state);\n // Resolved at READ time, every render: a stale deep link or a saved view naming\n // a scope that has since been removed falls back to the first declared scope\n // instead of putting an id the backend rejects on the wire.\n const scope = resolveScope(scopes, state.scope);\n // Server mode: re-fetch on query change (page resets to 1) + drive pagination.\n const { changePage } = useServerQuery(server, state, scope);\n const { gridColumns, hideableColumns } = useRenderedColumns(\n columnsWithActions,\n state.visibleColumns,\n onRowClick,\n state.order,\n );\n const toggleColumn = (id: string, visible: boolean): void =>\n setState((prev) => ({ ...prev, visibleColumns: nextVisibleColumns(prev.visibleColumns, id, visible) }));\n const selection = useSelection(matched, getRowId);\n const resolvedSortFields = sortFields ?? defaultSortFields(columns);\n\n return {\n state,\n ranges: state.ranges ?? {},\n patch,\n matched,\n gridColumns,\n hideableColumns,\n columnOrder: orderedColumnIds(allColumnIds, state.order),\n toggleColumn,\n ...selection,\n filterOpen,\n setFilterOpen,\n resolvedSortFields,\n ...activeSortOf(state, resolvedSortFields),\n activeFilterCount: computeActiveFilterCount(state, fields, rangeFields),\n ...serverDerived(server, matched.length),\n changePage,\n scope,\n setScope: makeSetScope(patch, selection.clearSelection),\n currentQuery: liveQuery(state, scope, server, matched.length),\n // Verbatim, or absent. See DataViewServer.scopeCounts for why there is no\n // client-side fallback.\n scopeCounts: server?.scopeCounts,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-grid-parts.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\nimport { TableFilter } from \"../../layout/TableFilter\";\nimport { Text } from \"../../typography/Text\";\nimport { Box } from \"../../../mui/Box\";\nimport { Stack } from \"../../../mui/Stack\";\n\nimport {\n DataViewsLayoutProvider,\n useDataViewsLayout,\n type DataViewsLayout,\n} from \"./data-views-layout-context\";\nimport { FilterDialog, GridFilterPanel } from \"./data-views-filter-panel\";\nimport { GridMain } from \"./data-views-grid-bodies\";\nimport type { ListGroupConfig } from \"./list-card-rails\";\nimport { InlineFilterControls } from \"./data-views-inline-bar\";\nimport { toOverflowFields, useFilterOverflow, type OverflowSplit } from \"./data-views-overflow\";\nimport { ShellToolbar } from \"./data-views-shell-toolbar\";\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { DataViewsEmpty } from \"./data-views-empty\";\nimport { DataViewsPagination } from \"./data-views-pagination\";\nimport type { BoardConfig } from \"./DataViewsBoard\";\nimport { type ScopeConfig } from \"./data-views-scopes\";\nimport { ScopeTabsSlot } from \"./data-views-scope-tabs\";\nimport { togglePillValues } from \"./data-views-grid-helpers\";\nimport type {\n DataViewCardSelection,\n FilterFieldConfig,\n RangeFieldConfig,\n RangeValue,\n RowAction,\n} from \"./data-views-types\";\nimport type { DataViewsController } from \"./use-data-views-state\";\n\n/* ── Header row ──────────────────────────────────────────────────────────── */\n\n/**\n * The grid's own header row: the page title on the left, the primary page\n * actions on the right.\n *\n * `title` and `headerActions` were DECLARED on `DataViewsGridProps` and\n * `DataViewsTableBaseProps` but never destructured or forwarded — dead props\n * whose types lied to every caller that set them. Wired here rather than\n * deleted: a table that carries its own title keeps the title, the scope tabs\n * and the toolbar as one block, instead of the page having to space them.\n *\n * Renders NOTHING when neither is supplied, so no existing table gains a row.\n */\nfunction GridHeaderRow({\n title,\n headerActions,\n testIdPrefix,\n}: {\n title?: string;\n headerActions?: React.ReactNode;\n testIdPrefix: string;\n}): React.JSX.Element | null {\n if (!title && !headerActions) return null;\n return (\n <Box\n data-testid={`${testIdPrefix}-header`}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 2,\n flexWrap: \"wrap\",\n pb: 1.5,\n }}\n >\n {title ? (\n <Text variant=\"heading\" size=\"lg\" as=\"h2\">\n {title}\n </Text>\n ) : (\n <Box />\n )}\n {headerActions && <Box sx={{ display: \"flex\", alignItems: \"center\", gap: 1 }}>{headerActions}</Box>}\n </Box>\n );\n}\n\n/* ── Layout ⇄ view-state mirror ──────────────────────────────────────────── */\n\n/**\n * Mirrors the LIVE layout back into the view state, so saving a view captures\n * the layout the user is actually looking at.\n *\n * A component rather than a callback prop because only something INSIDE the\n * provider can read the layout, and only the controller can write the state.\n * The `stored !== layout` guard is what makes it idempotent: `c` is rebuilt on\n * every render, so an unguarded effect here would patch → re-render → patch.\n *\n * It re-fires when `stored` changes too, which is the case that matters after\n * applying a saved view: `appliedState` REPLACES the state, so a view saved\n * before layouts were captured clears `state.layout`, and the mirror puts the\n * current one back rather than leaving the next save with nothing to store.\n */\nfunction LayoutStateSync<T extends Record<string, unknown>>({\n c,\n}: {\n c: DataViewsController<T>;\n}): null {\n const { layout } = useDataViewsLayout();\n const stored = c.state.layout;\n useEffect(() => {\n if (stored !== layout) c.patch({ layout });\n // `c` is intentionally out of the deps — see the guard above.\n }, [layout, stored]);\n return null;\n}\n\n/* ── Shell (composes toolbar + body + panel) ─────────────────────────────── */\n\n/** The shared filter-surface props consumed by the inline bar, panel, and modal. */\ninterface FilterSurfaceProps<T extends Record<string, unknown>> {\n testIdPrefix: string;\n search: string;\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n pills: Record<string, string[]>;\n ranges: Record<string, RangeValue>;\n onSearchChange: (value: string) => void;\n onTogglePill: (fieldId: string, value: string, checked: boolean) => void;\n onChangeRange: (fieldId: string, range: RangeValue) => void;\n onClearField: (fieldId: string) => void;\n onClearAll: () => void;\n}\n\n/**\n * Derives the responsive filter state (which surface to show at this width) and\n * the filter-mutation handlers from the controller — pulled out of `GridShell`\n * so the component body stays under the size/complexity budget.\n */\n/** Grouped rather than positional: the list had grown past readability. */\ninterface GridShellFiltersArgs<T extends Record<string, unknown>> {\n c: DataViewsController<T>;\n inlineFilters: boolean;\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n testIdPrefix: string;\n alwaysShowSearch: boolean;\n /** Is \"Exportar\" on the bar? Half the right cluster's cost when it is not. */\n hasExport: boolean;\n}\n\nfunction useGridShellFilters<T extends Record<string, unknown>>({\n c,\n inlineFilters,\n fields,\n rangeFields,\n testIdPrefix,\n alwaysShowSearch,\n hasExport,\n}: GridShellFiltersArgs<T>): {\n showInline: boolean;\n useModal: boolean;\n inlineVisible: boolean;\n filterProps: FilterSurfaceProps<T>;\n split: OverflowSplit<T>;\n onControlOpenChange: (open: boolean) => void;\n} {\n const { state } = c;\n // How many filter controls are open. A COUNT, not a flag: closing one popover\n // by opening another overlaps, and a boolean would unfreeze mid-handover.\n const [openControls, setOpenControls] = useState(0);\n // ONE measurement for the whole shell: the filter row decides which controls\n // it can keep, and the TOOLBAR needs the same answer to drop its labels.\n // Measuring twice would let the two disagree at the crossover width.\n const split = useFilterOverflow(\n toOverflowFields(fields, rangeFields),\n state.pills,\n c.ranges,\n openControls > 0,\n hasExport,\n );\n // THE BAR RENDERS AT EVERY WIDTH. It used to be swapped for a full-screen\n // filter MODAL below `lg`, which was the responsive strategy before the\n // measured ladder existed — and the two now do the same job, badly together:\n // the modal took the bar away at 1199px, and with it the very degradation\n // (labels off, search collapsed, filters into \"Mais\") that exists to make a\n // narrow bar work. So a 900px window got no bar and no ladder, and the\n // operator lost the search entirely rather than gaining a compact one.\n //\n // The ladder is measured, so it already covers every width the modal did.\n const showInline = inlineFilters;\n const useModal = false;\n const inlineVisible =\n showInline &&\n (alwaysShowSearch || fields.length > 0 || rangeFields.length > 0 || state.search !== \"\");\n const filterProps: FilterSurfaceProps<T> = {\n testIdPrefix,\n search: state.search,\n fields,\n rangeFields,\n pills: state.pills,\n ranges: c.ranges,\n onSearchChange: (value) => c.patch({ search: value }),\n onTogglePill: (fieldId, value, checked) =>\n c.patch({ pills: { ...state.pills, [fieldId]: togglePillValues(state.pills[fieldId], value, checked) } }),\n onChangeRange: (fieldId, range) => c.patch({ ranges: { ...c.ranges, [fieldId]: range } }),\n onClearField: (fieldId) => c.patch({ pills: { ...state.pills, [fieldId]: [] } }),\n onClearAll: () => c.patch({ search: \"\", pills: {}, ranges: {} }),\n };\n return {\n showInline,\n useModal,\n inlineVisible,\n filterProps,\n split,\n onControlOpenChange: (open) =>\n setOpenControls((count) => Math.max(0, count + (open ? 1 : -1))),\n };\n}\n\ninterface GridShellProps<T extends Record<string, unknown>> {\n c: DataViewsController<T>;\n rows: T[];\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n testIdPrefix: string;\n dataTestId?: string;\n emptyState?: React.ReactNode;\n toolbarRightSlot?: React.ReactNode;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** Opt-in \"Grade\" (cards) layout: renders each row as an entity-supplied card.\n * Omit ⇒ table only (no layout toggle). */\n renderCard?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /**\n * Opt-in \"Quadro\" (board) layout. Needs `renderCard` too — the board reuses\n * the entity's card, so a board config without one simply offers no board\n * rather than failing: that is a config gap, not a runtime error.\n */\n board?: BoardConfig<T>;\n /** Opt-in \"Lista\" layout: one full-width, entity-rendered row per record. */\n renderListRow?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** The Lista's shared columns, so its rows line up by construction. */\n listGroup?: ListGroupConfig<T>;\n /** The page-level partition rendered as tabs under the toolbar. */\n scopes?: ScopeConfig[];\n /**\n * The row field the scopes partition by. Compared against the board's\n * `groupBy` so the two are not shown as the same partition twice.\n */\n scopeFieldId?: string;\n /** Per-sort-field value kind, so directions read in the column's own terms. */\n sortKinds?: Record<string, string>;\n /** The saved-view chrome bracketing the Exibir panel. */\n displayView?: DisplayPanelView;\n /** Injected export — the host re-queries; the grid never fetches. */\n exportConfig?: DataViewExport;\n /** Page title in the grid's own header row, above the scopes + toolbar. */\n title?: string;\n /** Primary page actions rendered at the header row's right. */\n headerActions?: React.ReactNode;\n /** Which layout to show first when the user has expressed no preference (default \"table\"). */\n defaultLayout?: DataViewsLayout;\n /** Pin to `defaultLayout`, ignoring the remembered preference (stories/docs). */\n ignoreStoredLayout?: boolean;\n /**\n * Opt into the responsive inline filter UX: a collapsible filter row below the\n * toolbar on wide screens and a modal on narrow ones. When false (default),\n * keep the classic slide-in filter panel opened by the \"Filtros\" button.\n */\n inlineFilters?: boolean;\n /**\n * Keep the inline search box on screen even with no filter fields and no\n * active search. Without it a grid whose only filter IS the search (`fields`\n * empty) can never OFFER one: the row renders only once a search exists, so\n * the operator would have to hand-edit the URL to start one. Default false —\n * every grid that ships filter fields already shows the row.\n */\n alwaysShowSearch?: boolean;\n}\n\n/** The scrollable content region: scope tabs, toolbar, filter bar, body, pager. */\nfunction ShellStack<T extends Record<string, unknown>>({\n props,\n filters,\n}: {\n props: GridShellProps<T>;\n filters: ReturnType<typeof useGridShellFilters<T>>;\n}): React.JSX.Element {\n const copy = useDataViewsCopy();\n const { c, testIdPrefix, dataTestId, scopes = [], emptyState, inlineFilters = false } = props;\n const { showInline, useModal, inlineVisible, filterProps, split, onControlOpenChange } = filters;\n // The grid renders the FILTERED empty state itself — it is the only party\n // that knows a filter is applied. See {@link DataViewsEmpty}.\n const body = (\n <DataViewsEmpty\n filtered={c.activeFilterCount > 0 || c.state.search !== \"\"}\n onClearFilters={() => c.patch({ search: \"\", pills: {}, ranges: {} })}\n emptyState={emptyState}\n testIdPrefix={testIdPrefix}\n />\n );\n return (\n <TableFilter\n copy={copy.tableFilter} open={c.filterOpen} onOpenChange={c.setFilterOpen}\n hasActiveFilters={c.activeFilterCount > 0}\n >\n <Stack spacing={0} data-testid={dataTestId ? `${dataTestId}-container` : undefined}>\n <GridHeaderRow title={props.title} headerActions={props.headerActions} testIdPrefix={testIdPrefix} />\n <ShellToolbar\n c={c}\n rows={props.rows}\n sortKinds={props.sortKinds}\n displayView={props.displayView}\n exportConfig={props.exportConfig}\n filterControls={\n inlineVisible ? (\n <InlineFilterControls\n {...filterProps} split={split} activeFilterCount={c.activeFilterCount}\n onControlOpenChange={onControlOpenChange}\n />\n ) : undefined\n }\n barRef={split.barRef}\n testIdPrefix={testIdPrefix}\n rowActions={props.rowActions}\n bulkActions={props.bulkActions}\n toolbarRightSlot={props.toolbarRightSlot}\n compactControls={showInline && split.compactControls}\n counterHidden={showInline && split.counterHidden}\n showInline={showInline}\n />\n <ScopeTabsSlot\n scopes={scopes} scopeFieldId={props.scopeFieldId} board={props.board}\n value={c.scope} onChange={c.setScope} counts={c.scopeCounts}\n testIdPrefix={testIdPrefix}\n />\n <TableFilter.Layout>\n <TableFilter.Main>\n <GridMain\n c={c}\n getRowId={props.getRowId}\n renderCard={props.renderCard}\n renderListRow={props.renderListRow}\n listGroup={props.listGroup}\n board={props.board}\n dataTestId={dataTestId}\n testIdPrefix={testIdPrefix}\n emptyState={body}\n />\n <DataViewsPagination c={c} testIdPrefix={testIdPrefix} />\n </TableFilter.Main>\n {inlineFilters ? null : <GridFilterPanel {...filterProps} />}\n </TableFilter.Layout>\n {useModal && <FilterDialog open={c.filterOpen} onClose={() => c.setFilterOpen(false)} {...filterProps} />}\n </Stack>\n </TableFilter>\n );\n}\n\nexport function GridShell<T extends Record<string, unknown>>(props: GridShellProps<T>): React.JSX.Element {\n const {\n c,\n fields,\n rangeFields,\n testIdPrefix,\n renderCard,\n renderListRow,\n board,\n defaultLayout,\n ignoreStoredLayout,\n inlineFilters = false,\n alwaysShowSearch = false,\n } = props;\n const filters = useGridShellFilters({\n c,\n inlineFilters,\n fields,\n rangeFields,\n testIdPrefix,\n alwaysShowSearch,\n hasExport: props.exportConfig !== undefined,\n });\n return (\n <DataViewsLayoutProvider\n canUseCards={Boolean(renderCard)}\n canUseList={Boolean(renderListRow)}\n // The board reuses the entity's card, so it needs BOTH — a `board` with no\n // `renderCard` offers no board rather than throwing.\n canUseBoard={Boolean(board && renderCard)}\n defaultLayout={defaultLayout}\n ignoreStoredLayout={ignoreStoredLayout}\n viewLayout={c.state.layout}\n >\n <LayoutStateSync c={c} />\n <ShellStack props={props} filters={filters} />\n </DataViewsLayoutProvider>\n );\n}\n"],"mappings":"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","names":["default"]}
@@ -1,27 +0,0 @@
1
- // src/components/data-display/DataViews/data-views-selection.ts
2
- import { useMemo, useState } from "react";
3
- function useSelection(matched, getRowId) {
4
- const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
5
- const selectedRows = useMemo(
6
- () => matched.filter((row) => selectedIds.has(getRowId(row))),
7
- [matched, selectedIds, getRowId]
8
- );
9
- return {
10
- selectedIds,
11
- setSelectedIds,
12
- toggleId: (id) => setSelectedIds((prev) => {
13
- const next = new Set(prev);
14
- if (next.has(id)) next.delete(id);
15
- else next.add(id);
16
- return next;
17
- }),
18
- selectedRows,
19
- clearSelection: () => setSelectedIds(/* @__PURE__ */ new Set()),
20
- selectAll: () => setSelectedIds(new Set(matched.map((row) => getRowId(row))))
21
- };
22
- }
23
-
24
- export {
25
- useSelection
26
- };
27
- //# sourceMappingURL=chunk-WTOTWP6A.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-selection.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\n\n/** The multi-select model, identical in every layout (table, cards, board). */\ninterface DataViewsSelection<T> {\n selectedIds: Set<string | number>;\n setSelectedIds: (ids: Set<string | number>) => void;\n /** Add/remove ONE id — what a card's or board card's checkbox calls. */\n toggleId: (id: string | number) => void;\n /** The selected rows, narrowed to what is currently rendered. */\n selectedRows: T[];\n clearSelection: () => void;\n selectAll: () => void;\n}\n\n/**\n * Owns the DataViews selection. ONE set of ids across every layout, so switching\n * from the board to the table (or to the cards) keeps exactly the same rows\n * selected and offers exactly the same bulk actions.\n *\n * Extracted from {@link useDataViewsState} for that hook's size budget, and\n * because `toggleId` needs a functional update: two cards toggled in the same\n * tick would otherwise both read the pre-render set and the second would drop\n * the first's change.\n */\nexport function useSelection<T>(\n matched: T[],\n getRowId: (row: T) => string | number,\n): DataViewsSelection<T> {\n const [selectedIds, setSelectedIds] = useState<Set<string | number>>(new Set());\n const selectedRows = useMemo(\n () => matched.filter((row) => selectedIds.has(getRowId(row))),\n [matched, selectedIds, getRowId],\n );\n return {\n selectedIds,\n setSelectedIds,\n toggleId: (id) =>\n setSelectedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n }),\n selectedRows,\n clearSelection: () => setSelectedIds(new Set()),\n selectAll: () => setSelectedIds(new Set(matched.map((row) => getRowId(row)))),\n };\n}\n"],"mappings":";AAEA,SAAS,SAAS,gBAAgB;AAwB3B,SAAS,aACd,SACA,UACuB;AACvB,QAAM,CAAC,aAAa,cAAc,IAAI,SAA+B,oBAAI,IAAI,CAAC;AAC9E,QAAM,eAAe;AAAA,IACnB,MAAM,QAAQ,OAAO,CAAC,QAAQ,YAAY,IAAI,SAAS,GAAG,CAAC,CAAC;AAAA,IAC5D,CAAC,SAAS,aAAa,QAAQ;AAAA,EACjC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,CAAC,OACT,eAAe,CAAC,SAAS;AACvB,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,UAAI,KAAK,IAAI,EAAE,EAAG,MAAK,OAAO,EAAE;AAAA,UAC3B,MAAK,IAAI,EAAE;AAChB,aAAO;AAAA,IACT,CAAC;AAAA,IACH;AAAA,IACA,gBAAgB,MAAM,eAAe,oBAAI,IAAI,CAAC;AAAA,IAC9C,WAAW,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC,QAAQ,SAAS,GAAG,CAAC,CAAC,CAAC;AAAA,EAC9E;AACF;","names":[]}