@12-apps/ui 6.13.2 → 6.15.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.
- package/components-catalog.md +8 -1
- package/dist/_internal/components/data-display/AsyncStateContainer/AsyncStateContainer.js +4 -4
- package/dist/_internal/components/data-display/Badge/Badge.js +2 -2
- package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +5 -5
- package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +5 -5
- package/dist/_internal/components/data-display/Carousel/Carousel.js +3 -3
- package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
- package/dist/_internal/components/data-display/Chart/SpecChart.js +8 -8
- package/dist/_internal/components/data-display/Chart/chart-context.js +2 -2
- package/dist/_internal/components/data-display/Chart/chart-renderers.js +3 -3
- package/dist/_internal/components/data-display/Chart/chart-spec.js +2 -2
- package/dist/_internal/components/data-display/DataGrid/DataGrid.js +3 -3
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +44 -42
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +60 -58
- package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +5 -5
- package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +4 -4
- package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +3 -3
- package/dist/_internal/components/data-display/DataViews/base-list-card.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +13 -13
- package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +1 -1
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +20 -20
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +39 -37
- package/dist/_internal/components/data-display/DataViews/data-views-header-row.js +12 -0
- package/dist/_internal/components/data-display/DataViews/data-views-header-row.js.map +1 -0
- package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +20 -20
- package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-selection-extra.js +8 -0
- package/dist/_internal/components/data-display/DataViews/data-views-selection-extra.js.map +1 -0
- package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +9 -9
- package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +6 -6
- package/dist/_internal/components/data-display/DataViews/list-card-rails.js +2 -2
- package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +4 -4
- package/dist/_internal/components/data-display/DataViews/use-saved-views-controller.js +2 -2
- package/dist/_internal/components/data-display/HoverCard/HoverCard.js +2 -2
- package/dist/_internal/components/data-display/LazyImage/LazyImage.js +3 -3
- package/dist/_internal/components/data-display/Lightbox/Lightbox.js +6 -6
- package/dist/_internal/components/data-display/LoadingState/LoadingState.js +3 -3
- package/dist/_internal/components/data-display/MapPreview/MapDecorations.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapLayers.js +3 -3
- package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.js +11 -11
- package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
- package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
- package/dist/_internal/components/data-display/StatCard/StatCard.js +3 -3
- package/dist/_internal/components/data-display/Table/Table.js +2 -2
- package/dist/_internal/components/data-display/index.js +52 -52
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmAction.js +2 -2
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +3 -3
- package/dist/_internal/components/feedback/ConfirmAction/with-confirmation.js +2 -2
- package/dist/_internal/components/feedback/StackedModal/StackedModal.js +6 -6
- package/dist/_internal/components/feedback/TutorialOverlay/TutorialOverlay.js +2 -2
- package/dist/_internal/components/feedback/index.js +15 -15
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.hooks.js +4 -4
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +7 -7
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +2 -2
- package/dist/_internal/components/form/Autocomplete/Autocomplete.js +2 -2
- package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +4 -4
- package/dist/_internal/components/form/CategorySelect/CategoryPanelList.js +3 -3
- package/dist/_internal/components/form/CategorySelect/CategoryRows.js +2 -2
- package/dist/_internal/components/form/CategorySelect/CategorySelect.js +9 -9
- package/dist/_internal/components/form/CodeEditor/CodeEditor.js +3 -3
- package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +3 -3
- package/dist/_internal/components/form/HeaderActions/HeaderActions.js +11 -0
- package/dist/_internal/components/form/HeaderActions/HeaderActions.js.map +1 -0
- package/dist/_internal/components/form/HeaderActions/HeaderActions.types.js +1 -0
- package/dist/_internal/components/form/HeaderActions/HeaderActions.types.js.map +1 -0
- package/dist/_internal/components/form/Label/Label.js +2 -2
- package/dist/_internal/components/form/PhoneInput/PhoneInput.hooks.js +2 -2
- package/dist/_internal/components/form/PhoneInput/PhoneInput.js +3 -3
- package/dist/_internal/components/form/index.js +38 -38
- package/dist/_internal/components/form/total-form/Fields/CategoryField.js +10 -10
- package/dist/_internal/components/form/total-form/Fields/index.js +13 -13
- package/dist/_internal/components/index.js +143 -141
- package/dist/_internal/components/layout/ContentToolbar/ContentToolbar.js +1 -1
- package/dist/_internal/components/layout/Dashboard/Dashboard.js +4 -2
- package/dist/_internal/components/layout/Dashboard/DashboardParts.js +5 -1
- package/dist/_internal/components/layout/ScrollArea/ScrollArea.js +3 -3
- package/dist/_internal/components/layout/Skeleton/Skeleton.js +2 -2
- package/dist/_internal/components/layout/index.js +22 -20
- package/dist/_internal/components/navigation/CommandPalette/CommandPalette.js +2 -2
- package/dist/_internal/components/navigation/NavigationMenu/NavigationMegaSection.js +3 -3
- package/dist/_internal/components/navigation/NavigationMenu/NavigationMenu.js +5 -5
- package/dist/_internal/components/navigation/NavigationMenu/NavigationMenuItem.js +2 -2
- package/dist/_internal/components/navigation/NavigationMenu/NavigationStandardBody.js +3 -3
- package/dist/_internal/components/navigation/index.js +11 -11
- package/dist/_internal/components/typography/index.js +3 -3
- package/dist/_internal/components/utility/InstallPrompt/InstallPrompt.js +2 -2
- package/dist/_internal/components/utility/index.js +7 -7
- package/dist/_internal/en-US.data-display.js +2 -2
- package/dist/charts.js +17 -17
- package/dist/{chunk-WQSL6MCA.js → chunk-23FCBIUN.js} +4 -4
- package/dist/{chunk-6PFBYCBU.js → chunk-24LW52EU.js} +2 -2
- package/dist/{chunk-HR7YTBR7.js → chunk-3AOOI2NR.js} +4 -4
- package/dist/{chunk-EIGELK2H.js → chunk-3P4THDBM.js} +4 -4
- package/dist/{chunk-SJIBPRPB.js → chunk-3T2I6BYA.js} +4 -4
- package/dist/{chunk-5ZZPQ3MT.js → chunk-434EDUHY.js} +5 -5
- package/dist/{chunk-4ETQRBZC.js → chunk-46UPILLK.js} +4 -4
- package/dist/{chunk-CKZFYGBY.js → chunk-47DCYF4G.js} +6 -6
- package/dist/{chunk-B2324WXJ.js → chunk-4KNJQFDJ.js} +4 -4
- package/dist/{chunk-V44U7H4M.js → chunk-5KZESOK6.js} +8 -8
- package/dist/{chunk-JE6RZ5L6.js → chunk-5ZOJLYD2.js} +4 -4
- package/dist/{chunk-AVGTTWTE.js → chunk-65DLYC4S.js} +4 -4
- package/dist/{chunk-HRJ27X5B.js → chunk-6HNEEJES.js} +7 -7
- package/dist/{chunk-4VNUOSTQ.js → chunk-6YFMGNSA.js} +4 -4
- package/dist/{chunk-R7MX5KPJ.js → chunk-6YLAVHV4.js} +4 -4
- package/dist/{chunk-56SMIHWE.js → chunk-747HBFGH.js} +4 -4
- package/dist/{chunk-A43SJQYE.js → chunk-74LYLKO2.js} +4 -2
- package/dist/chunk-74LYLKO2.js.map +1 -0
- package/dist/{chunk-RXSGHPCR.js → chunk-7FOOLP5H.js} +4 -4
- package/dist/{chunk-EICVL6GS.js → chunk-7HPPUO2A.js} +2 -2
- package/dist/chunk-A4YWFX5C.js +39 -0
- package/dist/chunk-A4YWFX5C.js.map +1 -0
- package/dist/{chunk-VJFH2AXT.js → chunk-ARI5ZU75.js} +7 -7
- package/dist/{chunk-7QVYJQN4.js → chunk-B5LNUTGZ.js} +2 -2
- package/dist/{chunk-75KRWRJA.js → chunk-BQYIJOKS.js} +6 -6
- package/dist/{chunk-72NOM3O2.js → chunk-C34GFGA5.js} +2 -2
- package/dist/{chunk-4KSOSI3U.js → chunk-CRHQN42I.js} +5 -5
- package/dist/{chunk-LQR2IVSL.js → chunk-DWUMMMLR.js} +4 -4
- package/dist/{chunk-SHDIZSN5.js → chunk-EGRFMPGD.js} +6 -6
- package/dist/{chunk-XFUNJYFT.js → chunk-EPNUVSNK.js} +7 -7
- package/dist/{chunk-FLSSV4TH.js → chunk-EWGVRRUF.js} +23 -2
- package/dist/chunk-EWGVRRUF.js.map +1 -0
- package/dist/{chunk-L6KEVPXN.js → chunk-FH4VARZ7.js} +7 -7
- package/dist/{chunk-N6JGYVRY.js → chunk-GDUIT5I6.js} +2 -2
- package/dist/{chunk-R6SBP5M5.js → chunk-GOWBYHYW.js} +4 -4
- package/dist/{chunk-HDNK7BAX.js → chunk-GT7C6TSM.js} +3 -3
- package/dist/{chunk-X5MPHXG5.js → chunk-HEG7JIBM.js} +4 -4
- package/dist/{chunk-RDYBS45D.js → chunk-HIZCBYEP.js} +7 -7
- package/dist/{chunk-AZUFGKMQ.js → chunk-HJOABXKN.js} +4 -4
- package/dist/{chunk-ZOUWHGV3.js → chunk-HOJL2GKW.js} +7 -7
- package/dist/{chunk-AZSFIQIA.js → chunk-I2S2GHEG.js} +12 -12
- package/dist/{chunk-RRO2EOJB.js → chunk-JB67KPGM.js} +4 -4
- package/dist/{chunk-MNJVOU7T.js → chunk-K2T2CQSZ.js} +4 -4
- package/dist/chunk-KX75HM5U.js +20 -0
- package/dist/chunk-KX75HM5U.js.map +1 -0
- package/dist/{chunk-AWTERXCW.js → chunk-LDMXHDZ5.js} +4 -2
- package/dist/chunk-LDMXHDZ5.js.map +1 -0
- package/dist/{chunk-IIUB4IOH.js → chunk-LKF5KQ2Q.js} +4 -4
- package/dist/{chunk-A2WJMZX5.js → chunk-LNQ6QMKG.js} +2 -2
- package/dist/{chunk-ECIGNYSI.js → chunk-LR2ECQSZ.js} +2 -2
- package/dist/{chunk-SFAP5EH5.js → chunk-LUMF63BM.js} +4 -4
- package/dist/{chunk-CZPU5TW3.js → chunk-LYSSO6WC.js} +4 -4
- package/dist/{chunk-XSKVBGCZ.js → chunk-MHJ52VJE.js} +5 -5
- package/dist/{chunk-WXBBWSNU.js → chunk-MJOXIENM.js} +3 -2
- package/dist/chunk-MJOXIENM.js.map +1 -0
- package/dist/chunk-N4JEQJBL.js +93 -0
- package/dist/chunk-N4JEQJBL.js.map +1 -0
- package/dist/{chunk-HNDUCGM3.js → chunk-NI2ISQZI.js} +3 -3
- package/dist/chunk-NI2ISQZI.js.map +1 -0
- package/dist/{chunk-Q4ITS2EP.js → chunk-NJS4WCHA.js} +21 -45
- package/dist/chunk-NJS4WCHA.js.map +1 -0
- package/dist/{chunk-RUO4D4N6.js → chunk-NKCKIGRL.js} +6 -6
- package/dist/{chunk-IRDGC7FK.js → chunk-NVOQLMYF.js} +4 -4
- package/dist/{chunk-AGYGNNOM.js → chunk-PQECNGDE.js} +2 -2
- package/dist/{chunk-LPYB4Y7C.js → chunk-PRAGFBHW.js} +4 -4
- package/dist/{chunk-7DNQHMDO.js → chunk-PXH24VIP.js} +4 -4
- package/dist/{chunk-AP3PVR3T.js → chunk-Q6KXTTC4.js} +2 -2
- package/dist/{chunk-CDJPDZCA.js → chunk-QISJKBCM.js} +2 -2
- package/dist/{chunk-WBKWIFXA.js → chunk-QYNCPS5W.js} +6 -6
- package/dist/{chunk-XEE7PLDR.js → chunk-QZBUGUOY.js} +6 -6
- package/dist/{chunk-BLT5ZBVL.js → chunk-RRX6ZTNX.js} +2 -2
- package/dist/{chunk-QQE2PVLO.js → chunk-RXYSP56G.js} +6 -6
- package/dist/{chunk-BVGR7OYA.js → chunk-SE4Z3P6D.js} +4 -4
- package/dist/chunk-SIZOJNB2.js +1 -0
- package/dist/chunk-SIZOJNB2.js.map +1 -0
- package/dist/{chunk-2WWKBD4D.js → chunk-TSPHRZ4U.js} +5 -1
- package/dist/chunk-TSPHRZ4U.js.map +1 -0
- package/dist/{chunk-BGYLL467.js → chunk-TXHJX2NG.js} +4 -4
- package/dist/{chunk-KEDI6IRA.js → chunk-UN5D73A4.js} +2 -2
- package/dist/{chunk-PKJKA4CU.js → chunk-UPR7F3ML.js} +2 -2
- package/dist/{chunk-4ZEU22L2.js → chunk-VLNM4BTH.js} +4 -4
- package/dist/{chunk-2SWQ6HIK.js → chunk-W3FAKT3D.js} +4 -4
- package/dist/{chunk-UHXNEXOC.js → chunk-WWNXJMBX.js} +2 -2
- package/dist/{chunk-V5P5Q6HM.js → chunk-X24P3ZYW.js} +10 -10
- package/dist/{chunk-PMS3H3OO.js → chunk-XSJWN3WH.js} +10 -10
- package/dist/{chunk-OGGHD64H.js → chunk-Y5UCOBQN.js} +4 -4
- package/dist/{chunk-O6J4CKS5.js → chunk-YROTCW42.js} +2 -2
- package/dist/{chunk-2A3OMYCB.js → chunk-YRUCIKPO.js} +4 -4
- package/dist/{chunk-PDGAFQ6Z.js → chunk-YVX7GGS4.js} +3 -3
- package/dist/{chunk-G5ZVD5IJ.js → chunk-ZDWU52DJ.js} +2 -2
- package/dist/{chunk-2UCJJACD.js → chunk-ZLNKBKUB.js} +11 -11
- package/dist/{chunk-RRYQG5Y6.js → chunk-ZPIFVTJA.js} +6 -6
- package/dist/chunk-ZPIFVTJA.js.map +1 -0
- package/dist/data-display/AsyncStateContainer.js +4 -4
- package/dist/data-display/Badge.js +2 -2
- package/dist/data-display/CardKit.js +11 -11
- package/dist/data-display/Carousel.js +3 -3
- package/dist/data-display/Chart.js +17 -17
- package/dist/data-display/DataGrid.js +3 -3
- package/dist/data-display/DataViews.js +77 -75
- package/dist/data-display/HoverCard.js +2 -2
- package/dist/data-display/LazyImage.js +3 -3
- package/dist/data-display/Lightbox.js +6 -6
- package/dist/data-display/LoadingState.js +3 -3
- package/dist/data-display/MapPreview.js +11 -11
- package/dist/data-display/StatCard.js +3 -3
- package/dist/data-display/Table.js +2 -2
- package/dist/en-US.js +8 -8
- package/dist/feedback/ConfirmAction.js +7 -7
- package/dist/feedback/StackedModal.js +6 -6
- package/dist/feedback/TutorialOverlay.js +2 -2
- package/dist/form/AddressAutocomplete.js +7 -7
- package/dist/form/Autocomplete.js +2 -2
- package/dist/form/CategorySelect.js +9 -9
- package/dist/form/CodeEditor.js +3 -3
- package/dist/form/DateRangePicker.js +3 -3
- package/dist/form/HeaderActions.js +11 -0
- package/dist/form/HeaderActions.js.map +1 -0
- package/dist/form/Label.js +2 -2
- package/dist/form/PhoneInput.js +3 -3
- package/dist/form/total-form.js +16 -16
- package/dist/layout/ContentToolbar.js +7 -7
- package/dist/layout/Dashboard.js +4 -2
- package/dist/layout/ScrollArea.js +3 -3
- package/dist/layout/Skeleton.js +2 -2
- package/dist/locales.js +11 -11
- package/dist/navigation/CommandPalette.js +2 -2
- package/dist/navigation/NavigationMenu.js +5 -5
- package/dist/pt-BR.js +4 -4
- package/dist/types/components/data-display/DataViews/DataViewsGrid.d.ts +12 -0
- package/dist/types/components/data-display/DataViews/DataViewsGrid.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/DataViewsTableBase.d.ts +3 -0
- package/dist/types/components/data-display/DataViews/DataViewsTableBase.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts +3 -0
- package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-header-row.d.ts +18 -0
- package/dist/types/components/data-display/DataViews/data-views-header-row.d.ts.map +1 -0
- package/dist/types/components/data-display/DataViews/data-views-selection-extra.d.ts +50 -0
- package/dist/types/components/data-display/DataViews/data-views-selection-extra.d.ts.map +1 -0
- package/dist/types/components/data-display/DataViews/data-views-shell-toolbar.d.ts +3 -1
- package/dist/types/components/data-display/DataViews/data-views-shell-toolbar.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts +2 -0
- package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/index.d.ts +1 -0
- package/dist/types/components/data-display/DataViews/index.d.ts.map +1 -1
- package/dist/types/components/form/HeaderActions/HeaderActions.d.ts +48 -0
- package/dist/types/components/form/HeaderActions/HeaderActions.d.ts.map +1 -0
- package/dist/types/components/form/HeaderActions/HeaderActions.types.d.ts +62 -0
- package/dist/types/components/form/HeaderActions/HeaderActions.types.d.ts.map +1 -0
- package/dist/types/components/form/HeaderActions/index.d.ts +3 -0
- package/dist/types/components/form/HeaderActions/index.d.ts.map +1 -0
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +15 -0
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.d.ts +4 -0
- package/dist/types/components/layout/Dashboard/Dashboard.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts +10 -0
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts +22 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/index.d.ts +1 -1
- package/dist/types/components/layout/Dashboard/index.d.ts.map +1 -1
- package/dist/utility/InstallPrompt.js +2 -2
- package/package.json +5 -1
- package/src/components/data-display/DataViews/DataViewsGrid.tsx +12 -0
- package/src/components/data-display/DataViews/DataViewsTableBase.tsx +3 -0
- package/src/components/data-display/DataViews/data-views-grid-parts.tsx +5 -50
- package/src/components/data-display/DataViews/data-views-header-row.tsx +52 -0
- package/src/components/data-display/DataViews/data-views-selection-extra.ts +67 -0
- package/src/components/data-display/DataViews/data-views-shell-toolbar.tsx +4 -0
- package/src/components/data-display/DataViews/data-views-toolbar.tsx +3 -0
- package/src/components/data-display/DataViews/index.ts +1 -0
- package/src/components/form/HeaderActions/HeaderActions.md +72 -0
- package/src/components/form/HeaderActions/HeaderActions.tsx +134 -0
- package/src/components/form/HeaderActions/HeaderActions.types.ts +64 -0
- package/src/components/form/HeaderActions/index.ts +2 -0
- package/src/components/layout/ContentToolbar/ContentToolbar.md +10 -3
- package/src/components/layout/ContentToolbar/ContentToolbar.tsx +5 -0
- package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +15 -0
- package/src/components/layout/Dashboard/Dashboard.md +9 -2
- package/src/components/layout/Dashboard/Dashboard.tsx +2 -0
- package/src/components/layout/Dashboard/Dashboard.types.ts +12 -0
- package/src/components/layout/Dashboard/DashboardParts.tsx +36 -0
- package/src/components/layout/Dashboard/index.ts +1 -0
- package/dist/chunk-2WWKBD4D.js.map +0 -1
- package/dist/chunk-A43SJQYE.js.map +0 -1
- package/dist/chunk-AWTERXCW.js.map +0 -1
- package/dist/chunk-FLSSV4TH.js.map +0 -1
- package/dist/chunk-HNDUCGM3.js.map +0 -1
- package/dist/chunk-Q4ITS2EP.js.map +0 -1
- package/dist/chunk-RRYQG5Y6.js.map +0 -1
- package/dist/chunk-WXBBWSNU.js.map +0 -1
- /package/dist/{chunk-WQSL6MCA.js.map → chunk-23FCBIUN.js.map} +0 -0
- /package/dist/{chunk-6PFBYCBU.js.map → chunk-24LW52EU.js.map} +0 -0
- /package/dist/{chunk-HR7YTBR7.js.map → chunk-3AOOI2NR.js.map} +0 -0
- /package/dist/{chunk-EIGELK2H.js.map → chunk-3P4THDBM.js.map} +0 -0
- /package/dist/{chunk-SJIBPRPB.js.map → chunk-3T2I6BYA.js.map} +0 -0
- /package/dist/{chunk-5ZZPQ3MT.js.map → chunk-434EDUHY.js.map} +0 -0
- /package/dist/{chunk-4ETQRBZC.js.map → chunk-46UPILLK.js.map} +0 -0
- /package/dist/{chunk-CKZFYGBY.js.map → chunk-47DCYF4G.js.map} +0 -0
- /package/dist/{chunk-B2324WXJ.js.map → chunk-4KNJQFDJ.js.map} +0 -0
- /package/dist/{chunk-V44U7H4M.js.map → chunk-5KZESOK6.js.map} +0 -0
- /package/dist/{chunk-JE6RZ5L6.js.map → chunk-5ZOJLYD2.js.map} +0 -0
- /package/dist/{chunk-AVGTTWTE.js.map → chunk-65DLYC4S.js.map} +0 -0
- /package/dist/{chunk-HRJ27X5B.js.map → chunk-6HNEEJES.js.map} +0 -0
- /package/dist/{chunk-4VNUOSTQ.js.map → chunk-6YFMGNSA.js.map} +0 -0
- /package/dist/{chunk-R7MX5KPJ.js.map → chunk-6YLAVHV4.js.map} +0 -0
- /package/dist/{chunk-56SMIHWE.js.map → chunk-747HBFGH.js.map} +0 -0
- /package/dist/{chunk-RXSGHPCR.js.map → chunk-7FOOLP5H.js.map} +0 -0
- /package/dist/{chunk-EICVL6GS.js.map → chunk-7HPPUO2A.js.map} +0 -0
- /package/dist/{chunk-VJFH2AXT.js.map → chunk-ARI5ZU75.js.map} +0 -0
- /package/dist/{chunk-7QVYJQN4.js.map → chunk-B5LNUTGZ.js.map} +0 -0
- /package/dist/{chunk-75KRWRJA.js.map → chunk-BQYIJOKS.js.map} +0 -0
- /package/dist/{chunk-72NOM3O2.js.map → chunk-C34GFGA5.js.map} +0 -0
- /package/dist/{chunk-4KSOSI3U.js.map → chunk-CRHQN42I.js.map} +0 -0
- /package/dist/{chunk-LQR2IVSL.js.map → chunk-DWUMMMLR.js.map} +0 -0
- /package/dist/{chunk-SHDIZSN5.js.map → chunk-EGRFMPGD.js.map} +0 -0
- /package/dist/{chunk-XFUNJYFT.js.map → chunk-EPNUVSNK.js.map} +0 -0
- /package/dist/{chunk-L6KEVPXN.js.map → chunk-FH4VARZ7.js.map} +0 -0
- /package/dist/{chunk-N6JGYVRY.js.map → chunk-GDUIT5I6.js.map} +0 -0
- /package/dist/{chunk-R6SBP5M5.js.map → chunk-GOWBYHYW.js.map} +0 -0
- /package/dist/{chunk-HDNK7BAX.js.map → chunk-GT7C6TSM.js.map} +0 -0
- /package/dist/{chunk-X5MPHXG5.js.map → chunk-HEG7JIBM.js.map} +0 -0
- /package/dist/{chunk-RDYBS45D.js.map → chunk-HIZCBYEP.js.map} +0 -0
- /package/dist/{chunk-AZUFGKMQ.js.map → chunk-HJOABXKN.js.map} +0 -0
- /package/dist/{chunk-ZOUWHGV3.js.map → chunk-HOJL2GKW.js.map} +0 -0
- /package/dist/{chunk-AZSFIQIA.js.map → chunk-I2S2GHEG.js.map} +0 -0
- /package/dist/{chunk-RRO2EOJB.js.map → chunk-JB67KPGM.js.map} +0 -0
- /package/dist/{chunk-MNJVOU7T.js.map → chunk-K2T2CQSZ.js.map} +0 -0
- /package/dist/{chunk-IIUB4IOH.js.map → chunk-LKF5KQ2Q.js.map} +0 -0
- /package/dist/{chunk-A2WJMZX5.js.map → chunk-LNQ6QMKG.js.map} +0 -0
- /package/dist/{chunk-ECIGNYSI.js.map → chunk-LR2ECQSZ.js.map} +0 -0
- /package/dist/{chunk-SFAP5EH5.js.map → chunk-LUMF63BM.js.map} +0 -0
- /package/dist/{chunk-CZPU5TW3.js.map → chunk-LYSSO6WC.js.map} +0 -0
- /package/dist/{chunk-XSKVBGCZ.js.map → chunk-MHJ52VJE.js.map} +0 -0
- /package/dist/{chunk-RUO4D4N6.js.map → chunk-NKCKIGRL.js.map} +0 -0
- /package/dist/{chunk-IRDGC7FK.js.map → chunk-NVOQLMYF.js.map} +0 -0
- /package/dist/{chunk-AGYGNNOM.js.map → chunk-PQECNGDE.js.map} +0 -0
- /package/dist/{chunk-LPYB4Y7C.js.map → chunk-PRAGFBHW.js.map} +0 -0
- /package/dist/{chunk-7DNQHMDO.js.map → chunk-PXH24VIP.js.map} +0 -0
- /package/dist/{chunk-AP3PVR3T.js.map → chunk-Q6KXTTC4.js.map} +0 -0
- /package/dist/{chunk-CDJPDZCA.js.map → chunk-QISJKBCM.js.map} +0 -0
- /package/dist/{chunk-WBKWIFXA.js.map → chunk-QYNCPS5W.js.map} +0 -0
- /package/dist/{chunk-XEE7PLDR.js.map → chunk-QZBUGUOY.js.map} +0 -0
- /package/dist/{chunk-BLT5ZBVL.js.map → chunk-RRX6ZTNX.js.map} +0 -0
- /package/dist/{chunk-QQE2PVLO.js.map → chunk-RXYSP56G.js.map} +0 -0
- /package/dist/{chunk-BVGR7OYA.js.map → chunk-SE4Z3P6D.js.map} +0 -0
- /package/dist/{chunk-BGYLL467.js.map → chunk-TXHJX2NG.js.map} +0 -0
- /package/dist/{chunk-KEDI6IRA.js.map → chunk-UN5D73A4.js.map} +0 -0
- /package/dist/{chunk-PKJKA4CU.js.map → chunk-UPR7F3ML.js.map} +0 -0
- /package/dist/{chunk-4ZEU22L2.js.map → chunk-VLNM4BTH.js.map} +0 -0
- /package/dist/{chunk-2SWQ6HIK.js.map → chunk-W3FAKT3D.js.map} +0 -0
- /package/dist/{chunk-UHXNEXOC.js.map → chunk-WWNXJMBX.js.map} +0 -0
- /package/dist/{chunk-V5P5Q6HM.js.map → chunk-X24P3ZYW.js.map} +0 -0
- /package/dist/{chunk-PMS3H3OO.js.map → chunk-XSJWN3WH.js.map} +0 -0
- /package/dist/{chunk-OGGHD64H.js.map → chunk-Y5UCOBQN.js.map} +0 -0
- /package/dist/{chunk-O6J4CKS5.js.map → chunk-YROTCW42.js.map} +0 -0
- /package/dist/{chunk-2A3OMYCB.js.map → chunk-YRUCIKPO.js.map} +0 -0
- /package/dist/{chunk-PDGAFQ6Z.js.map → chunk-YVX7GGS4.js.map} +0 -0
- /package/dist/{chunk-G5ZVD5IJ.js.map → chunk-ZDWU52DJ.js.map} +0 -0
- /package/dist/{chunk-2UCJJACD.js.map → chunk-ZLNKBKUB.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/layout/Dashboard/Dashboard.tsx"],"sourcesContent":["'use client';\n\nimport ExpandLessIcon from '@mui/icons-material/ExpandLess';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport FilterIcon from '@mui/icons-material/FilterListRounded';\nimport NavigateNextIcon from '@mui/icons-material/NavigateNext';\nimport Box from '@mui/material/Box/index.js';\nimport MuiBreadcrumbs from '@mui/material/Breadcrumbs/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport Collapse from '@mui/material/Collapse/index.js';\nimport MuiLink from '@mui/material/Link/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { styled } from '@mui/material/styles/index.js';\nimport React, { useMemo, useState } from 'react';\n\nimport { DashboardContext, useDashboardContext } from './DashboardContext';\nimport {\n DashboardAction,\n DashboardExport,\n DashboardFilterToggle,\n DashboardInfo,\n DashboardSettings,\n DashboardSpacer,\n} from './DashboardParts';\nimport type {\n DashboardBodyProps,\n DashboardBreadcrumbProps,\n DashboardFiltersProps,\n DashboardHeaderProps,\n DashboardMoreFiltersProps,\n DashboardProps,\n} from './Dashboard.types';\n\n/**\n * Ordered slot keys. The root reorders composed children into this sequence so\n * authoring order in JSX never matters — a `<Dashboard.Filters>` placed above\n * a `<Dashboard.Header>` still renders below it.\n */\nconst SLOT_ORDER = ['breadcrumb', 'header', 'filters', 'body'] as const;\n/** A slot a component can occupy in the canonical Dashboard order. */\nexport type DashboardSlot = (typeof SLOT_ORDER)[number];\n\n/** Marker attached to each sub-component so the root can rank it by slot. */\ntype SlottedComponent = { dashboardSlot?: DashboardSlot };\n\n/**\n * Tag a component with the Dashboard slot it occupies so the root ranks it in\n * canonical order. The root inspects only its DIRECT children's `type`, so a\n * page that wraps a `<Dashboard.Header>` (or any part) in its own component MUST\n * mark that wrapper — otherwise it counts as an unrecognised child and sinks\n * below the body. Returns the component for convenient inline use.\n *\n * @example\n * ```tsx\n * function ProductsHeader(props) {\n * return <Dashboard.Header title=\"Products\">{/* … *\\/}</Dashboard.Header>;\n * }\n * markDashboardSlot(ProductsHeader, 'header');\n * ```\n */\nexport function markDashboardSlot<T>(component: T, slot: DashboardSlot): T {\n (component as SlottedComponent).dashboardSlot = slot;\n return component;\n}\n\nconst Root = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(2),\n width: '100%',\n}));\n\nfunction slotRank(node: React.ReactNode): number {\n if (React.isValidElement(node)) {\n const slot = (node.type as SlottedComponent).dashboardSlot;\n if (slot) {\n const rank = SLOT_ORDER.indexOf(slot);\n if (rank >= 0) {\n return rank;\n }\n }\n }\n // Unknown / arbitrary children keep their relative position after the\n // recognised slots.\n return SLOT_ORDER.length;\n}\n\n/**\n * Composable page shell. `<Dashboard>` provides shared state through context\n * and renders whichever sub-components you compose — nothing is implied. Drop\n * in only the parts you need; omit `<Dashboard.Filters>` and there is simply no\n * filter UI.\n *\n * @example\n * ```tsx\n * <Dashboard activeFilterCount={2}>\n * <Dashboard.Breadcrumb items={[{ label: 'Admin', href: '/admin' }, { label: 'Products' }]} />\n * <Dashboard.Header title=\"Products\">\n * <Dashboard.Info>What this page does…</Dashboard.Info>\n * <Dashboard.FilterToggle />\n * <Dashboard.Settings>In development</Dashboard.Settings>\n * <Dashboard.Spacer />\n * <Dashboard.Export onExport={handleExport} />\n * <Dashboard.Action><Button variant=\"contained\">New product</Button></Dashboard.Action>\n * </Dashboard.Header>\n * <Dashboard.Filters>{/* search + pills *\\/}</Dashboard.Filters>\n * <Dashboard.Body>{table}</Dashboard.Body>\n * </Dashboard>\n * ```\n */\nexport const Dashboard = ({\n children,\n defaultFiltersVisible = true,\n activeFilterCount = 0,\n testIdPrefix = 'dashboard',\n className,\n}: DashboardProps): React.JSX.Element => {\n const [filtersVisible, setFiltersVisible] = useState(defaultFiltersVisible);\n const [moreFiltersOpen, setMoreFiltersOpen] = useState(false);\n\n const value = useMemo(\n () => ({\n filtersVisible,\n toggleFilters: () => setFiltersVisible((v) => !v),\n moreFiltersOpen,\n toggleMoreFilters: () => setMoreFiltersOpen((v) => !v),\n activeFilterCount,\n testIdPrefix,\n }),\n [filtersVisible, moreFiltersOpen, activeFilterCount, testIdPrefix],\n );\n\n // Stable sort recognised slots into canonical order, preserving the original\n // order of anything unrecognised.\n const ordered = useMemo(() => {\n const arr = React.Children.toArray(children);\n return arr\n .map((node, index) => ({ node, index, rank: slotRank(node) }))\n .sort((a, b) => (a.rank === b.rank ? a.index - b.index : a.rank - b.rank))\n .map((entry) => entry.node);\n }, [children]);\n\n return (\n <DashboardContext.Provider value={value}>\n <Root className={className} data-testid={testIdPrefix}>\n {ordered}\n </Root>\n </DashboardContext.Provider>\n );\n};\n\nDashboard.displayName = 'Dashboard';\n\n/* -------------------------------------------------------------------------- */\n/* Breadcrumb */\n/* -------------------------------------------------------------------------- */\n\nconst DashboardBreadcrumb = ({\n items,\n renderLink,\n className,\n}: DashboardBreadcrumbProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n return (\n <MuiBreadcrumbs\n separator={<NavigateNextIcon fontSize=\"small\" />}\n className={className}\n aria-label=\"breadcrumb\"\n data-testid={`${testIdPrefix}-breadcrumb`}\n sx={{ fontSize: '0.875rem', color: 'text.secondary' }}\n >\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n if (isLast || !item.href) {\n return (\n <Typography\n key={`${item.label}-${index}`}\n component=\"span\"\n sx={{ fontSize: '0.875rem', color: isLast ? 'text.primary' : 'text.secondary' }}\n aria-current={isLast ? 'page' : undefined}\n >\n {item.label}\n </Typography>\n );\n }\n const linkContent = item.label;\n if (renderLink) {\n return <React.Fragment key={`${item.label}-${index}`}>{renderLink(item, linkContent)}</React.Fragment>;\n }\n return (\n <MuiLink\n key={`${item.label}-${index}`}\n href={item.href}\n underline=\"hover\"\n color=\"inherit\"\n sx={{ fontSize: '0.875rem' }}\n >\n {linkContent}\n </MuiLink>\n );\n })}\n </MuiBreadcrumbs>\n );\n};\nDashboardBreadcrumb.displayName = 'Dashboard.Breadcrumb';\n(DashboardBreadcrumb as SlottedComponent).dashboardSlot = 'breadcrumb';\n\n/* -------------------------------------------------------------------------- */\n/* Header + action parts */\n/* -------------------------------------------------------------------------- */\n\nconst DashboardHeader = ({ title, children, className }: DashboardHeaderProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n return (\n <Box\n className={className}\n data-testid={`${testIdPrefix}-header`}\n sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap', minHeight: 40 }}\n >\n <Typography variant=\"h5\" component=\"h1\" sx={{ fontWeight: 600, mr: 0.5 }}>\n {title}\n </Typography>\n {children}\n </Box>\n );\n};\nDashboardHeader.displayName = 'Dashboard.Header';\n(DashboardHeader as SlottedComponent).dashboardSlot = 'header';\n\n/** Flexible spacer — everything composed after it is pushed to the right. */\n/* -------------------------------------------------------------------------- */\n/* Filters */\n/* -------------------------------------------------------------------------- */\n\nconst DashboardFilters = ({ children, className }: DashboardFiltersProps): React.JSX.Element => {\n const { filtersVisible, testIdPrefix } = useDashboardContext();\n return (\n <Collapse in={filtersVisible} unmountOnExit data-testid={`${testIdPrefix}-filters`}>\n <Box\n className={className}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 1.5,\n p: 2,\n borderRadius: 1,\n border: 1,\n borderColor: 'divider',\n bgcolor: 'action.hover',\n }}\n >\n {children}\n </Box>\n </Collapse>\n );\n};\nDashboardFilters.displayName = 'Dashboard.Filters';\n(DashboardFilters as SlottedComponent).dashboardSlot = 'filters';\n\nconst DashboardMoreFilters = ({ children, label = 'More filters' }: DashboardMoreFiltersProps): React.JSX.Element => {\n const { moreFiltersOpen, toggleMoreFilters, testIdPrefix } = useDashboardContext();\n return (\n <Box>\n <Button\n variant=\"text\"\n size=\"small\"\n startIcon={<FilterIcon fontSize=\"small\" />}\n endIcon={moreFiltersOpen ? <ExpandLessIcon fontSize=\"small\" /> : <ExpandMoreIcon fontSize=\"small\" />}\n onClick={toggleMoreFilters}\n aria-expanded={moreFiltersOpen}\n data-testid={`${testIdPrefix}-more-filters-toggle`}\n >\n {label}\n </Button>\n <Collapse in={moreFiltersOpen} unmountOnExit data-testid={`${testIdPrefix}-more-filters-panel`}>\n <Box sx={{ mt: 1.5, p: 2, borderRadius: 1, border: 1, borderColor: 'divider', bgcolor: 'background.paper' }}>\n {children}\n </Box>\n </Collapse>\n </Box>\n );\n};\nDashboardMoreFilters.displayName = 'Dashboard.MoreFilters';\n\n/* -------------------------------------------------------------------------- */\n/* Body */\n/* -------------------------------------------------------------------------- */\n\nconst DashboardBody = ({ children, className }: DashboardBodyProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n return (\n <Box className={className} data-testid={`${testIdPrefix}-body`}>\n {children}\n </Box>\n );\n};\nDashboardBody.displayName = 'Dashboard.Body';\n(DashboardBody as SlottedComponent).dashboardSlot = 'body';\n\n/* -------------------------------------------------------------------------- */\n/* Attach sub-components as dot-notation parts */\n/* -------------------------------------------------------------------------- */\n\nDashboard.Breadcrumb = DashboardBreadcrumb;\nDashboard.Header = DashboardHeader;\nDashboard.Spacer = DashboardSpacer;\nDashboard.Info = DashboardInfo;\nDashboard.FilterToggle = DashboardFilterToggle;\nDashboard.Settings = DashboardSettings;\nDashboard.Export = DashboardExport;\nDashboard.Action = DashboardAction;\nDashboard.Filters = DashboardFilters;\nDashboard.MoreFilters = DashboardMoreFilters;\nDashboard.Body = DashboardBody;\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/DataViews/data-views-shell-toolbar.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The toolbar band, fed from the controller — ~25 props of pure forwarding and\n * nothing else, which is why it lives in its own file rather than in the shell.\n */\nimport { type ColumnVisibilityOption } from \"../../layout/ContentToolbar\";\n\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport { GridToolbar } from \"./data-views-toolbar\";\nimport type { RowAction } from \"./data-views-types\";\nimport type { DataViewsController } from \"./use-data-views-state\";\n\n/**\n * The toolbar band, fed from the controller. Split out of `GridShell` for that\n * function's size budget — it is ~25 props of pure forwarding and nothing else.\n */\nexport function ShellToolbar<T extends Record<string, unknown>>({\n c,\n rows,\n testIdPrefix,\n rowActions,\n bulkActions,\n toolbarRightSlot,\n showInline,\n compactControls,\n counterHidden,\n sortKinds,\n displayView,\n exportConfig,\n filterControls,\n barRef,\n}: {\n c: DataViewsController<T>;\n rows: T[];\n testIdPrefix: string;\n sortKinds?: Record<string, string>;\n displayView?: DisplayPanelView;\n exportConfig?: DataViewExport;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n toolbarRightSlot?: React.ReactNode;\n /** Search + filters, rendered on the toolbar line (see `GridToolbar`). */\n filterControls?: React.ReactNode;\n barRef?: React.Ref<HTMLDivElement>;\n showInline: boolean;\n /** Step 2 of the ladder: Exibir/Exportar as icons only. */\n compactControls?: boolean;\n /** Step 5, last resort: drop the counter so the row still fits one line. */\n counterHidden?: boolean;\n}): React.JSX.Element {\n const columnOptions: ColumnVisibilityOption[] = c.hideableColumns.map((col) => ({\n id: col.id,\n label: col.label,\n visible: c.state.visibleColumns.includes(col.id),\n }));\n return (\n <GridToolbar\n c={c}\n sortKinds={sortKinds}\n displayView={displayView}\n exportConfig={exportConfig}\n filterControls={filterControls}\n barRef={barRef}\n compactControls={compactControls}\n counterHidden={counterHidden}\n testIdPrefix={testIdPrefix}\n selectedRows={c.selectedRows}\n selectAll={c.selectAll}\n clearSelection={c.clearSelection}\n rowActions={rowActions}\n bulkActions={bulkActions}\n sortFields={c.resolvedSortFields}\n activeSortField={c.activeSortField}\n activeSortOrder={c.activeSortOrder}\n onChangeSort={(field, order) => c.patch({ sortBy: [{ id: field, dir: order }] })}\n matchedCount={c.matched.length}\n totalCount={c.serverMode ? c.serverTotalCount : rows.length}\n toolbarRightSlot={toolbarRightSlot}\n columnOptions={columnOptions}\n onToggleColumn={c.toggleColumn}\n filterOpen={c.filterOpen}\n setFilterOpen={c.setFilterOpen}\n activeFilterCount={c.activeFilterCount}\n showFilterTrigger={!showInline}\n />\n );\n}\n\n/** Wires the controller into the shared toolbar + filter panel + grid/cards body. */\n"],"mappings":";;;;;AA0DI;AAxCG,SAAS,aAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAkBsB;AACpB,QAAM,gBAA0C,EAAE,gBAAgB,IAAI,CAAC,SAAS;AAAA,IAC9E,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,SAAS,EAAE,MAAM,eAAe,SAAS,IAAI,EAAE;AAAA,EACjD,EAAE;AACF,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,EAAE;AAAA,MAChB,WAAW,EAAE;AAAA,MACb,gBAAgB,EAAE;AAAA,MAClB;AAAA,MACA;AAAA,MACA,YAAY,EAAE;AAAA,MACd,iBAAiB,EAAE;AAAA,MACnB,iBAAiB,EAAE;AAAA,MACnB,cAAc,CAAC,OAAO,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,CAAC;AAAA,MAC/E,cAAc,EAAE,QAAQ;AAAA,MACxB,YAAY,EAAE,aAAa,EAAE,mBAAmB,KAAK;AAAA,MACrD;AAAA,MACA;AAAA,MACA,gBAAgB,EAAE;AAAA,MAClB,YAAY,EAAE;AAAA,MACd,eAAe,EAAE;AAAA,MACjB,mBAAmB,EAAE;AAAA,MACrB,mBAAmB,CAAC;AAAA;AAAA,EACtB;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/layout/Dashboard/DashboardParts.tsx"],"sourcesContent":["'use client';\n\nimport CloseIcon from '@mui/icons-material/Close';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport ExportIcon from '@mui/icons-material/FileDownloadOutlined';\nimport FilterIcon from '@mui/icons-material/FilterListRounded';\nimport InfoIcon from '@mui/icons-material/InfoOutlined';\nimport SettingsIcon from '@mui/icons-material/SettingsOutlined';\nimport Badge from '@mui/material/Badge/index.js';\nimport Box from '@mui/material/Box/index.js';\nimport Dialog from '@mui/material/Dialog/index.js';\nimport DialogContent from '@mui/material/DialogContent/index.js';\nimport DialogTitle from '@mui/material/DialogTitle/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport Menu from '@mui/material/Menu/index.js';\nimport MenuItem from '@mui/material/MenuItem/index.js';\nimport Popover from '@mui/material/Popover/index.js';\nimport Tooltip from '@mui/material/Tooltip/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport React, { useState } from 'react';\n\nimport { HeaderButton } from '../../form/HeaderButton';\nimport { useDashboardContext } from './DashboardContext';\nimport type {\n DashboardActionProps,\n DashboardExportFormat,\n DashboardExportProps,\n DashboardFilterToggleProps,\n DashboardInfoProps,\n DashboardSettingsProps,\n} from './Dashboard.types';\n\n/** Flexible spacer — everything composed after it is pushed to the right. */\nexport const DashboardSpacer = (): React.JSX.Element => <Box sx={{ flex: 1 }} aria-hidden />;\nDashboardSpacer.displayName = 'Dashboard.Spacer';\n\nexport const DashboardInfo = ({\n title = 'About this page',\n children,\n ariaLabel = 'Page information',\n}: DashboardInfoProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);\n const open = Boolean(anchorEl);\n return (\n <>\n <Tooltip title={ariaLabel}>\n <IconButton\n size=\"small\"\n aria-label={ariaLabel}\n aria-haspopup=\"dialog\"\n onClick={(e) => setAnchorEl(e.currentTarget)}\n data-testid={`${testIdPrefix}-info-trigger`}\n sx={{ color: 'text.secondary' }}\n >\n <InfoIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Popover\n open={open}\n anchorEl={anchorEl}\n onClose={() => setAnchorEl(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}\n slotProps={{ paper: { sx: { width: 360, maxWidth: '90vw' } } }}\n data-testid={`${testIdPrefix}-info-popover`}\n >\n <Box sx={{ px: 2, py: 1.5, borderBottom: 1, borderColor: 'divider', display: 'flex', gap: 1, alignItems: 'center' }}>\n <InfoIcon fontSize=\"small\" sx={{ color: 'text.secondary' }} />\n <Typography sx={{ fontWeight: 600 }}>{title}</Typography>\n </Box>\n <Box sx={{ px: 2, py: 1.5, fontSize: '0.875rem', color: 'text.secondary' }}>{children}</Box>\n </Popover>\n </>\n );\n};\nDashboardInfo.displayName = 'Dashboard.Info';\n\nexport const DashboardFilterToggle = ({ ariaLabel }: DashboardFilterToggleProps): React.JSX.Element => {\n const { filtersVisible, toggleFilters, activeFilterCount, testIdPrefix } = useDashboardContext();\n const label = ariaLabel ?? (filtersVisible ? 'Hide filters' : 'Show filters');\n return (\n <Tooltip title={label}>\n <IconButton\n size=\"small\"\n aria-label={label}\n aria-pressed={filtersVisible}\n onClick={toggleFilters}\n data-testid={`${testIdPrefix}-filter-toggle`}\n sx={{ color: filtersVisible ? 'primary.main' : 'text.secondary', bgcolor: filtersVisible ? 'action.selected' : 'transparent' }}\n >\n <Badge badgeContent={activeFilterCount} color=\"primary\" overlap=\"circular\">\n <FilterIcon fontSize=\"small\" />\n </Badge>\n </IconButton>\n </Tooltip>\n );\n};\nDashboardFilterToggle.displayName = 'Dashboard.FilterToggle';\n\nexport const DashboardSettings = ({\n title = 'Settings',\n closeLabel,\n children,\n ariaLabel = 'Settings',\n href,\n linkComponent,\n}: DashboardSettingsProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n const [open, setOpen] = useState(false);\n\n // Link mode: the gear navigates to a settings route (e.g. the page's\n // Configuração section) instead of opening an in-page dialog.\n if (href) {\n const LinkComponent = linkComponent ?? 'a';\n return (\n <Tooltip title={ariaLabel}>\n <IconButton\n size=\"small\"\n aria-label={ariaLabel}\n component={LinkComponent}\n href={href}\n data-testid={`${testIdPrefix}-settings-trigger`}\n sx={{ color: 'text.secondary' }}\n >\n <SettingsIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n );\n }\n\n return (\n <>\n <Tooltip title={ariaLabel}>\n <IconButton\n size=\"small\"\n aria-label={ariaLabel}\n aria-haspopup=\"dialog\"\n onClick={() => setOpen(true)}\n data-testid={`${testIdPrefix}-settings-trigger`}\n sx={{ color: 'text.secondary' }}\n >\n <SettingsIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Dialog open={open} onClose={() => setOpen(false)} maxWidth=\"sm\" fullWidth data-testid={`${testIdPrefix}-settings-dialog`}>\n <DialogTitle sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n {title}\n <IconButton aria-label={closeLabel} size=\"small\" onClick={() => setOpen(false)}>\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n </DialogTitle>\n <DialogContent dividers>{children}</DialogContent>\n </Dialog>\n </>\n );\n};\nDashboardSettings.displayName = 'Dashboard.Settings';\n\nconst DEFAULT_EXPORT_FORMATS: DashboardExportFormat[] = [\n { id: 'csv', label: 'CSV (.csv)' },\n { id: 'xlsx', label: 'Excel (.xlsx)' },\n { id: 'json', label: 'JSON (.json)' },\n];\n\nexport const DashboardExport = ({\n formats = DEFAULT_EXPORT_FORMATS,\n onExport,\n label = 'Export',\n}: DashboardExportProps): React.JSX.Element => {\n const { testIdPrefix } = useDashboardContext();\n const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);\n const open = Boolean(anchorEl);\n return (\n <>\n <HeaderButton\n variant=\"outlined\"\n color=\"inherit\"\n text={label}\n icon={<ExportIcon fontSize=\"small\" />}\n endIcon={<ExpandMoreIcon fontSize=\"small\" />}\n onClick={(e) => setAnchorEl(e.currentTarget)}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n dataTestId={`${testIdPrefix}-export-trigger`}\n />\n <Menu anchorEl={anchorEl} open={open} onClose={() => setAnchorEl(null)} data-testid={`${testIdPrefix}-export-menu`}>\n {formats.map((format) => (\n <MenuItem\n key={format.id}\n onClick={() => {\n onExport(format.id);\n setAnchorEl(null);\n }}\n data-testid={`${testIdPrefix}-export-${format.id}`}\n >\n {format.label}\n </MenuItem>\n ))}\n </Menu>\n </>\n );\n};\nDashboardExport.displayName = 'Dashboard.Export';\n\nexport const DashboardAction = ({ children }: DashboardActionProps): React.JSX.Element => (\n <Box sx={{ display: 'inline-flex' }}>{children}</Box>\n);\nDashboardAction.displayName = 'Dashboard.Action';\n"],"mappings":";;;;;;;;AAEA,OAAO,eAAe;AACtB,OAAO,oBAAoB;AAC3B,OAAO,gBAAgB;AACvB,OAAO,gBAAgB;AACvB,OAAO,cAAc;AACrB,OAAO,kBAAkB;AACzB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,YAAY;AACnB,OAAO,mBAAmB;AAC1B,OAAO,iBAAiB;AACxB,OAAO,gBAAgB;AACvB,OAAO,UAAU;AACjB,OAAO,cAAc;AACrB,OAAO,aAAa;AACpB,OAAO,aAAa;AACpB,OAAO,gBAAgB;AACvB,SAAgB,gBAAgB;AAcwB,SAYpD,UAZoD,KAiChD,YAjCgD;AAAjD,IAAM,kBAAkB,MAAyB,oBAAC,OAAI,IAAI,EAAE,MAAM,EAAE,GAAG,eAAW,MAAC;AAC1F,gBAAgB,cAAc;AAEvB,IAAM,gBAAgB,CAAC;AAAA,EAC5B,QAAQ;AAAA,EACR;AAAA,EACA,YAAY;AACd,MAA6C;AAC3C,QAAM,EAAE,aAAa,IAAI,oBAAoB;AAC7C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmC,IAAI;AACvE,QAAM,OAAO,QAAQ,QAAQ;AAC7B,SACE,iCACE;AAAA,wBAAC,WAAQ,OAAO,WACd;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,iBAAc;AAAA,QACd,SAAS,CAAC,MAAM,YAAY,EAAE,aAAa;AAAA,QAC3C,eAAa,GAAG,YAAY;AAAA,QAC5B,IAAI,EAAE,OAAO,iBAAiB;AAAA,QAE9B,8BAAC,YAAS,UAAS,SAAQ;AAAA;AAAA,IAC7B,GACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS,MAAM,YAAY,IAAI;AAAA,QAC/B,cAAc,EAAE,UAAU,UAAU,YAAY,OAAO;AAAA,QACvD,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,UAAU,OAAO,EAAE,EAAE;AAAA,QAC7D,eAAa,GAAG,YAAY;AAAA,QAE5B;AAAA,+BAAC,OAAI,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,cAAc,GAAG,aAAa,WAAW,SAAS,QAAQ,KAAK,GAAG,YAAY,SAAS,GAChH;AAAA,gCAAC,YAAS,UAAS,SAAQ,IAAI,EAAE,OAAO,iBAAiB,GAAG;AAAA,YAC5D,oBAAC,cAAW,IAAI,EAAE,YAAY,IAAI,GAAI,iBAAM;AAAA,aAC9C;AAAA,UACA,oBAAC,OAAI,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,UAAU,YAAY,OAAO,iBAAiB,GAAI,UAAS;AAAA;AAAA;AAAA,IACxF;AAAA,KACF;AAEJ;AACA,cAAc,cAAc;AAErB,IAAM,wBAAwB,CAAC,EAAE,UAAU,MAAqD;AACrG,QAAM,EAAE,gBAAgB,eAAe,mBAAmB,aAAa,IAAI,oBAAoB;AAC/F,QAAM,QAAQ,cAAc,iBAAiB,iBAAiB;AAC9D,SACE,oBAAC,WAAQ,OAAO,OACd;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,gBAAc;AAAA,MACd,SAAS;AAAA,MACT,eAAa,GAAG,YAAY;AAAA,MAC5B,IAAI,EAAE,OAAO,iBAAiB,iBAAiB,kBAAkB,SAAS,iBAAiB,oBAAoB,cAAc;AAAA,MAE7H,8BAAC,SAAM,cAAc,mBAAmB,OAAM,WAAU,SAAQ,YAC9D,8BAAC,cAAW,UAAS,SAAQ,GAC/B;AAAA;AAAA,EACF,GACF;AAEJ;AACA,sBAAsB,cAAc;AAE7B,IAAM,oBAAoB,CAAC;AAAA,EAChC,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AACF,MAAiD;AAC/C,QAAM,EAAE,aAAa,IAAI,oBAAoB;AAC7C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AAItC,MAAI,MAAM;AACR,UAAM,gBAAgB,iBAAiB;AACvC,WACE,oBAAC,WAAQ,OAAO,WACd;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,WAAW;AAAA,QACX;AAAA,QACA,eAAa,GAAG,YAAY;AAAA,QAC5B,IAAI,EAAE,OAAO,iBAAiB;AAAA,QAE9B,8BAAC,gBAAa,UAAS,SAAQ;AAAA;AAAA,IACjC,GACF;AAAA,EAEJ;AAEA,SACE,iCACE;AAAA,wBAAC,WAAQ,OAAO,WACd;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,iBAAc;AAAA,QACd,SAAS,MAAM,QAAQ,IAAI;AAAA,QAC3B,eAAa,GAAG,YAAY;AAAA,QAC5B,IAAI,EAAE,OAAO,iBAAiB;AAAA,QAE9B,8BAAC,gBAAa,UAAS,SAAQ;AAAA;AAAA,IACjC,GACF;AAAA,IACA,qBAAC,UAAO,MAAY,SAAS,MAAM,QAAQ,KAAK,GAAG,UAAS,MAAK,WAAS,MAAC,eAAa,GAAG,YAAY,oBACrG;AAAA,2BAAC,eAAY,IAAI,EAAE,SAAS,QAAQ,YAAY,UAAU,gBAAgB,gBAAgB,GACvF;AAAA;AAAA,QACD,oBAAC,cAAW,cAAY,YAAY,MAAK,SAAQ,SAAS,MAAM,QAAQ,KAAK,GAC3E,8BAAC,aAAU,UAAS,SAAQ,GAC9B;AAAA,SACF;AAAA,MACA,oBAAC,iBAAc,UAAQ,MAAE,UAAS;AAAA,OACpC;AAAA,KACF;AAEJ;AACA,kBAAkB,cAAc;AAEhC,IAAM,yBAAkD;AAAA,EACtD,EAAE,IAAI,OAAO,OAAO,aAAa;AAAA,EACjC,EAAE,IAAI,QAAQ,OAAO,gBAAgB;AAAA,EACrC,EAAE,IAAI,QAAQ,OAAO,eAAe;AACtC;AAEO,IAAM,kBAAkB,CAAC;AAAA,EAC9B,UAAU;AAAA,EACV;AAAA,EACA,QAAQ;AACV,MAA+C;AAC7C,QAAM,EAAE,aAAa,IAAI,oBAAoB;AAC7C,QAAM,CAAC,UAAU,WAAW,IAAI,SAA6B,IAAI;AACjE,QAAM,OAAO,QAAQ,QAAQ;AAC7B,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM,oBAAC,cAAW,UAAS,SAAQ;AAAA,QACnC,SAAS,oBAAC,kBAAe,UAAS,SAAQ;AAAA,QAC1C,SAAS,CAAC,MAAM,YAAY,EAAE,aAAa;AAAA,QAC3C,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,YAAY,GAAG,YAAY;AAAA;AAAA,IAC7B;AAAA,IACA,oBAAC,QAAK,UAAoB,MAAY,SAAS,MAAM,YAAY,IAAI,GAAG,eAAa,GAAG,YAAY,gBACjG,kBAAQ,IAAI,CAAC,WACZ;AAAA,MAAC;AAAA;AAAA,QAEC,SAAS,MAAM;AACb,mBAAS,OAAO,EAAE;AAClB,sBAAY,IAAI;AAAA,QAClB;AAAA,QACA,eAAa,GAAG,YAAY,WAAW,OAAO,EAAE;AAAA,QAE/C,iBAAO;AAAA;AAAA,MAPH,OAAO;AAAA,IAQd,CACD,GACH;AAAA,KACF;AAEJ;AACA,gBAAgB,cAAc;AAEvB,IAAM,kBAAkB,CAAC,EAAE,SAAS,MACzC,oBAAC,OAAI,IAAI,EAAE,SAAS,cAAc,GAAI,UAAS;AAEjD,gBAAgB,cAAc;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/DataViews/DataViewsGrid.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\nimport { type SortFieldDefinition } from \"../../layout/ContentToolbar\";\n\nimport { GridShell } from \"./data-views-grid-parts\";\nimport type { ListGroupConfig } from \"./list-card-rails\";\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport type { BoardConfig } from \"./DataViewsBoard\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport type { ScopeConfig } from \"./data-views-scopes\";\nimport type { DataViewCardSelection } from \"./data-views-types\";\nimport {\n type DataViewColumn,\n type DataViewsLayout,\n type DataViewServer,\n type DataViewState,\n type DataViewSyncState,\n type FilterFieldConfig,\n type RangeFieldConfig,\n type RowAction,\n} from \"./data-views-types\";\nimport { useDataViewsState } from \"./use-data-views-state\";\n\ninterface DataViewsGridProps<T extends Record<string, unknown>> {\n rows: T[];\n columns: DataViewColumn<T>[];\n fields: FilterFieldConfig<T>[];\n /** Optional numeric min/max range filters (advanced \"filter by amount\"). */\n rangeFields?: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n /** Row click opens the row; clicks in the actions column are ignored. */\n onRowClick?: (row: T) => void;\n emptyState?: React.ReactNode;\n dataTestId?: string;\n testIdPrefix?: string;\n /** Seed/replace the view state. A NEW reference re-applies (used to apply a saved view). */\n appliedState?: DataViewState;\n /**\n * URL-driven controls (search/pills/ranges/sort) that RE-APPLY on reference\n * change while preserving column visibility — for server-mode lists that keep\n * their filter/sort/page in the address bar (see {@link DataViewSyncState}).\n */\n syncState?: DataViewSyncState;\n /** Notified on every view-state change (so a save-view modal can read it). */\n onStateChange?: (state: DataViewState) => void;\n /**\n * Notified with the currently-visible (search + filter matched) rows whenever\n * they change — so a page-level Export exports what the user sees, not the\n * full dataset.\n */\n onVisibleRowsChange?: (rows: T[]) => void;\n /** Saved-views UI injected into the toolbar (FUT-89). */\n toolbarRightSlot?: React.ReactNode;\n /**\n * The saved-view chrome for the Exibir panel: its VISÃO header (with the\n * views dropdown) and its Redefinir / Salvar visão footer. Supplied by\n * `DataViewsTableBase`; without it the panel is tabs only.\n */\n displayView?: DisplayPanelView;\n /** Big page title in the header row (next to the funnel + gear). */\n title?: string;\n /** Primary page actions rendered at the header's right. */\n headerActions?: React.ReactNode;\n /**\n * Sort options for the toolbar's \"Sort By\" dropdown. Defaults to the sortable\n * columns (asc/desc each) when omitted.\n */\n sortFields?: SortFieldDefinition[];\n /**\n * Per-sort-field VALUE KIND (`\"currency\" | \"number\" | \"date\" | \"text\"`), so the\n * Exibir panel phrases the direction in that column's own terms. \"Crescente\"\n * on a currency column is a puzzle; \"Menor → maior\" is not. Defaults to text.\n */\n sortKinds?: Record<string, string>;\n /**\n * Opt-in \"Exportar\" control. The grid hands the host the current query,\n * UNPAGINATED, and the host re-queries — the grid never fetches, and an\n * export therefore follows the filters rather than the loaded page.\n */\n exportConfig?: DataViewExport;\n /**\n * A single, reusable list of row actions that drives BOTH the per-row \"⋮\"\n * kebab AND the bulk-actions menu (tabwoah model). When provided, the grid\n * appends a kebab actions column automatically (unless the page already\n * defines one) and shows an \"Ações\" bulk menu when rows are selected.\n */\n rowActions?: RowAction<T>[];\n /**\n * Extra leading control rendered in the auto kebab column, before the \"⋮\"\n * (e.g. a favourite star). Only used when `rowActions` is set.\n */\n rowActionsLeading?: (row: T) => React.ReactNode;\n /**\n * Low-level override for the selection bulk control. Prefer `rowActions`.\n * Receives the selected rows + a `clearSelection` callback.\n */\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /**\n * Render a bespoke per-row menu in the actions column instead of the auto\n * kebab — typically an entity's self-contained 3-dots menu that owns its own\n * popups, so the SAME menu component drives both the table row and the card.\n * `rowActions`/`bulkActions` still drive the multi-row bulk menu.\n */\n renderRowMenu?: (row: T) => React.ReactNode;\n /**\n * Opt-in \"Grade\" (cards) layout. When provided, a Grade/Tabela toggle appears in\n * the toolbar and the cards body renders each visible row via this function\n * (reusing the same search/filter/sort). Omit ⇒ table only (unchanged).\n */\n renderCard?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /**\n * Opt-in \"Quadro\" (board) layout: the loaded page laid out as columns of one\n * grouping field. Reuses `renderCard`, so supplying a board WITHOUT one simply\n * offers no board. Best when the groups are states in a state machine — derive\n * these groups and `scopes` from ONE definition so the two cannot drift.\n */\n board?: BoardConfig<T>;\n /**\n * Opt-in \"Lista\" layout (FUT-733): one FULL-WIDTH row per record, rendered by\n * the entity — a marker, a title, a subtitle and a value on the right. Sits\n * between the table (compare columns) and the cards (browse); omit ⇒ not\n * offered, exactly as `renderCard` gates the cards.\n */\n renderListRow?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /**\n * The Lista's SHARED COLUMNS — declared once for the list, obeyed by every row.\n *\n * This is what makes a list line up by construction rather than by convention.\n * Omit it and each row still resolves its own tracks from its own config,\n * which agrees with its neighbours right up until one row carries an unusually\n * wide value.\n */\n listGroup?: ListGroupConfig<T>;\n /**\n * The page-level partition rendered as an exclusive tab strip above the\n * toolbar, with server-supplied counts. Requires `server`: a scope is applied\n * at the backend, never in the browser.\n */\n scopes?: ScopeConfig[];\n /** The row field the scopes partition by — used only to reject a pill over the same field. */\n scopeFieldId?: string;\n /** Which layout to show first when the user has expressed no preference (default \"table\"). */\n defaultLayout?: DataViewsLayout;\n /**\n * Ignore the remembered cross-screen layout preference and pin to\n * `defaultLayout`. For tables that exist to SHOW a layout — stories, docs,\n * screenshots — not for real screens.\n */\n ignoreStoredLayout?: boolean;\n /**\n * Opt into the responsive inline filter UX (collapsible filter row on wide\n * screens, modal on narrow). Default `false` keeps the classic slide-in panel.\n */\n inlineFilters?: boolean;\n /** Keep the inline search visible with no filter fields and no active search. */\n alwaysShowSearch?: boolean;\n /** Server-mode wiring; when set the grid is backend-driven (no client filter/sort/paginate). */\n server?: DataViewServer;\n}\n\n/**\n * Surface the visible (filtered) rows so a page-level Export matches the view.\n *\n * Pages pass inline column/field arrays, so `matched` is a fresh reference on\n * every render even when its contents are unchanged. The guard is a signature\n * over the rows' *contents* (not just their ids), so the callback — and the\n * parent `useState` it usually drives — fires only when the visible data\n * actually changes. Ids alone are not enough: a server refresh can change a\n * visible row's values while keeping its id, and the export must reflect them.\n * Content-equal renders keep the same signature, so this never loops.\n */\nfunction useVisibleRowsNotifier<T>(matched: T[], onVisibleRowsChange?: (rows: T[]) => void): void {\n const visibleSignature = JSON.stringify(matched);\n const lastSignature = useRef<string | null>(null);\n useEffect(() => {\n if (lastSignature.current === visibleSignature) return;\n lastSignature.current = visibleSignature;\n onVisibleRowsChange?.(matched);\n }, [visibleSignature, matched, onVisibleRowsChange]);\n}\n\n/**\n * The reusable admin DataViews table (FUT-88): the shared ContentToolbar +\n * TableFilter panel over `@12-apps/ui` DataGrid. State + derived data live in\n * {@link useDataViewsState}; the render lives in `GridShell`. This component just\n * connects the two. Reused across every admin list page.\n */\nexport function DataViewsGrid<T extends Record<string, unknown>>(\n props: DataViewsGridProps<T>,\n): React.JSX.Element {\n // Forwarded as a whole rather than restated name-by-name twice: this component\n // only ADDS the controller, and a 25-name destructure repeated in the JSX is\n // where a newly added prop silently stops being passed on.\n const { rangeFields = [], testIdPrefix = \"table\" } = props;\n const controller = useDataViewsState({ ...props, rangeFields, testIdPrefix });\n useVisibleRowsNotifier(controller.matched, props.onVisibleRowsChange);\n return <GridShell {...props} c={controller} rangeFields={rangeFields} testIdPrefix={testIdPrefix} />;\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,WAAW,cAAc;AAoMzB;AAzBT,SAAS,uBAA0B,SAAc,qBAAiD;AAChG,QAAM,mBAAmB,KAAK,UAAU,OAAO;AAC/C,QAAM,gBAAgB,OAAsB,IAAI;AAChD,YAAU,MAAM;AACd,QAAI,cAAc,YAAY,iBAAkB;AAChD,kBAAc,UAAU;AACxB,0BAAsB,OAAO;AAAA,EAC/B,GAAG,CAAC,kBAAkB,SAAS,mBAAmB,CAAC;AACrD;AAQO,SAAS,cACd,OACmB;AAInB,QAAM,EAAE,cAAc,CAAC,GAAG,eAAe,QAAQ,IAAI;AACrD,QAAM,aAAa,kBAAkB,EAAE,GAAG,OAAO,aAAa,aAAa,CAAC;AAC5E,yBAAuB,WAAW,SAAS,MAAM,mBAAmB;AACpE,SAAO,oBAAC,aAAW,GAAG,OAAO,GAAG,YAAY,aAA0B,cAA4B;AACpG;","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 // Updater, never the render's `state` — see {@link DataViewStatePatch}.\n onTogglePill: (fieldId, value, checked) =>\n c.patch(({ pills }) => ({ pills: { ...pills, [fieldId]: togglePillValues(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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/DataViews/DataViewsTableBase.tsx"],"sourcesContent":["\"use client\";\n\nimport type { SortFieldDefinition } from \"../../layout/ContentToolbar\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { DataViewsGrid } from \"./DataViewsGrid\";\nimport type { ListGroupConfig } from \"./list-card-rails\";\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport { viewStateKey } from \"./data-views-dirty\";\nimport { DeleteViewDialog } from \"./DeleteViewDialog\";\nimport type { BoardConfig } from \"./DataViewsBoard\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport type { ScopeConfig } from \"./data-views-scopes\";\nimport { ViewDialogs, ViewMutationErrorAlert } from \"./data-views-table-parts\";\nimport {\n useSavedViewsController,\n type SavedViewsController,\n} from \"./use-saved-views-controller\";\nimport {\n type DataViewColumn,\n type DataViewsLayout,\n type DataViewServer,\n type DataViewState,\n type DataViewSyncState,\n type DataViewPersistence,\n type DataViewRouter,\n type FilterFieldConfig,\n type RangeFieldConfig,\n type DataViewCardSelection,\n type RowAction,\n type SavedViewSummary,\n} from \"./data-views-types\";\n\nexport interface DataViewsTableBaseProps<T extends Record<string, unknown>> {\n /** The applied-view id read from the URL (`?view=`) on load, or null. */\n initialViewId?: string | null;\n /** Injected saved-view persistence (create/update/delete). */\n persistence: DataViewPersistence;\n /** Injected router side-effects (URL sync + refresh). */\n router: DataViewRouter;\n rows: T[];\n columns: DataViewColumn<T>[];\n fields: FilterFieldConfig<T>[];\n /** Optional numeric min/max range filters (advanced \"filter by amount\"). */\n rangeFields?: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n onRowClick?: (row: T) => void;\n emptyState?: React.ReactNode;\n dataTestId?: string;\n testIdPrefix?: string;\n /** The user's + shared views for this table (from the server). */\n views: SavedViewSummary[];\n /** Big page title in the table header, beside the funnel + gear (GTA layout). */\n title?: string;\n /** Primary page actions (e.g. \"Novo produto\") rendered at the header's right. */\n headerActions?: React.ReactNode;\n /** Sort options for the toolbar's \"Sort By\" dropdown (defaults to sortable columns). */\n sortFields?: SortFieldDefinition[];\n /**\n * Per-sort-field VALUE KIND (`\"currency\" | \"number\" | \"date\" | \"text\"`), so the\n * Exibir panel phrases the direction in that column's own terms. \"Crescente\"\n * on a currency column is a puzzle; \"Menor → maior\" is not. Defaults to text.\n */\n sortKinds?: Record<string, string>;\n /**\n * Opt-in \"Exportar\" control. The grid hands the host the current query,\n * UNPAGINATED, and the host re-queries — the grid never fetches, and an\n * export therefore follows the filters rather than the loaded page.\n */\n exportConfig?: DataViewExport;\n /** Notified with the currently-visible (filtered) rows, so Export matches the view. */\n onVisibleRowsChange?: (rows: T[]) => void;\n /** Reusable row actions driving both the row \"⋮\" kebab and the bulk menu. */\n rowActions?: RowAction<T>[];\n /** Leading control in the auto kebab column (e.g. a favourite star). */\n rowActionsLeading?: (row: T) => React.ReactNode;\n /** Low-level bulk-action override; prefer `rowActions`. */\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** Bespoke per-row menu (an entity's self-contained 3-dots menu) instead of the auto kebab. */\n renderRowMenu?: (row: T) => React.ReactNode;\n /** Opt-in \"Grade\" (cards) layout — a card renderer per row; adds a Grade/Tabela toggle. */\n renderCard?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** Opt-in \"Quadro\" (board) layout — the loaded page as columns of one field. Needs `renderCard`. */\n board?: BoardConfig<T>;\n /** Opt-in \"Lista\" layout — one full-width, entity-rendered row per record (FUT-733). */\n renderListRow?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** The Lista's shared columns, so its rows line up by construction not convention. */\n listGroup?: ListGroupConfig<T>;\n /** The page-level partition rendered as tabs under the toolbar (server mode only). */\n scopes?: ScopeConfig[];\n /** The row field the scopes partition by — used only to reject a pill over the same field. */\n scopeFieldId?: string;\n /** Which layout to show first when the user has expressed no preference (default \"table\"). */\n defaultLayout?: DataViewsLayout;\n /**\n * Ignore the remembered cross-screen layout preference and pin to\n * `defaultLayout`. For tables that exist to SHOW a layout — stories, docs,\n * screenshots — not for real screens.\n */\n ignoreStoredLayout?: boolean;\n /** Opt into the responsive inline filter UX (collapsible row / modal). Default keeps the panel. */\n inlineFilters?: boolean;\n /** Keep the inline search visible with no filter fields and no active search. */\n alwaysShowSearch?: boolean;\n /** Server-mode wiring (FUT-180): backend-driven rows/total + re-fetch. Omit for client mode. */\n server?: DataViewServer;\n /** Seed the initial view state (search/pills/ranges/sort) from the URL when no saved view applies. */\n initialState?: DataViewState;\n}\n\n/**\n * Derive the grid's reactive `syncState` from the URL-seeded `initialState` in\n * server mode so browser back/forward RE-APPLIES the search/pills/sort controls\n * (merging over live state, preserving hidden columns — see {@link DataViewSyncState}).\n * Client-mode tables (no `server`) get `undefined`. Callers memoize `initialState`\n * on the URL, so this reference only changes on genuine navigations.\n */\nfunction useUrlSyncState(\n server: DataViewServer | undefined,\n initialState: DataViewState | undefined,\n): DataViewSyncState | undefined {\n const isServerMode = server !== undefined;\n return useMemo<DataViewSyncState | undefined>(\n () =>\n isServerMode && initialState\n ? {\n search: initialState.search,\n pills: initialState.pills,\n ranges: initialState.ranges,\n sortBy: initialState.sortBy,\n // The scope belongs in the URL-driven slice alongside them: a\n // `?view=recusados`-style deep link and browser back/forward must\n // move the tab strip, and they must do it WITHOUT resetting the\n // user's hidden columns — which is the whole reason this is a\n // merging `syncState` and not a replacing `appliedState`.\n scope: initialState.scope,\n }\n : undefined,\n [isServerMode, initialState],\n );\n}\n\n/**\n * Resolve the initial applied view: a `?view=<id>` shortcut (FUT-90) wins, else\n * the user's default view, else none. Drives the seed state + trigger label.\n */\nfunction resolveInitialView(\n views: SavedViewSummary[],\n requestedId: string | null,\n): SavedViewSummary | undefined {\n const requested = requestedId ? views.find((view) => view.id === requestedId) : undefined;\n return requested ?? views.find((view) => view.isDefault);\n}\n\n/**\n * The Exibir panel's view chrome, assembled from the saved-views controller.\n * Extracted so {@link DataViewsTableBase} stays inside its size budget.\n */\nfunction buildDisplayView({\n ctl,\n views,\n activeView,\n dirty,\n onRequestDelete,\n}: {\n ctl: SavedViewsController;\n views: SavedViewSummary[];\n activeView: SavedViewSummary | undefined;\n dirty: boolean;\n /** Opens the confirmation; the delete itself happens on confirm. */\n onRequestDelete: (view: SavedViewSummary) => void;\n}): DisplayPanelView {\n return {\n activeViewName: ctl.activeViewName,\n dirty,\n onReset: () => (activeView ? ctl.applyView(activeView) : ctl.selectMain()),\n // Only offer \"Atualizar\" when there IS a view to update — otherwise the\n // single footer button is a plain \"Salvar visão\".\n onUpdate: activeView ? () => ctl.openEdit(activeView) : undefined,\n onSaveAs: ctl.openCreate,\n // The views themselves, not a dropdown: the panel renders them in its own\n // body (see `data-views-view-nav`), so there is no second popover to clip\n // the row actions.\n nav: {\n views,\n activeViewId: activeView?.id ?? null,\n onSelectView: (id) => {\n const next = id === null ? null : views.find((view) => view.id === id);\n if (next) ctl.applyView(next);\n else ctl.selectMain();\n },\n onEditView: ctl.openEdit,\n onPatchView: (view, changes) => void ctl.patchView(view, changes),\n onDeleteView: onRequestDelete,\n },\n };\n}\n\n/**\n * \"Are there unsaved changes?\" — the dot on Exibir, and whether Redefinir and\n * Salvar visão are live.\n *\n * Two things it gets right that the inline version did not. It compares\n * NORMALISED states (`viewStateKey`), so a filter applied and then removed is\n * clean again rather than clean-looking but flagged; and it re-baselines after\n * a SAVE, because the state just written is the clean one from that point.\n *\n * The baseline is the first state the grid emits for a view, not the view\n * itself: the grid normalises what it is handed — resolving visible columns,\n * filling in layout — so the applied view is never byte-identical to the state\n * it produces.\n */\nfunction useDirtyTracking(ctl: SavedViewsController): {\n dirty: boolean;\n noteState: (state: DataViewState) => void;\n markSaved: () => void;\n} {\n const [dirty, setDirty] = useState(false);\n const [savedAt, setSavedAt] = useState(0);\n const baseline = useRef<string | null>(null);\n const appliedKey = JSON.stringify(ctl.applied ?? null);\n\n useEffect(() => {\n baseline.current = null;\n setDirty(false);\n }, [appliedKey, savedAt]);\n\n return {\n dirty,\n noteState: (state) => {\n ctl.currentRef.current = state;\n const key = viewStateKey(state);\n if (baseline.current === null) {\n baseline.current = key;\n setDirty(false);\n return;\n }\n const next = key !== baseline.current;\n setDirty((prev) => (prev === next ? prev : next));\n },\n markSaved: () => setSavedAt((tick) => tick + 1),\n };\n}\n\n/**\n * The reusable admin table (FUT-89): the DataViews grid plus the full saved-views\n * experience — a views dropdown, a save/edit modal (with preview), and a manage\n * dialog. Framework-agnostic: saved-view persistence and router side-effects are\n * INJECTED (`persistence`, `router`, `initialViewId`) so the host app wires them\n * to its backend + framework router. A default view auto-applies on load; applying\n * a view restores its filters + columns + sort. Each table supplies its own columns\n * + filter fields; everything else is shared.\n */\nexport function DataViewsTableBase<T extends Record<string, unknown>>(\n props: DataViewsTableBaseProps<T>,\n): React.JSX.Element {\n // Forwarded as a whole rather than restated name-by-name twice (as in\n // DataViewsGrid): this component only ADDS the saved-views chrome, and a\n // 30-name destructure repeated in the JSX is exactly where a newly added prop\n // silently stops being passed on.\n const {\n initialViewId = null,\n persistence,\n router,\n columns,\n fields,\n testIdPrefix = \"table\",\n views,\n server,\n initialState,\n } = props;\n const initialView = resolveInitialView(views, initialViewId);\n const columnIds = columns.map((col) => col.id);\n const ctl = useSavedViewsController(persistence, router, columnIds, views, initialView, initialState);\n // Unsaved-changes flag for the Exibir panel. Set from `onStateChange` rather\n // than derived in render because the live state lives in a REF (the grid owns\n // it); the equality bail-out in `setDirty` is what stops the update loop.\n const { dirty, noteState, markSaved } = useDirtyTracking(ctl);\n // Deleting a saved view is confirmed, not immediate — see `DeleteViewDialog`.\n const [pendingDelete, setPendingDelete] = useState<SavedViewSummary | null>(null);\n // The view the panel's \"Redefinir\" restores: the applied one, or the built-in\n // \"Visão principal\" when none is.\n const activeView = views.find((view) => view.name === ctl.activeViewName);\n const displayView = buildDisplayView({\n ctl,\n views,\n activeView,\n dirty,\n onRequestDelete: setPendingDelete,\n });\n // Server-mode lists re-apply URL-derived controls on back/forward (not just the mount seed).\n const syncState = useUrlSyncState(server, initialState);\n\n return (\n <>\n <ViewMutationErrorAlert error={ctl.mutationError} onClose={ctl.clearMutationError} testIdPrefix={testIdPrefix} />\n <DataViewsGrid<T>\n {...props}\n testIdPrefix={testIdPrefix}\n appliedState={ctl.applied}\n syncState={syncState}\n onStateChange={noteState}\n // The saved-views menu is NOT a toolbar control any more: it lives in\n // the Exibir panel's VISÃO header, passed through `displayView`.\n displayView={displayView}\n />\n {renderViewDialogs(ctl, fields, columns, views, testIdPrefix, markSaved)}\n <DeleteViewDialog\n view={pendingDelete}\n onClose={() => setPendingDelete(null)}\n onConfirm={(view) => {\n void ctl.handleDelete(view);\n setPendingDelete(null);\n }}\n testIdPrefix={testIdPrefix}\n />\n </>\n );\n}\n\n/** The save + manage saved-view dialogs, split out to keep the base thin. */\nfunction renderViewDialogs<T extends Record<string, unknown>>(\n ctl: SavedViewsController,\n fields: DataViewsTableBaseProps<T>[\"fields\"],\n columns: DataViewsTableBaseProps<T>[\"columns\"],\n views: SavedViewSummary[],\n testIdPrefix: string,\n onSaved: () => void,\n): React.JSX.Element {\n return (\n <ViewDialogs<T>\n saveOpen={ctl.saveOpen}\n onCloseSave={ctl.closeSave}\n currentState={ctl.editing ? ctl.editing.state : ctl.currentRef.current}\n fields={fields}\n columns={columns}\n editing={ctl.editing}\n onSave={async (payload) => {\n await ctl.handleSave(payload);\n // The saved state is the clean one from here on.\n onSaved();\n }}\n manageOpen={ctl.manageOpen}\n onCloseManage={() => ctl.setManageOpen(false)}\n views={views}\n onEditFromManage={ctl.editFromManage}\n onDelete={(view) => void ctl.handleDelete(view)}\n testIdPrefix={testIdPrefix}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/DataViews/data-views-toolbar.tsx"],"sourcesContent":["\"use client\";\n\nimport Divider from \"@mui/material/Divider/index.js\";\n\nimport {\n ContentToolbar,\n FilterTrigger,\n type ColumnVisibilityOption,\n type SortFieldDefinition,\n} from \"../../layout/ContentToolbar\";\nimport { Box } from \"../../../mui/Box\";\nimport { Text } from \"../../typography/Text\";\n\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { DataViewsDisplayPanel, type DisplayPanelView } from \"./data-views-display-panel\";\nimport { DataViewsExportMenu, type DataViewExport } from \"./data-views-export\";\nimport { renderBulkActions } from \"./data-views-grid-helpers\";\nimport type { RowAction } from \"./data-views-types\";\nimport type { DataViewsController } from \"./use-data-views-state\";\n\nexport interface GridToolbarProps<T extends Record<string, unknown>> {\n testIdPrefix: string;\n selectedRows: T[];\n selectAll: () => void;\n clearSelection: () => void;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n sortFields: SortFieldDefinition[];\n activeSortField: string;\n activeSortOrder: \"asc\" | \"desc\";\n onChangeSort: (field: string, order: \"asc\" | \"desc\") => void;\n matchedCount: number;\n totalCount: number;\n toolbarRightSlot?: React.ReactNode;\n columnOptions: ColumnVisibilityOption[];\n onToggleColumn: (id: string, visible: boolean) => void;\n filterOpen: boolean;\n setFilterOpen: (open: boolean) => void;\n activeFilterCount: number;\n /** Hide the \"Filtros\" slide-in trigger (compact layout shows filters inline). */\n showFilterTrigger?: boolean;\n /**\n * Search + filter controls, rendered ON the toolbar line rather than on a row\n * beneath it. Absent ⇒ the toolbar keeps its plain two-cluster shape.\n */\n filterControls?: React.ReactNode;\n /** Measures the toolbar ROW for the filter overflow — see `useFilterOverflow`. */\n barRef?: React.Ref<HTMLDivElement>;\n /** The controller, so \"Exibir\" can drive sort, columns, order and format. */\n c: DataViewsController<T>;\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, when the host has views. */\n displayView?: DisplayPanelView;\n /** Injected export. Absent ⇒ no Exportar control. */\n exportConfig?: DataViewExport;\n /**\n * Step 2 of the degradation ladder: Exibir/Exportar as icons only.\n * MEASURED upstream (see `useFilterOverflow`) rather than switched at a\n * breakpoint, so a two-filter page keeps its labels where a five-filter one\n * has already given them up.\n */\n compactControls?: boolean;\n /**\n * Step 5 of the ladder, and its floor: on a screen too narrow for even the\n * fully-collapsed row, the counter is dropped so the controls still fit one\n * line instead of spilling outside the toolbar.\n */\n counterHidden?: boolean;\n}\n\n/** The right-aligned toolbar controls: Sort By, the counter, zoom/layout/columns, filters. */\nfunction ToolbarRightControls<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {\n const { testIdPrefix, matchedCount, totalCount, filterOpen, setFilterOpen } = props;\n return (\n <>\n {/* MEASURED, never breakpointed: `RESERVED.counter` prices it into the\n ladder, so hiding it at `md` was the ladder and a breakpoint\n disagreeing about the same pixels — which broke the row at exactly\n 900px. It is dropped only as the ladder's last rung. */}\n {!props.counterHidden && (\n <>\n <Text variant=\"caption\" as=\"span\">\n <Box\n component=\"span\"\n data-testid={`${testIdPrefix}-counter`}\n sx={{ whiteSpace: \"nowrap\" }}\n >\n {matchedCount} de {totalCount}\n </Box>\n </Text>\n {/* Divides the READING of the list from the controls that change it —\n the counter states what is on screen, everything right of here\n acts on it. */}\n <Divider\n orientation=\"vertical\"\n flexItem\n sx={{ height: 20, alignSelf: \"center\", mx: 0.5 }}\n />\n </>\n )}\n {props.toolbarRightSlot}\n {/* Sort + columns + format, in ONE control — see DataViewsDisplayPanel. */}\n <DataViewsDisplayPanel\n c={props.c}\n testIdPrefix={testIdPrefix}\n sortKinds={props.sortKinds}\n view={props.displayView}\n compact={props.compactControls}\n />\n {props.exportConfig && (\n <DataViewsExportMenu\n config={props.exportConfig}\n query={props.c.currentQuery}\n totalCount={props.totalCount}\n selectedIds={[...props.c.selectedIds]}\n columns={props.columnOptions.filter((col) => col.visible).map((col) => ({ id: col.id, label: col.label }))}\n testIdPrefix={testIdPrefix}\n compact={props.compactControls}\n />\n )}\n {props.showFilterTrigger !== false && (\n <FilterTrigger\n open={filterOpen}\n onOpenChange={setFilterOpen}\n activeCount={props.activeFilterCount}\n data-testid={`${testIdPrefix}-filters-toggle`}\n />\n )}\n </>\n );\n}\n\n/**\n * The bordered toolbar band: selection chrome + Sort By, the result counter, the\n * saved-views slot, and the filter funnel. The negative margin lets the top/bottom\n * separators reach the sidebar's vertical line and the window edge.\n */\nexport function GridToolbar<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {\n const copy = useDataViewsCopy();\n const { testIdPrefix, selectedRows } = props;\n return (\n <Box\n ref={props.barRef}\n sx={{\n borderTop: 1,\n borderBottom: 1,\n borderColor: \"divider\",\n py: 1.25,\n mx: { xs: -2, md: -3 },\n px: { xs: 2, md: 3 },\n }}\n >\n <ContentToolbar\n selectAllLabel={copy.selection.selectAll}\n selectAllText={copy.selection.selectAllOnPage}\n clearAllText={copy.filters.clearAll}\n hasSelection={selectedRows.length > 0}\n selectedCount={selectedRows.length}\n selectAll={props.selectAll}\n clearSelection={props.clearSelection}\n selectAllTestId={`${testIdPrefix}-select-all`}\n clearAllTestId={`${testIdPrefix}-clear-all`}\n actions={renderBulkActions({\n rowActions: props.rowActions,\n bulkActions: props.bulkActions,\n selectedRows,\n clearSelection: props.clearSelection,\n testIdPrefix,\n })}\n leadingControls={props.filterControls}\n // Selection takes the whole line: no Select All while browsing, and no\n // search/filters/Exibir/Exportar once a row is ticked.\n exclusiveSelection\n rightControls={<ToolbarRightControls {...props} />}\n />\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,OAAO,aAAa;AA+EZ,mBACE,KACE,YAFJ;AATR,SAAS,qBAAwD,OAA+C;AAC9G,QAAM,EAAE,cAAc,cAAc,YAAY,YAAY,cAAc,IAAI;AAC9E,SACE,iCAKG;AAAA,KAAC,MAAM,iBACN,iCACE;AAAA,0BAAC,QAAK,SAAQ,WAAU,IAAG,QACzB;AAAA,QAACA;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,eAAa,GAAG,YAAY;AAAA,UAC5B,IAAI,EAAE,YAAY,SAAS;AAAA,UAE1B;AAAA;AAAA,YAAa;AAAA,YAAK;AAAA;AAAA;AAAA,MACrB,GACF;AAAA,MAIA;AAAA,QAAC;AAAA;AAAA,UACC,aAAY;AAAA,UACZ,UAAQ;AAAA,UACR,IAAI,EAAE,QAAQ,IAAI,WAAW,UAAU,IAAI,IAAI;AAAA;AAAA,MACjD;AAAA,OACF;AAAA,IAED,MAAM;AAAA,IAEP;AAAA,MAAC;AAAA;AAAA,QACC,GAAG,MAAM;AAAA,QACT;AAAA,QACA,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA;AAAA,IACjB;AAAA,IACC,MAAM,gBACL;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM,EAAE;AAAA,QACf,YAAY,MAAM;AAAA,QAClB,aAAa,CAAC,GAAG,MAAM,EAAE,WAAW;AAAA,QACpC,SAAS,MAAM,cAAc,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,EAAE;AAAA,QACzG;AAAA,QACA,SAAS,MAAM;AAAA;AAAA,IACjB;AAAA,IAED,MAAM,sBAAsB,SAC3B;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,cAAc;AAAA,QACd,aAAa,MAAM;AAAA,QACnB,eAAa,GAAG,YAAY;AAAA;AAAA,IAC9B;AAAA,KAEJ;AAEJ;AAOO,SAAS,YAA+C,OAA+C;AAC5G,QAAM,OAAO,iBAAiB;AAC9B,QAAM,EAAE,cAAc,aAAa,IAAI;AACvC,SACE;AAAA,IAACA;AAAA,IAAA;AAAA,MACC,KAAK,MAAM;AAAA,MACX,IAAI;AAAA,QACF,WAAW;AAAA,QACX,cAAc;AAAA,QACd,aAAa;AAAA,QACb,IAAI;AAAA,QACJ,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG;AAAA,QACrB,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE;AAAA,MACrB;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,gBAAgB,KAAK,UAAU;AAAA,UAC/B,eAAe,KAAK,UAAU;AAAA,UAC9B,cAAc,KAAK,QAAQ;AAAA,UAC3B,cAAc,aAAa,SAAS;AAAA,UACpC,eAAe,aAAa;AAAA,UAC5B,WAAW,MAAM;AAAA,UACjB,gBAAgB,MAAM;AAAA,UACtB,iBAAiB,GAAG,YAAY;AAAA,UAChC,gBAAgB,GAAG,YAAY;AAAA,UAC/B,SAAS,kBAAkB;AAAA,YACzB,YAAY,MAAM;AAAA,YAClB,aAAa,MAAM;AAAA,YACnB;AAAA,YACA,gBAAgB,MAAM;AAAA,YACtB;AAAA,UACF,CAAC;AAAA,UACD,iBAAiB,MAAM;AAAA,UAGvB,oBAAkB;AAAA,UAClB,eAAe,oBAAC,wBAAsB,GAAG,OAAO;AAAA;AAAA,MAClD;AAAA;AAAA,EACF;AAEJ;","names":["default"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|