@12-apps/ui 6.14.0 → 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 +2 -2
- package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
- package/dist/_internal/components/data-display/Chart/SpecChart.js +7 -7
- 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 +2 -2
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +46 -46
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +62 -62
- 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 +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +12 -12
- package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +18 -18
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +41 -41
- package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +18 -18
- package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +5 -5
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +9 -9
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +8 -8
- 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 +43 -43
- 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 +133 -131
- 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 +21 -19
- 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 +10 -10
- package/dist/{chunk-WQSL6MCA.js → chunk-23FCBIUN.js} +4 -4
- package/dist/{chunk-QIKTIKO6.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-BPCYXLWY.js → chunk-6HNEEJES.js} +4 -4
- package/dist/{chunk-PHA3NFZM.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-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-O6V7KKW7.js → chunk-CRHQN42I.js} +3 -3
- 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-UENDC45F.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-RPWEXIAW.js → chunk-HEG7JIBM.js} +5 -5
- package/dist/{chunk-J4DDXHLB.js → chunk-HGBZZDP6.js} +4 -4
- package/dist/{chunk-O6MZPB64.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-GNAAHDCN.js → chunk-LDMXHDZ5.js} +2 -2
- 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-ZNGUDGKW.js → chunk-MJOXIENM.js} +4 -4
- package/dist/chunk-N4JEQJBL.js +93 -0
- package/dist/chunk-N4JEQJBL.js.map +1 -0
- package/dist/{chunk-62WEMJV3.js → chunk-NI2ISQZI.js} +3 -3
- package/dist/{chunk-LNIVT62P.js → chunk-NJS4WCHA.js} +15 -15
- package/dist/{chunk-LPNF4YJ7.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-DFLTUI7W.js → chunk-QZBUGUOY.js} +4 -4
- package/dist/{chunk-BLT5ZBVL.js → chunk-RRX6ZTNX.js} +2 -2
- package/dist/{chunk-M6365FGG.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-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-XPS7FWZS.js → chunk-VLNM4BTH.js} +2 -2
- 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-U5RIDMMV.js → chunk-ZPIFVTJA.js} +6 -6
- package/dist/data-display/AsyncStateContainer.js +4 -4
- package/dist/data-display/Badge.js +2 -2
- package/dist/data-display/CardKit.js +15 -15
- package/dist/data-display/Carousel.js +2 -2
- package/dist/data-display/Chart.js +10 -10
- package/dist/data-display/DataGrid.js +2 -2
- package/dist/data-display/DataViews.js +79 -79
- 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 +6 -6
- 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/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/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/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/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-A43SJQYE.js.map +0 -1
- package/dist/chunk-FLSSV4TH.js.map +0 -1
- /package/dist/{chunk-WQSL6MCA.js.map → chunk-23FCBIUN.js.map} +0 -0
- /package/dist/{chunk-QIKTIKO6.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-BPCYXLWY.js.map → chunk-6HNEEJES.js.map} +0 -0
- /package/dist/{chunk-PHA3NFZM.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-O6V7KKW7.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-UENDC45F.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-RPWEXIAW.js.map → chunk-HEG7JIBM.js.map} +0 -0
- /package/dist/{chunk-J4DDXHLB.js.map → chunk-HGBZZDP6.js.map} +0 -0
- /package/dist/{chunk-O6MZPB64.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-GNAAHDCN.js.map → chunk-LDMXHDZ5.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-ZNGUDGKW.js.map → chunk-MJOXIENM.js.map} +0 -0
- /package/dist/{chunk-62WEMJV3.js.map → chunk-NI2ISQZI.js.map} +0 -0
- /package/dist/{chunk-LNIVT62P.js.map → chunk-NJS4WCHA.js.map} +0 -0
- /package/dist/{chunk-LPNF4YJ7.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-DFLTUI7W.js.map → chunk-QZBUGUOY.js.map} +0 -0
- /package/dist/{chunk-BLT5ZBVL.js.map → chunk-RRX6ZTNX.js.map} +0 -0
- /package/dist/{chunk-M6365FGG.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-XPS7FWZS.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
- /package/dist/{chunk-U5RIDMMV.js.map → chunk-ZPIFVTJA.js.map} +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
4
|
+
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
|
5
|
+
import Box from '@mui/material/Box/index.js';
|
|
6
|
+
import ListItemIcon from '@mui/material/ListItemIcon/index.js';
|
|
7
|
+
import ListItemText from '@mui/material/ListItemText/index.js';
|
|
8
|
+
import Menu from '@mui/material/Menu/index.js';
|
|
9
|
+
import MenuItem from '@mui/material/MenuItem/index.js';
|
|
10
|
+
import React, { useState } from 'react';
|
|
11
|
+
|
|
12
|
+
import { HeaderButton } from '../HeaderButton';
|
|
13
|
+
import type { HeaderActionItem, HeaderActionsProps } from './HeaderActions.types';
|
|
14
|
+
|
|
15
|
+
/** Drop the gated-away entries, so everything below can count what is left. */
|
|
16
|
+
function present(
|
|
17
|
+
actions: HeaderActionsProps['actions'],
|
|
18
|
+
): HeaderActionItem[] {
|
|
19
|
+
return actions.filter(
|
|
20
|
+
(action): action is HeaderActionItem => Boolean(action) && (action as HeaderActionItem).visible !== false,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The page header's actions, as ONE control that scales with how many there
|
|
26
|
+
* are: nothing, a button, or a button plus an overflow menu.
|
|
27
|
+
*
|
|
28
|
+
* | actions | renders |
|
|
29
|
+
* |---|---|
|
|
30
|
+
* | 0 | nothing at all — not an empty box, and not a menu with no items |
|
|
31
|
+
* | 1 | that action, as an ordinary `HeaderButton` |
|
|
32
|
+
* | n | the FIRST as a button; the other n−1 inside one dropdown |
|
|
33
|
+
*
|
|
34
|
+
* ## Why the first one stays a button
|
|
35
|
+
*
|
|
36
|
+
* A header whose every action lives behind a menu costs two clicks for the
|
|
37
|
+
* thing the page is FOR — "Novo produto" on a catalog, "Nova categoria" on the
|
|
38
|
+
* categories list. Folding it in with the exports and the reorder screens
|
|
39
|
+
* would treat a merchant's daily action as equal to the one they use monthly.
|
|
40
|
+
* So the array is in PRIORITY order and index 0 keeps its button; everything
|
|
41
|
+
* after it is secondary by the caller's own declaration.
|
|
42
|
+
*
|
|
43
|
+
* ## Why this takes a list and not children
|
|
44
|
+
*
|
|
45
|
+
* The 0/1/n decision is only decidable over data. A component handed JSX can
|
|
46
|
+
* count `React.Children`, but it cannot tell a gated-away action from an
|
|
47
|
+
* absent one, cannot read a label to put in a menu row, and cannot re-render
|
|
48
|
+
* a `<Button>` as a `<MenuItem>` without reaching into its props. Every
|
|
49
|
+
* caller in the estate had therefore hand-written the row, which is how four
|
|
50
|
+
* equally-weighted buttons ended up wrapping the line on a catalog page.
|
|
51
|
+
*
|
|
52
|
+
* ## One element, so the spacing is the component's and not the mount's
|
|
53
|
+
*
|
|
54
|
+
* It renders an `inline-flex` box rather than a fragment. A fragment inherits
|
|
55
|
+
* whatever gap its parent happens to set, and the two mounts here set
|
|
56
|
+
* different ones — a `Dashboard.Header` spaces its children, a
|
|
57
|
+
* `Dashboard.Action` slot does not, which is why the pair of buttons in that
|
|
58
|
+
* slot sat flush against each other. The gap belongs to the control.
|
|
59
|
+
*
|
|
60
|
+
* ## The ids survive the move
|
|
61
|
+
*
|
|
62
|
+
* An action that overflows keeps its `dataTestId` on its `MenuItem`. It is a
|
|
63
|
+
* different element in a different place, and it must still answer to the same
|
|
64
|
+
* selector: otherwise adding a fifth action to a header silently breaks the
|
|
65
|
+
* suite of the action that got pushed out, which is the last place anyone
|
|
66
|
+
* would look.
|
|
67
|
+
*/
|
|
68
|
+
export function HeaderActions({
|
|
69
|
+
actions,
|
|
70
|
+
moreLabel,
|
|
71
|
+
collapseBelow = 'md',
|
|
72
|
+
testIdPrefix = 'header-actions',
|
|
73
|
+
}: HeaderActionsProps): React.JSX.Element | null {
|
|
74
|
+
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
|
75
|
+
const items = present(actions);
|
|
76
|
+
const open = Boolean(anchorEl);
|
|
77
|
+
|
|
78
|
+
// Before the early return would be a conditional hook; after it is the only
|
|
79
|
+
// legal place. Nothing below runs for an empty list anyway.
|
|
80
|
+
const [primary, ...overflow] = items;
|
|
81
|
+
if (!primary) return null;
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 1 }}>
|
|
85
|
+
<HeaderButton
|
|
86
|
+
text={primary.text}
|
|
87
|
+
icon={primary.icon}
|
|
88
|
+
onClick={primary.onClick}
|
|
89
|
+
disabled={primary.disabled}
|
|
90
|
+
variant={primary.variant}
|
|
91
|
+
color={primary.color}
|
|
92
|
+
collapseBelow={collapseBelow}
|
|
93
|
+
dataTestId={primary.dataTestId ?? primary.id}
|
|
94
|
+
/>
|
|
95
|
+
{overflow.length > 0 && (
|
|
96
|
+
<>
|
|
97
|
+
<HeaderButton
|
|
98
|
+
text={moreLabel}
|
|
99
|
+
icon={<MoreHorizIcon fontSize="small" />}
|
|
100
|
+
endIcon={<ExpandMoreIcon fontSize="small" />}
|
|
101
|
+
onClick={(event) => setAnchorEl(event.currentTarget)}
|
|
102
|
+
collapseBelow={collapseBelow}
|
|
103
|
+
aria-haspopup="menu"
|
|
104
|
+
aria-expanded={open}
|
|
105
|
+
dataTestId={`${testIdPrefix}-more-trigger`}
|
|
106
|
+
/>
|
|
107
|
+
<Menu
|
|
108
|
+
anchorEl={anchorEl}
|
|
109
|
+
open={open}
|
|
110
|
+
onClose={() => setAnchorEl(null)}
|
|
111
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
|
112
|
+
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
113
|
+
data-testid={`${testIdPrefix}-more-menu`}
|
|
114
|
+
>
|
|
115
|
+
{overflow.map((action) => (
|
|
116
|
+
<MenuItem
|
|
117
|
+
key={action.id}
|
|
118
|
+
disabled={action.disabled}
|
|
119
|
+
onClick={() => {
|
|
120
|
+
setAnchorEl(null);
|
|
121
|
+
action.onClick?.();
|
|
122
|
+
}}
|
|
123
|
+
data-testid={action.dataTestId ?? action.id}
|
|
124
|
+
>
|
|
125
|
+
<ListItemIcon sx={{ minWidth: 32 }}>{action.icon}</ListItemIcon>
|
|
126
|
+
<ListItemText>{action.text}</ListItemText>
|
|
127
|
+
</MenuItem>
|
|
128
|
+
))}
|
|
129
|
+
</Menu>
|
|
130
|
+
</>
|
|
131
|
+
)}
|
|
132
|
+
</Box>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { HeaderButtonProps } from '../HeaderButton';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One page-header action, declared as DATA rather than composed as an element.
|
|
7
|
+
*
|
|
8
|
+
* That is the whole point of the type. A header that composes its buttons as
|
|
9
|
+
* JSX can only ever render all of them, because nothing can count a fragment's
|
|
10
|
+
* children without walking React internals — so "three actions" and "seven
|
|
11
|
+
* actions" produce the same row, and the seventh button is what wraps the line
|
|
12
|
+
* on a laptop. A list can be measured, so the component can decide.
|
|
13
|
+
*/
|
|
14
|
+
export interface HeaderActionItem {
|
|
15
|
+
/**
|
|
16
|
+
* Stable identity. Used as the React key, and as the `data-testid` fallback
|
|
17
|
+
* so an action that MOVES into the overflow menu keeps the selector it had
|
|
18
|
+
* as a button — a suite driving it by id must not care where it ended up.
|
|
19
|
+
*/
|
|
20
|
+
id: string;
|
|
21
|
+
/** The label. Shown beside the icon as a button; alone in the menu row. */
|
|
22
|
+
text: ReactNode;
|
|
23
|
+
/** Leading icon. Always visible as a button, and in the menu row. */
|
|
24
|
+
icon: ReactNode;
|
|
25
|
+
onClick?: () => void;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Drop this action entirely when false. Present so a caller can declare a
|
|
29
|
+
* permission- or plan-gated action inline, instead of building the array
|
|
30
|
+
* conditionally and losing the reason it is missing.
|
|
31
|
+
*
|
|
32
|
+
* @default true
|
|
33
|
+
*/
|
|
34
|
+
visible?: boolean;
|
|
35
|
+
/** Overrides the `data-testid`, which otherwise falls back to {@link id}. */
|
|
36
|
+
dataTestId?: string;
|
|
37
|
+
/** MUI variant for the PRIMARY rendering. Ignored inside the menu. */
|
|
38
|
+
variant?: HeaderButtonProps['variant'];
|
|
39
|
+
/** MUI color for the PRIMARY rendering. Ignored inside the menu. */
|
|
40
|
+
color?: HeaderButtonProps['color'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Props for {@link HeaderActions}. */
|
|
44
|
+
export interface HeaderActionsProps {
|
|
45
|
+
/**
|
|
46
|
+
* The actions, in priority order — the first is the one that stays a button.
|
|
47
|
+
*
|
|
48
|
+
* `false`/`null`/`undefined` entries are dropped, so a caller can write
|
|
49
|
+
* `[edit, canDelete && del]` without pre-filtering.
|
|
50
|
+
*/
|
|
51
|
+
actions: Array<HeaderActionItem | false | null | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* The overflow trigger's label, which is also its accessible name. REQUIRED:
|
|
54
|
+
* this package ships no copy of its own, in any language.
|
|
55
|
+
*/
|
|
56
|
+
moreLabel: string;
|
|
57
|
+
/** Width below which every button collapses to icon-only. @default 'md' */
|
|
58
|
+
collapseBelow?: HeaderButtonProps['collapseBelow'];
|
|
59
|
+
/**
|
|
60
|
+
* Prefix for the overflow trigger's and menu's own test ids. The ACTIONS
|
|
61
|
+
* keep their own ids either way. @default 'header-actions'
|
|
62
|
+
*/
|
|
63
|
+
testIdPrefix?: string;
|
|
64
|
+
}
|
|
@@ -27,7 +27,13 @@ import { Dashboard } from '@12-apps/ui/layout/Dashboard';
|
|
|
27
27
|
<Dashboard.Settings title="Product settings">In development</Dashboard.Settings>
|
|
28
28
|
<Dashboard.Spacer />
|
|
29
29
|
<Dashboard.Export onExport={(id) => exportAs(id)} />
|
|
30
|
-
<Dashboard.
|
|
30
|
+
<Dashboard.Actions
|
|
31
|
+
moreLabel={copy.moreActions}
|
|
32
|
+
actions={[
|
|
33
|
+
{ id: 'new-product', text: 'New product', icon: <AddIcon fontSize="small" />, onClick: onCreate },
|
|
34
|
+
{ id: 'import', text: 'Import sheet', icon: <UploadIcon fontSize="small" />, onClick: onImport },
|
|
35
|
+
]}
|
|
36
|
+
/>
|
|
31
37
|
</Dashboard.Header>
|
|
32
38
|
<Dashboard.Filters>
|
|
33
39
|
<SearchInput />
|
|
@@ -51,7 +57,8 @@ import { Dashboard } from '@12-apps/ui/layout/Dashboard';
|
|
|
51
57
|
| `Dashboard.Settings` | (in header) | Gear icon. Default: opens a dialog with `children`. With `href` (+ optional `linkComponent`): renders as a link to a settings route (e.g. the page's Configuração section) — no dialog. |
|
|
52
58
|
| `Dashboard.Export` | (in header) | Export dropdown (CSV/Excel/JSON by default); calls `onExport(id)`. |
|
|
53
59
|
| `Dashboard.Spacer` | (in header) | Pushes following controls to the right edge. |
|
|
54
|
-
| `Dashboard.Action` | (in header) | Slot for a
|
|
60
|
+
| `Dashboard.Action` | (in header) | Slot for ONE header control that is not an action — a link, a toggle, a status pill. |
|
|
61
|
+
| `Dashboard.Actions` | (in header) | The header's actions declared as a list. 0 renders nothing, 1 renders a button, n renders the first as a button and the other n−1 in a dropdown. See [HeaderActions](../../form/HeaderActions/HeaderActions.md). |
|
|
55
62
|
| `Dashboard.Filters` | filters | Collapsible search/filter region; visibility driven by `FilterToggle`. |
|
|
56
63
|
| `Dashboard.MoreFilters` | (in filters) | Expandable advanced panel for ranges/dates. |
|
|
57
64
|
| `Dashboard.Body` | body | Main content area (the table/grid). |
|
|
@@ -16,6 +16,7 @@ import React, { useMemo, useState } from 'react';
|
|
|
16
16
|
import { DashboardContext, useDashboardContext } from './DashboardContext';
|
|
17
17
|
import {
|
|
18
18
|
DashboardAction,
|
|
19
|
+
DashboardActions,
|
|
19
20
|
DashboardExport,
|
|
20
21
|
DashboardFilterToggle,
|
|
21
22
|
DashboardInfo,
|
|
@@ -309,6 +310,7 @@ Dashboard.FilterToggle = DashboardFilterToggle;
|
|
|
309
310
|
Dashboard.Settings = DashboardSettings;
|
|
310
311
|
Dashboard.Export = DashboardExport;
|
|
311
312
|
Dashboard.Action = DashboardAction;
|
|
313
|
+
Dashboard.Actions = DashboardActions;
|
|
312
314
|
Dashboard.Filters = DashboardFilters;
|
|
313
315
|
Dashboard.MoreFilters = DashboardMoreFilters;
|
|
314
316
|
Dashboard.Body = DashboardBody;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ElementType, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
+
import type { HeaderActionsProps } from '../../form/HeaderActions';
|
|
4
|
+
|
|
3
5
|
/** A single breadcrumb entry for `<Dashboard.Breadcrumb>`. */
|
|
4
6
|
export interface DashboardBreadcrumbItem {
|
|
5
7
|
/** Visible label. */
|
|
@@ -139,6 +141,16 @@ export interface DashboardActionProps {
|
|
|
139
141
|
children: ReactNode;
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Props for `<Dashboard.Actions>` — the header's actions DECLARED, rather than
|
|
146
|
+
* composed one `<Dashboard.Action>` at a time.
|
|
147
|
+
*
|
|
148
|
+
* `testIdPrefix` is not among them: the Dashboard already has one, from its
|
|
149
|
+
* root, and letting the part carry a second would give one page two answers to
|
|
150
|
+
* "what is this header called".
|
|
151
|
+
*/
|
|
152
|
+
export type DashboardActionsProps = Omit<HeaderActionsProps, 'testIdPrefix'>;
|
|
153
|
+
|
|
142
154
|
/** Props for `<Dashboard.Filters>` — the collapsible search/filter region. */
|
|
143
155
|
export interface DashboardFiltersProps {
|
|
144
156
|
/** Filter controls (search input, pills, `<Dashboard.MoreFilters>`, …). */
|
|
@@ -19,10 +19,12 @@ import Tooltip from '@mui/material/Tooltip/index.js';
|
|
|
19
19
|
import Typography from '@mui/material/Typography/index.js';
|
|
20
20
|
import React, { useState } from 'react';
|
|
21
21
|
|
|
22
|
+
import { HeaderActions } from '../../form/HeaderActions';
|
|
22
23
|
import { HeaderButton } from '../../form/HeaderButton';
|
|
23
24
|
import { useDashboardContext } from './DashboardContext';
|
|
24
25
|
import type {
|
|
25
26
|
DashboardActionProps,
|
|
27
|
+
DashboardActionsProps,
|
|
26
28
|
DashboardExportFormat,
|
|
27
29
|
DashboardExportProps,
|
|
28
30
|
DashboardFilterToggleProps,
|
|
@@ -206,3 +208,37 @@ export const DashboardAction = ({ children }: DashboardActionProps): React.JSX.E
|
|
|
206
208
|
<Box sx={{ display: 'inline-flex' }}>{children}</Box>
|
|
207
209
|
);
|
|
208
210
|
DashboardAction.displayName = 'Dashboard.Action';
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* The header's actions, declared as a LIST — `<Dashboard.Action>`'s plural.
|
|
214
|
+
*
|
|
215
|
+
* `<Dashboard.Action>` is a slot: it renders whatever you hand it, once per
|
|
216
|
+
* action, and a page with five of them draws five equally-loud buttons. That is
|
|
217
|
+
* the right primitive for one button and the wrong one for five, and the pages
|
|
218
|
+
* here that grew a fifth action all grew it the same way — by adding a fifth
|
|
219
|
+
* slot, because the slot was the only thing on offer.
|
|
220
|
+
*
|
|
221
|
+
* This part answers the question the slot cannot: given N actions, how many
|
|
222
|
+
* belong on the bar? See {@link HeaderActions} for the rule (0 ⇒ nothing,
|
|
223
|
+
* 1 ⇒ a button, n ⇒ a button and a menu of the rest).
|
|
224
|
+
*
|
|
225
|
+
* Both stay. A header still composes `<Dashboard.Action>` for the one control
|
|
226
|
+
* that is not an action at all — a link, a toggle, a status pill — and reaches
|
|
227
|
+
* for this when it has actions to rank.
|
|
228
|
+
*/
|
|
229
|
+
export const DashboardActions = ({
|
|
230
|
+
actions,
|
|
231
|
+
moreLabel,
|
|
232
|
+
collapseBelow,
|
|
233
|
+
}: DashboardActionsProps): React.JSX.Element => {
|
|
234
|
+
const { testIdPrefix } = useDashboardContext();
|
|
235
|
+
return (
|
|
236
|
+
<HeaderActions
|
|
237
|
+
actions={actions}
|
|
238
|
+
moreLabel={moreLabel}
|
|
239
|
+
collapseBelow={collapseBelow}
|
|
240
|
+
testIdPrefix={`${testIdPrefix}-actions`}
|
|
241
|
+
/>
|
|
242
|
+
);
|
|
243
|
+
};
|
|
244
|
+
DashboardActions.displayName = 'Dashboard.Actions';
|
|
@@ -4,6 +4,7 @@ export { DashboardContext, useDashboardContext } from './DashboardContext';
|
|
|
4
4
|
export type { DashboardContextValue } from './DashboardContext';
|
|
5
5
|
export type {
|
|
6
6
|
DashboardActionProps,
|
|
7
|
+
DashboardActionsProps,
|
|
7
8
|
DashboardBodyProps,
|
|
8
9
|
DashboardBreadcrumbItem,
|
|
9
10
|
DashboardBreadcrumbProps,
|
|
@@ -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/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":"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","names":[]}
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|