@v-miniapp/ui-react 1.0.45 → 1.0.59
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/dist/components/app/app.d.ts +17 -0
- package/dist/components/app/bottom-tab-bar-layout/hook.d.ts +21 -0
- package/dist/components/app/bottom-tab-bar-layout/store.d.ts +13 -0
- package/dist/components/app/bottom-tab-bar-layout/type.d.ts +13 -0
- package/dist/components/app/data-theme.d.ts +8 -0
- package/dist/components/app/index.d.ts +9 -18
- package/dist/components/app/navigation-bar-layout/hook.d.ts +17 -0
- package/dist/components/app/navigation-bar-layout/store.d.ts +13 -0
- package/dist/components/app/navigation-bar-layout/type.d.ts +7 -0
- package/dist/components/app/page-layout/hook.d.ts +21 -0
- package/dist/components/app/page-layout/store.d.ts +13 -0
- package/dist/components/app/page-layout/type.d.ts +8 -0
- package/dist/components/app/type.d.ts +27 -0
- package/dist/components/calendar/default-render.d.ts +1 -1
- package/dist/components/calendar/utils.d.ts +1 -1
- package/dist/components/carousel/index.d.ts +1 -0
- package/dist/components/input-wrapper/input-wrapper.d.ts +2 -2
- package/dist/components/layout/page.d.ts +8 -1
- package/dist/external/index.js +11344 -7959
- package/dist/external/styles.css +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4194 -4376
- package/dist/styles.css +1 -1
- package/dist/utils/event-emitter.d.ts +4 -0
- package/dist-storybook/assets/App-Dp1UG-xp.js +93 -0
- package/dist-storybook/assets/{Color-AVL7NMMY-1_8XTICv.js → Color-AVL7NMMY-XA8cFKdV.js} +1 -1
- package/dist-storybook/assets/DEEPLINK-cjgFMuRJ.js +33 -0
- package/dist-storybook/assets/{DocsRenderer-PQXLIZUC-BO86igwd.js → DocsRenderer-PQXLIZUC-D10-0Yfb.js} +2 -2
- package/dist-storybook/assets/EVENTS-BY66PjI7.js +65 -0
- package/dist-storybook/assets/GETTING_STARTED-580o-9Mx.js +64 -0
- package/dist-storybook/assets/GETTING_STARTED-BiQMvjvo.js +62 -0
- package/dist-storybook/assets/GETTING_STARTED-CIVMqKZW.js +80 -0
- package/dist-storybook/assets/{INFINITE_SCROLL-BtM3uoX0.js → INFINITE_SCROLL-BbeR5HeP.js} +1 -1
- package/dist-storybook/assets/LocalesProvider-CMlmwAyY.js +53 -0
- package/dist-storybook/assets/MIGRATE_DARKMODE_TO_THEME-CBDyZyg2.js +107 -0
- package/dist-storybook/assets/{MIGRATION_GUIDE-2LONslE4.js → MIGRATION_GUIDE-FZyRWI-B.js} +3 -3
- package/dist-storybook/assets/OVERVIEW-C9_6gX5Q.js +51 -0
- package/dist-storybook/assets/Router-B5U8bubH.js +71 -0
- package/dist-storybook/assets/{TAILWIND_INTEGRATION-_T-VfvkM.js → TAILWIND_INTEGRATION-BJdy5DAv.js} +1 -1
- package/dist-storybook/assets/THEME-CRbvH7KT.js +103 -0
- package/dist-storybook/assets/_baseClone-DQVxEhny.js +1 -0
- package/dist-storybook/assets/alert-CKwsuaPI.js +1 -0
- package/dist-storybook/assets/{alert.stories-B-vuojPh.js → alert.stories-D0X5wUHk.js} +3 -3
- package/dist-storybook/assets/app-CTv8lFU3.js +1 -0
- package/dist-storybook/assets/avatar-rWcYGe6j.js +1 -0
- package/dist-storybook/assets/{avatar.stories-KYFztAc8.js → avatar.stories-8lrbhMma.js} +6 -6
- package/dist-storybook/assets/{axe-CmvD4WV5.js → axe-BHGdSCoA.js} +1 -1
- package/dist-storybook/assets/badge-VcjGVEum.js +1 -0
- package/dist-storybook/assets/{badge.stories-Be2ItCmQ.js → badge.stories-BEFNaUA1.js} +3 -3
- package/dist-storybook/assets/{blocks-BuaOUtiH.js → blocks-DKR3P4qW.js} +3 -3
- package/dist-storybook/assets/{bottom-tab-bar-CtcTAxuI.js → bottom-tab-bar-B6IAoRwz.js} +1 -1
- package/dist-storybook/assets/{bottom-tab-bar.stories-CDmEve6z.js → bottom-tab-bar.stories-DXzLlO5o.js} +3 -3
- package/dist-storybook/assets/button-DJH3RlJl.js +1 -0
- package/dist-storybook/assets/{button.stories-CaqLWQiY.js → button.stories-DgYDJ6x7.js} +3 -3
- package/dist-storybook/assets/calendar-C4Xe_TW2.js +1 -0
- package/dist-storybook/assets/{calendar.stories-DLWZldet.js → calendar.stories-IVvRAjWN.js} +3 -3
- package/dist-storybook/assets/carousel-DJlgMyS5.js +37 -0
- package/dist-storybook/assets/{carousel.stories-B8YbGOOr.js → carousel.stories-3rA3nxdL.js} +3 -3
- package/dist-storybook/assets/checkbox-JOxcmyCZ.js +1 -0
- package/dist-storybook/assets/{checkbox.stories-CLvfZPiw.js → checkbox.stories-ge3pgfBb.js} +3 -3
- package/dist-storybook/assets/chip-Crt60rph.js +1 -0
- package/dist-storybook/assets/{chip.stories-BbwJb5eD.js → chip.stories-D7E6fdiV.js} +3 -3
- package/dist-storybook/assets/{date-Cg-Uk_pp.js → date-B3PFMb6s.js} +1 -1
- package/dist-storybook/assets/date-field-range-B-sv9nbW.js +1 -0
- package/dist-storybook/assets/date-field.stories-B9G2heHt.js +129 -0
- package/dist-storybook/assets/date-picker-BPzKPdhO.js +1 -0
- package/dist-storybook/assets/{date-picker.stories-BuGWvzFL.js → date-picker.stories-CIFgk4q_.js} +3 -3
- package/dist-storybook/assets/dialog-BAfGQzk5.js +1 -0
- package/dist-storybook/assets/{dialog.stories-DJ0WsSkA.js → dialog.stories-vDMKz9Tw.js} +3 -3
- package/dist-storybook/assets/{chip-kG4p82WT.js → dropdown-Dtomaqpw.js} +2 -2
- package/dist-storybook/assets/{dropdown.stories-D6JUYP73.js → dropdown.stories-Cj0HM0VI.js} +3 -3
- package/dist-storybook/assets/{embla-carousel-react.esm-BYjpaHZ9.js → embla-carousel-react.esm-5D5fs7OQ.js} +1 -1
- package/dist-storybook/assets/icon-CdiFzFyf.js +1 -0
- package/dist-storybook/assets/{icon.stories-B-ZvRzFf.js → icon.stories-DWwbUUY-.js} +3 -3
- package/dist-storybook/assets/iframe-BHaCv4dM.css +1 -0
- package/dist-storybook/assets/{iframe-CQAwSt4E.js → iframe-DfPay7Zl.js} +42 -42
- package/dist-storybook/assets/image-CMKb-R3x.js +9 -0
- package/dist-storybook/assets/{image.stories-C4l8D3ju.js → image.stories-BhZU057W.js} +3 -3
- package/dist-storybook/assets/index-BWpuenI4.js +1 -0
- package/dist-storybook/assets/{index-CgMRTj-o.js → index-DqZh6B0b.js} +1 -1
- package/dist-storybook/assets/{index-BV0AJWP6.js → index-EGt7xBnA.js} +1 -1
- package/dist-storybook/assets/{index-DHiZ-gXR.js → index-cMNObl2z.js} +1 -1
- package/dist-storybook/assets/input-wrapper-CgaUwbbE.js +1 -0
- package/dist-storybook/assets/{label-DV2iCDmN.js → label-D44azUgi.js} +1 -1
- package/dist-storybook/assets/{label.stories-BwTIPFXX.js → label.stories-CXJjdYf_.js} +3 -3
- package/dist-storybook/assets/{navigation-bar-vI-FPasP.js → navigation-bar-DK3TxcTu.js} +2 -2
- package/dist-storybook/assets/{navigation-bar.stories-DYuFaJFD.js → navigation-bar.stories-CB3Kg-sH.js} +3 -3
- package/dist-storybook/assets/number-field-Bz7su9S1.js +1 -0
- package/dist-storybook/assets/{number-field.stories--fn26TJu.js → number-field.stories-DSxPSzLv.js} +3 -3
- package/dist-storybook/assets/omit-BWHsnDSR.js +1 -0
- package/dist-storybook/assets/option-item-CpeNcb5w.js +1 -0
- package/dist-storybook/assets/{option-item.stories-snjAvgay.js → option-item.stories-BvXoc8WX.js} +3 -3
- package/dist-storybook/assets/pagination-Cp-DHO4Q.js +1 -0
- package/dist-storybook/assets/{pagination.stories-BoEs0jzS.js → pagination.stories-_5qj2nTS.js} +4 -4
- package/dist-storybook/assets/proxy-B4G9nIBd.js +1 -0
- package/dist-storybook/assets/radio-D0aV0RIg.js +1 -0
- package/dist-storybook/assets/{radio.stories-DuN-Awi_.js → radio.stories-BNR-wwuw.js} +3 -3
- package/dist-storybook/assets/rating-D2e8RTGl.js +1 -0
- package/dist-storybook/assets/{rating.stories-BCcQjMEx.js → rating.stories-CI0LG0Qq.js} +3 -3
- package/dist-storybook/assets/{react-18-CNyWQ7je.js → react-18-C7pDmBBf.js} +1 -1
- package/dist-storybook/assets/{react-hufnxGVs.js → react-I9jCW2VV.js} +1 -1
- package/dist-storybook/assets/search-field-DINESW8Y.js +1 -0
- package/dist-storybook/assets/{search-field.stories-DiCZbhng.js → search-field.stories-CKXC6-Za.js} +3 -3
- package/dist-storybook/assets/section-content-D49PabBW.js +1 -0
- package/dist-storybook/assets/{section.stories-C2I_kKhu.js → section.stories-9vd48AgB.js} +3 -3
- package/dist-storybook/assets/sheet-footer-nEdxsYan.js +1 -0
- package/dist-storybook/assets/{sheet.stories-wk1JaKU5.js → sheet.stories-C3gLIQsn.js} +3 -3
- package/dist-storybook/assets/skeleton-B12XbNAJ.js +1 -0
- package/dist-storybook/assets/{skeleton.stories-BCmX-VNr.js → skeleton.stories-C0y1o1Y_.js} +3 -3
- package/dist-storybook/assets/{store-D2RudmNr.js → store-Ce3Ikv5g.js} +5 -5
- package/dist-storybook/assets/switch-D0Z9tWin.js +1 -0
- package/dist-storybook/assets/{switch.stories-BqPLNKB9.js → switch.stories-BdWFln-M.js} +3 -3
- package/dist-storybook/assets/{tab-bar-CSeCmtIZ.js → tab-bar-kExoGg5P.js} +1 -1
- package/dist-storybook/assets/{tab-bar.stories-Cb6v8H2w.js → tab-bar.stories-BgDXX0of.js} +3 -3
- package/dist-storybook/assets/text-area-GKy5HL12.js +1 -0
- package/dist-storybook/assets/{text-area.stories-By8bCfgc.js → text-area.stories-DCt3RB3A.js} +3 -3
- package/dist-storybook/assets/text-field-CGWNqitB.js +1 -0
- package/dist-storybook/assets/{text-field.stories-CrWBAhvI.js → text-field.stories-Bqv7f948.js} +3 -3
- package/dist-storybook/assets/toast-provider-DKSrfhJD.js +9 -0
- package/dist-storybook/assets/{toast.stories-iWAToAZA.js → toast.stories-CcFzS6QI.js} +1 -1
- package/dist-storybook/assets/tooltip-B9rDI6z9.js +1 -0
- package/dist-storybook/assets/{tooltip.stories-RC6SuPPD.js → tooltip.stories-DDdsuU3U.js} +3 -3
- package/dist-storybook/assets/typography-CB8hPDyK.js +1 -0
- package/dist-storybook/assets/{typography.stories-Bu8qFugR.js → typography.stories-BzCxaZQU.js} +3 -3
- package/dist-storybook/assets/{uploader.stories-B2wW9qVy.js → uploader.stories-izVumFqZ.js} +3 -3
- package/dist-storybook/assets/use-app-pause-ClsUnndr.js +21 -0
- package/dist-storybook/assets/use-app-resume-D_EcIvMd.js +21 -0
- package/dist-storybook/assets/use-bottom-tab-bar-BC1cz2uE.js +49 -0
- package/dist-storybook/assets/use-custom-icon-event-cUk4Md0Y.js +26 -0
- package/dist-storybook/assets/use-did-hide-BmABiaUE.js +30 -0
- package/dist-storybook/assets/use-did-show-CQuySkkT.js +30 -0
- package/dist-storybook/assets/use-histories-CBm09Lno.js +30 -0
- package/dist-storybook/assets/use-history-7yguNz6O.js +33 -0
- package/dist-storybook/assets/use-language-DPyWMce2.js +46 -0
- package/dist-storybook/assets/use-load-more-KlDJZhj2.js +42 -0
- package/dist-storybook/assets/use-location-C7kE1yla.js +39 -0
- package/dist-storybook/assets/use-navigate-BpIyvtwc.js +36 -0
- package/dist-storybook/assets/use-navigation-bar-guzwhM_u.js +42 -0
- package/dist-storybook/assets/use-navigation-type-DOndDqQH.js +27 -0
- package/dist-storybook/assets/use-page-layout-dO6ylI1b.js +37 -0
- package/dist-storybook/assets/use-page-scroll-CCG2d2Gb.js +42 -0
- package/dist-storybook/assets/use-pull-to-refresh-lhumDu1H.js +38 -0
- package/dist-storybook/assets/use-settings-changed-Bt58DJ-c.js +30 -0
- package/dist-storybook/assets/use-translate-Jhz6jTXo.js +59 -0
- package/dist-storybook/assets/{visibility-sensor-CwrzJO06.js → visibility-sensor-Jf-Nmil6.js} +1 -1
- package/dist-storybook/iframe.html +2 -2
- package/dist-storybook/index.json +1 -1
- package/dist-storybook/project.json +1 -1
- package/dist-storybook/sb-addons/a11y-2/manager-bundle.js +2 -2
- package/dist-storybook/sb-addons/docs-1/manager-bundle.js +2 -2
- package/dist-storybook/sb-addons/storybook-build-3/manager-bundle.js +1 -1
- package/dist-storybook/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +4 -4
- package/dist-storybook/stories-data.json +152 -122
- package/package.json +3 -1
- package/dist/components/app/components/app.d.ts +0 -13
- package/dist/components/app/components/link.d.ts +0 -8
- package/dist/components/app/components/navigation-analytic.d.ts +0 -2
- package/dist/components/app/components/pages-render.d.ts +0 -2
- package/dist/components/app/context/location-key.d.ts +0 -4
- package/dist/components/app/hooks/use-app-pause.d.ts +0 -1
- package/dist/components/app/hooks/use-app-resume.d.ts +0 -1
- package/dist/components/app/hooks/use-app-state.d.ts +0 -7
- package/dist/components/app/hooks/use-bottom-tab-bar.d.ts +0 -13
- package/dist/components/app/hooks/use-did-hide.d.ts +0 -1
- package/dist/components/app/hooks/use-did-show.d.ts +0 -1
- package/dist/components/app/hooks/use-history.d.ts +0 -2
- package/dist/components/app/hooks/use-location.d.ts +0 -1
- package/dist/components/app/hooks/use-navigate.d.ts +0 -1
- package/dist/components/app/hooks/use-navigation-bar.d.ts +0 -12
- package/dist/components/app/hooks/use-navigation-type.d.ts +0 -1
- package/dist/components/app/hooks/use-page-config.d.ts +0 -1
- package/dist/components/app/hooks/use-page-layout.d.ts +0 -14
- package/dist/components/app/hooks/use-page-scroll.d.ts +0 -5
- package/dist/components/app/hooks/use-page-state.d.ts +0 -6
- package/dist/components/app/stores/app.d.ts +0 -24
- package/dist/components/app/stores/app.selector.d.ts +0 -11
- package/dist/components/app/types/app.d.ts +0 -55
- package/dist/components/app/types/navigation.d.ts +0 -30
- package/dist/components/app/utils/animation.d.ts +0 -2
- package/dist/components/app/utils/data-theme.d.ts +0 -5
- package/dist/components/app/utils/history.d.ts +0 -7
- package/dist/hooks/use-analytic.d.ts +0 -1
- package/dist/hooks/use-is-using-app.d.ts +0 -1
- package/dist/hooks/use-is-using-locales.d.ts +0 -1
- package/dist/locales/defaultResources/en.d.ts +0 -27
- package/dist/locales/defaultResources/vi.d.ts +0 -27
- package/dist/locales/fns.d.ts +0 -6
- package/dist/locales/hooks.d.ts +0 -9
- package/dist/locales/index.d.ts +0 -4
- package/dist/locales/provider.d.ts +0 -6
- package/dist/locales/store.d.ts +0 -13
- package/dist/locales/types.d.ts +0 -37
- package/dist/locales/utils.d.ts +0 -2
- package/dist-storybook/assets/ANIMATION-CUdn1GTK.js +0 -99
- package/dist-storybook/assets/APP_FRAMEWORK-ljbIOHYd.js +0 -197
- package/dist-storybook/assets/BOTTOM_TAB_BAR-DxCwCfBK.js +0 -175
- package/dist-storybook/assets/CUSTOM_ERROR_BOUNDARY-B4wTQNZc.js +0 -250
- package/dist-storybook/assets/DARK_MODE-CoHseCDO.js +0 -57
- package/dist-storybook/assets/GETTING_STARTED-H_vVi5cv.js +0 -77
- package/dist-storybook/assets/KEEP_ALIVE-CL2au0al.js +0 -126
- package/dist-storybook/assets/LOCALE-XTCey55y.js +0 -465
- package/dist-storybook/assets/MOBILE_BEHAVIOURS-DZ6alKTX.js +0 -177
- package/dist-storybook/assets/PAGE_LAYOUT-BuOpN-1Y.js +0 -192
- package/dist-storybook/assets/ROUTING_NAVIGATION-BCPHXNto.js +0 -335
- package/dist-storybook/assets/_setToString-CbM921C9.js +0 -1
- package/dist-storybook/assets/alert-DLW8CoyB.js +0 -1
- package/dist-storybook/assets/avatar-GxcYPA1p.js +0 -1
- package/dist-storybook/assets/badge-D_LzMVtw.js +0 -1
- package/dist-storybook/assets/button-CL7GeC23.js +0 -1
- package/dist-storybook/assets/calendar-dOCsjhVU.js +0 -1
- package/dist-storybook/assets/carousel-1Kww3hIz.js +0 -37
- package/dist-storybook/assets/checkbox-MGytNNRt.js +0 -1
- package/dist-storybook/assets/classname-CUR_zgkh.js +0 -1
- package/dist-storybook/assets/date-field.stories-Diptwqfv.js +0 -129
- package/dist-storybook/assets/date-picker-Dnq_-0Md.js +0 -1
- package/dist-storybook/assets/icon-DdQsMyRa.js +0 -1
- package/dist-storybook/assets/iframe-yMKl6hJA.css +0 -1
- package/dist-storybook/assets/image-C3EsNRhz.js +0 -9
- package/dist-storybook/assets/input-wrapper-BKHgnPy6.js +0 -1
- package/dist-storybook/assets/number-field-CXKmnfKe.js +0 -1
- package/dist-storybook/assets/omit-Bsx5nTI0.js +0 -1
- package/dist-storybook/assets/option-item-LRh_OyV4.js +0 -1
- package/dist-storybook/assets/pagination-DZHoBs_4.js +0 -1
- package/dist-storybook/assets/pick-BhmhLmLe.js +0 -1
- package/dist-storybook/assets/radio-B5NJxG_l.js +0 -1
- package/dist-storybook/assets/rating-BdXViYBv.js +0 -1
- package/dist-storybook/assets/search-field-CQqgFbfg.js +0 -1
- package/dist-storybook/assets/section-content-DGNB4eLN.js +0 -1
- package/dist-storybook/assets/skeleton-C91JgehG.js +0 -1
- package/dist-storybook/assets/store-CPumdfcU.js +0 -1
- package/dist-storybook/assets/switch-p-aXI-ev.js +0 -1
- package/dist-storybook/assets/text-area-DwSXyqOe.js +0 -1
- package/dist-storybook/assets/text-field-jK6rpOo2.js +0 -1
- package/dist-storybook/assets/toast-provider-DurnMJhd.js +0 -9
- package/dist-storybook/assets/tooltip-QDdel5My.js +0 -1
- package/dist-storybook/assets/typography-DEpAJl_i.js +0 -1
- package/dist-storybook/assets/use-app-pause-B_tWHKJK.js +0 -29
- package/dist-storybook/assets/use-app-resume--900G-dV.js +0 -29
- package/dist-storybook/assets/use-custom-icon-event-3VExRzvC.js +0 -29
- package/dist-storybook/assets/use-did-hide-BUsL73ab.js +0 -48
- package/dist-storybook/assets/use-did-show-C1-VLDxi.js +0 -49
- package/dist-storybook/assets/use-histories-E4E2jJEY.js +0 -50
- package/dist-storybook/assets/use-history-o1im8IDj.js +0 -67
- package/dist-storybook/assets/use-location-CUEaBO4P.js +0 -56
- package/dist-storybook/assets/use-navigate-C4CTuFSZ.js +0 -84
- package/dist-storybook/assets/use-navigation-type-Dcz4hgKo.js +0 -44
- package/dist-storybook/assets/use-page-config-DSJBVQbq.js +0 -48
- package/dist-storybook/assets/use-page-scroll-dY-U1Vv4.js +0 -69
- package/dist-storybook/assets/use-page-state-CtNpwGPN.js +0 -79
- package/dist-storybook/assets/use-settings-changed-BBJwIHTE.js +0 -29
- /package/dist/components/app/{components/bottom-tab-bar.d.ts → bottom-tab-bar-layout/index.d.ts} +0 -0
- /package/dist/components/app/{components/navigation-bar.d.ts → navigation-bar-layout/index.d.ts} +0 -0
- /package/dist/components/app/{components/page-layout.d.ts → page-layout/index.d.ts} +0 -0
- /package/dist/{components/app/hooks → hooks}/use-custom-icon-event.d.ts +0 -0
- /package/dist/{components/app/hooks → hooks}/use-settings-changed.d.ts +0 -0
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import{j as n}from"./iframe-CQAwSt4E.js";import{useMDXComponents as o}from"./index-CgMRTj-o.js";import{b as a,M as r}from"./blocks-BuaOUtiH.js";import"./preload-helper-PPVm8Dsz.js";import"./index-DHiZ-gXR.js";function i(e){const t={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...o(),...e.components};return n.jsxs(n.Fragment,{children:[`
|
|
2
|
-
`,`
|
|
3
|
-
`,n.jsx(a,{title:"App Framework/Bottom Tab Bar"}),`
|
|
4
|
-
`,n.jsx(t.h1,{id:"bottom-tab-bar",children:"Bottom Tab Bar"}),`
|
|
5
|
-
`,n.jsx(t.p,{children:"Bottom Tab Bar config cho phép bạn cấu hình thanh điều hướng ở cuối màn hình với các tab items."}),`
|
|
6
|
-
`,n.jsx(t.h2,{id:"cấu-trúc",children:"Cấu trúc"}),`
|
|
7
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-typescript",children:`type IAppBottomTabBarState = Partial<
|
|
8
|
-
Omit<IBottomTabBarProps, 'activeId' | 'items'>
|
|
9
|
-
> & {
|
|
10
|
-
items: Array<
|
|
11
|
-
IBottomTabBarItem & { path: string; params?: Record<string, string> }
|
|
12
|
-
>
|
|
13
|
-
hidden?: boolean
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
type IBottomTabBarItem = {
|
|
17
|
-
id: string
|
|
18
|
-
name: string
|
|
19
|
-
icon?: IIconProps | ReactNode
|
|
20
|
-
activeIcon?: IIconProps | ReactNode
|
|
21
|
-
}
|
|
22
|
-
`})}),`
|
|
23
|
-
`,n.jsx(t.h2,{id:"thuộc-tính",children:"Thuộc tính"}),`
|
|
24
|
-
`,n.jsx(r,{children:"\n| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |\n| :--- | :--- | :--- | :--- |\n| `items` | <code>Array<IBottomTabBarItem & {<br/> path: string;<br/> params?: Record<string, string><br/>}></code> | - | Mảng tab items (mỗi item có `id`, `name`, `path`) |\n| `hidden` | `boolean` | `false` | Không render bottom tab bar (không có trong DOM) |\n| `indicator` | `boolean` | `true` | Hiển thị indicator bar cho tab active |\n| `setCssVariable` | `boolean` | - | Set CSS variable `--vsf-bottom-tab-bar-height` |\n| `bgColor` | `IColor` | - | Màu nền của tab bar |\n| `color` | `IColor` | - | Màu text và icon cho các tab không active |\n| `activeColor` | `IColor` | - | Màu text và icon cho tab active |\n| `safeAreaBottomOffset` | `boolean` | `true` | Thêm safe area bottom inset padding |\n| `onItemClick` | `(item, index) => void` | - | Callback khi click vào tab item |\n| `className` | `string` | - | CSS class name tùy chỉnh |\n| `...props` | `ComponentProps<'div'>` | - | Tất cả props HTML div chuẩn |\n"}),`
|
|
25
|
-
`,n.jsx(t.h2,{id:"cách-hoạt-động",children:"Cách hoạt động"}),`
|
|
26
|
-
`,n.jsxs(t.ol,{children:[`
|
|
27
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Items với path"}),": Mỗi item trong ",n.jsx(t.code,{children:"items"})," phải có ",n.jsx(t.code,{children:"path"})," để navigate khi click"]}),`
|
|
28
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Page linking"}),": Page phải có ",n.jsx(t.code,{children:"bottomTabBarId"})," khớp với ",n.jsx(t.code,{children:"id"})," của item để bottom tab bar hiển thị"]}),`
|
|
29
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Active state"}),": Tab bar tự động highlight tab có ",n.jsx(t.code,{children:"id"})," khớp với ",n.jsx(t.code,{children:"bottomTabBarId"})," của page hiện tại"]}),`
|
|
30
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Navigation"}),": Khi click vào tab, sẽ navigate đến ",n.jsx(t.code,{children:"path"})," của item đó"]}),`
|
|
31
|
-
`]}),`
|
|
32
|
-
`,n.jsx(t.h2,{id:"cấu-hình",children:"Cấu hình"}),`
|
|
33
|
-
`,n.jsx(t.h3,{id:"app-level-config",children:"App-level Config"}),`
|
|
34
|
-
`,n.jsx(t.p,{children:"Cấu hình bottom tab bar mặc định:"}),`
|
|
35
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-tsx",children:`import { HomeIcon, SettingsIcon } from '@ant-design/icons'
|
|
36
|
-
|
|
37
|
-
const appConfig: IAppConfig = {
|
|
38
|
-
bottomTabBar: {
|
|
39
|
-
items: [
|
|
40
|
-
{
|
|
41
|
-
id: 'home',
|
|
42
|
-
name: 'Trang chủ',
|
|
43
|
-
icon: <HomeIcon />,
|
|
44
|
-
path: '/home',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: 'settings',
|
|
48
|
-
name: 'Cài đặt',
|
|
49
|
-
icon: <SettingsIcon />,
|
|
50
|
-
path: '/settings',
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
indicator: true,
|
|
54
|
-
safeAreaBottomOffset: true,
|
|
55
|
-
},
|
|
56
|
-
pages: [
|
|
57
|
-
{
|
|
58
|
-
pathname: '/home',
|
|
59
|
-
Component: HomePage,
|
|
60
|
-
bottomTabBarId: 'home', // Link với bottom tab bar item
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
pathname: '/settings',
|
|
64
|
-
Component: SettingsPage,
|
|
65
|
-
bottomTabBarId: 'settings',
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
}
|
|
69
|
-
`})}),`
|
|
70
|
-
`,n.jsx(t.h3,{id:"page-level-config",children:"Page-level Config"}),`
|
|
71
|
-
`,n.jsx(t.p,{children:"Override bottom tab bar cho từng page:"}),`
|
|
72
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-tsx",children:`const appConfig: IAppConfig = {
|
|
73
|
-
bottomTabBar: {
|
|
74
|
-
items: [
|
|
75
|
-
{ id: 'home', name: 'Home', path: '/home' },
|
|
76
|
-
{ id: 'settings', name: 'Settings', path: '/settings' },
|
|
77
|
-
],
|
|
78
|
-
},
|
|
79
|
-
pages: [
|
|
80
|
-
{
|
|
81
|
-
pathname: '/home',
|
|
82
|
-
Component: HomePage,
|
|
83
|
-
bottomTabBarId: 'home',
|
|
84
|
-
// Override bottom tab bar cho page này
|
|
85
|
-
bottomTabBar: {
|
|
86
|
-
hidden: false,
|
|
87
|
-
indicator: false, // Tắt indicator cho page này
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
pathname: '/settings',
|
|
92
|
-
Component: SettingsPage,
|
|
93
|
-
bottomTabBarId: 'settings',
|
|
94
|
-
// Ẩn bottom tab bar cho page này
|
|
95
|
-
bottomTabBar: {
|
|
96
|
-
hidden: true,
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
}
|
|
101
|
-
`})}),`
|
|
102
|
-
`,n.jsx(t.h2,{id:"ví-dụ-với-icons",children:"Ví dụ với Icons"}),`
|
|
103
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-tsx",children:`import {
|
|
104
|
-
HomeOutlined,
|
|
105
|
-
HomeFilled,
|
|
106
|
-
SettingOutlined,
|
|
107
|
-
SettingFilled,
|
|
108
|
-
} from '@ant-design/icons'
|
|
109
|
-
|
|
110
|
-
const appConfig: IAppConfig = {
|
|
111
|
-
bottomTabBar: {
|
|
112
|
-
items: [
|
|
113
|
-
{
|
|
114
|
-
id: 'home',
|
|
115
|
-
name: 'Trang chủ',
|
|
116
|
-
icon: <HomeOutlined />, // Icon khi không active
|
|
117
|
-
activeIcon: <HomeFilled />, // Icon khi active
|
|
118
|
-
path: '/home',
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
id: 'settings',
|
|
122
|
-
name: 'Cài đặt',
|
|
123
|
-
icon: <SettingOutlined />,
|
|
124
|
-
activeIcon: <SettingFilled />,
|
|
125
|
-
path: '/settings',
|
|
126
|
-
},
|
|
127
|
-
],
|
|
128
|
-
},
|
|
129
|
-
pages: [
|
|
130
|
-
{
|
|
131
|
-
pathname: '/home',
|
|
132
|
-
Component: HomePage,
|
|
133
|
-
bottomTabBarId: 'home',
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
pathname: '/settings',
|
|
137
|
-
Component: SettingsPage,
|
|
138
|
-
bottomTabBarId: 'settings',
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
}
|
|
142
|
-
`})}),`
|
|
143
|
-
`,n.jsx(t.h2,{id:"ví-dụ-với-styling",children:"Ví dụ với Styling"}),`
|
|
144
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-tsx",children:`const appConfig: IAppConfig = {
|
|
145
|
-
bottomTabBar: {
|
|
146
|
-
items: [
|
|
147
|
-
{ id: 'home', name: 'Home', path: '/home' },
|
|
148
|
-
{ id: 'settings', name: 'Settings', path: '/settings' },
|
|
149
|
-
],
|
|
150
|
-
bgColor: '#ffffff',
|
|
151
|
-
color: '#666666',
|
|
152
|
-
activeColor: '#1890ff',
|
|
153
|
-
indicator: true,
|
|
154
|
-
},
|
|
155
|
-
pages: [
|
|
156
|
-
// ...
|
|
157
|
-
],
|
|
158
|
-
}
|
|
159
|
-
`})}),`
|
|
160
|
-
`,n.jsx(t.h2,{id:"lưu-ý",children:"Lưu ý"}),`
|
|
161
|
-
`,n.jsxs(t.ul,{children:[`
|
|
162
|
-
`,n.jsxs(t.li,{children:[n.jsxs(t.strong,{children:["Bottom tab bar chỉ hiển thị khi page có ",n.jsx(t.code,{children:"bottomTabBarId"})]}),": Nếu page không có ",n.jsx(t.code,{children:"bottomTabBarId"})," hoặc ",n.jsx(t.code,{children:"bottomTabBarId"})," không khớp với bất kỳ item nào, bottom tab bar sẽ không hiển thị"]}),`
|
|
163
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Path matching"}),": ",n.jsx(t.code,{children:"path"})," trong item phải khớp với ",n.jsx(t.code,{children:"pathname"})," của page để navigation hoạt động đúng"]}),`
|
|
164
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Params"}),": Bạn có thể thêm ",n.jsx(t.code,{children:"params"})," vào item để truyền query parameters khi navigate:",`
|
|
165
|
-
`,n.jsx(t.pre,{children:n.jsx(t.code,{className:"language-tsx",children:`{
|
|
166
|
-
id: 'detail',
|
|
167
|
-
name: 'Detail',
|
|
168
|
-
path: '/detail',
|
|
169
|
-
params: { id: '123' }, // Navigate đến /detail?id=123
|
|
170
|
-
}
|
|
171
|
-
`})}),`
|
|
172
|
-
`]}),`
|
|
173
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Hidden"}),": Khi ",n.jsx(t.code,{children:"hidden: true"}),", bottom tab bar sẽ không được render (không có trong DOM)"]}),`
|
|
174
|
-
`,n.jsxs(t.li,{children:[n.jsx(t.strong,{children:"Safe Area"}),": ",n.jsx(t.code,{children:"safeAreaBottomOffset"})," tự động thêm padding cho safe area bottom (quan trọng trên iOS)"]}),`
|
|
175
|
-
`]})]})}function l(e={}){const{wrapper:t}={...o(),...e.components};return t?n.jsx(t,{...e,children:n.jsx(i,{...e})}):i(e)}export{l as default};
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import{j as r}from"./iframe-CQAwSt4E.js";import{useMDXComponents as t}from"./index-CgMRTj-o.js";import{b as a}from"./blocks-BuaOUtiH.js";import"./preload-helper-PPVm8Dsz.js";import"./index-DHiZ-gXR.js";function e(o){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...t(),...o.components};return r.jsxs(r.Fragment,{children:[`
|
|
2
|
-
`,`
|
|
3
|
-
`,r.jsx(a,{title:"Use Cases/Custom Error Boundary"}),`
|
|
4
|
-
`,r.jsx(n.h1,{id:"custom-error-boundary",children:"Custom Error Boundary"}),`
|
|
5
|
-
`,r.jsx(n.p,{children:"App framework đã có sẵn ErrorBoundary global để catch tất cả lỗi, nhưng bạn có thể thêm ErrorBoundary riêng cho từng page thông qua Layouts để bắt lỗi trước và xử lý chi tiết hơn."}),`
|
|
6
|
-
`,r.jsx(n.h2,{id:"tổng-quan",children:"Tổng quan"}),`
|
|
7
|
-
`,r.jsxs(n.p,{children:["App component đã được bọc với ErrorBoundary global ở ngoài cùng để catch tất cả lỗi không được handle. Tuy nhiên, bạn có thể thêm ErrorBoundary riêng cho từng page thông qua ",r.jsx(n.code,{children:"Layouts"})," trong ",r.jsx(n.code,{children:"IPageConfig"})," để:"]}),`
|
|
8
|
-
`,r.jsxs(n.ul,{children:[`
|
|
9
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Bắt lỗi trước"}),": ErrorBoundary ở page-level sẽ bắt lỗi trước ErrorBoundary global"]}),`
|
|
10
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Xử lý chi tiết"}),": Mỗi page có thể có error UI và logic xử lý lỗi riêng phù hợp với context"]}),`
|
|
11
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Isolate errors"}),": Lỗi ở một page không ảnh hưởng đến các pages khác"]}),`
|
|
12
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Better UX"}),": User có thể tiếp tục sử dụng các pages khác khi một page bị lỗi"]}),`
|
|
13
|
-
`]}),`
|
|
14
|
-
`,r.jsx(n.h2,{id:"errorboundary-global",children:"ErrorBoundary Global"}),`
|
|
15
|
-
`,r.jsx(n.p,{children:"App component đã có ErrorBoundary global sẵn:"}),`
|
|
16
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`<ErrorBoundary isGlobal>{/* App content */}</ErrorBoundary>
|
|
17
|
-
`})}),`
|
|
18
|
-
`,r.jsx(n.p,{children:"ErrorBoundary global sẽ catch tất cả lỗi không được handle bởi các ErrorBoundary khác."}),`
|
|
19
|
-
`,r.jsx(n.h2,{id:"thêm-errorboundary-cho-từng-page",children:"Thêm ErrorBoundary cho từng Page"}),`
|
|
20
|
-
`,r.jsxs(n.p,{children:["Bạn có thể thêm ErrorBoundary riêng cho từng page thông qua ",r.jsx(n.code,{children:"Layouts"}),":"]}),`
|
|
21
|
-
`,r.jsx(n.h3,{id:"bước-1-tạo-custom-error-boundary-layout",children:"Bước 1: Tạo Custom Error Boundary Layout"}),`
|
|
22
|
-
`,r.jsx(n.p,{children:"Bạn có thể tự viết ErrorBoundary của riêng bạn:"}),`
|
|
23
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`import { Component } from 'react'
|
|
24
|
-
import { FC, PropsWithChildren } from 'react'
|
|
25
|
-
|
|
26
|
-
// Custom ErrorBoundary của riêng bạn
|
|
27
|
-
class CustomErrorBoundary extends Component<
|
|
28
|
-
PropsWithChildren,
|
|
29
|
-
{ hasError: boolean; error: Error | null }
|
|
30
|
-
> {
|
|
31
|
-
constructor(props: PropsWithChildren) {
|
|
32
|
-
super(props)
|
|
33
|
-
this.state = { hasError: false, error: null }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static getDerivedStateFromError(error: Error) {
|
|
37
|
-
return { hasError: true, error }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
41
|
-
// Log error to service
|
|
42
|
-
console.error('Error caught:', error, errorInfo)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
render() {
|
|
46
|
-
if (this.state.hasError) {
|
|
47
|
-
return (
|
|
48
|
-
<div>
|
|
49
|
-
<h1>Something went wrong</h1>
|
|
50
|
-
<p>{this.state.error?.message}</p>
|
|
51
|
-
</div>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return this.props.children
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const PageErrorBoundary: FC<PropsWithChildren> = ({ children }) => {
|
|
60
|
-
return <CustomErrorBoundary>{children}</CustomErrorBoundary>
|
|
61
|
-
}
|
|
62
|
-
`})}),`
|
|
63
|
-
`,r.jsx(n.h3,{id:"bước-2-sử-dụng-trong-page-config",children:"Bước 2: Sử dụng trong Page Config"}),`
|
|
64
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`import { App, type IAppConfig } from '@v-miniapp/ui-react'
|
|
65
|
-
import { PageErrorBoundary } from './layouts/PageErrorBoundary'
|
|
66
|
-
|
|
67
|
-
const appConfig: IAppConfig = {
|
|
68
|
-
pages: [
|
|
69
|
-
{
|
|
70
|
-
pathname: '/home',
|
|
71
|
-
Component: HomePage,
|
|
72
|
-
// Wrap page với ErrorBoundary riêng
|
|
73
|
-
Layouts: [PageErrorBoundary],
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
pathname: '/settings',
|
|
77
|
-
Component: SettingsPage,
|
|
78
|
-
// Page này không có ErrorBoundary riêng, sẽ dùng global
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
pathname: '/detail',
|
|
82
|
-
Component: DetailPage,
|
|
83
|
-
// Có thể kết hợp với các layouts khác
|
|
84
|
-
Layouts: [PageErrorBoundary, HeaderLayout],
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function MiniApp() {
|
|
90
|
-
return <App config={appConfig} />
|
|
91
|
-
}
|
|
92
|
-
`})}),`
|
|
93
|
-
`,r.jsx(n.h2,{id:"thứ-tự-xử-lý-lỗi",children:"Thứ tự xử lý lỗi"}),`
|
|
94
|
-
`,r.jsx(n.p,{children:"Khi có lỗi xảy ra, ErrorBoundary sẽ được gọi theo thứ tự từ trong ra ngoài:"}),`
|
|
95
|
-
`,r.jsxs(n.ol,{children:[`
|
|
96
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Page-level ErrorBoundary"})," (nếu có trong Layouts) - Bắt lỗi trước"]}),`
|
|
97
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Global ErrorBoundary"})," (trong App component) - Bắt các lỗi còn lại"]}),`
|
|
98
|
-
`]}),`
|
|
99
|
-
`,r.jsx(n.p,{children:"Nếu page có ErrorBoundary riêng và nó catch được lỗi, Global ErrorBoundary sẽ không nhận được lỗi đó."}),`
|
|
100
|
-
`,r.jsx(n.h2,{id:"ví-dụ-nâng-cao",children:"Ví dụ nâng cao"}),`
|
|
101
|
-
`,r.jsx(n.h3,{id:"custom-error-ui-cho-từng-page",children:"Custom Error UI cho từng page"}),`
|
|
102
|
-
`,r.jsx(n.p,{children:"Bạn có thể tạo các ErrorBoundary khác nhau với error UI và logic xử lý riêng. Có thể sử dụng ErrorBoundary có sẵn hoặc tự viết:"}),`
|
|
103
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`import { Component, type ReactNode } from 'react'
|
|
104
|
-
import { FC, PropsWithChildren } from 'react'
|
|
105
|
-
|
|
106
|
-
// ErrorBoundary với custom error UI cho home page
|
|
107
|
-
class HomeErrorBoundary extends Component<
|
|
108
|
-
PropsWithChildren,
|
|
109
|
-
{ hasError: boolean }
|
|
110
|
-
> {
|
|
111
|
-
constructor(props: PropsWithChildren) {
|
|
112
|
-
super(props)
|
|
113
|
-
this.state = { hasError: false }
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
static getDerivedStateFromError() {
|
|
117
|
-
return { hasError: true }
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
render() {
|
|
121
|
-
if (this.state.hasError) {
|
|
122
|
-
return <div>Home page error occurred</div>
|
|
123
|
-
}
|
|
124
|
-
return this.props.children
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// ErrorBoundary với custom error UI cho settings page
|
|
129
|
-
class SettingsErrorBoundary extends Component<
|
|
130
|
-
PropsWithChildren,
|
|
131
|
-
{ hasError: boolean }
|
|
132
|
-
> {
|
|
133
|
-
constructor(props: PropsWithChildren) {
|
|
134
|
-
super(props)
|
|
135
|
-
this.state = { hasError: false }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
static getDerivedStateFromError() {
|
|
139
|
-
return { hasError: true }
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
render() {
|
|
143
|
-
if (this.state.hasError) {
|
|
144
|
-
return <div>Settings page error occurred</div>
|
|
145
|
-
}
|
|
146
|
-
return this.props.children
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const HomeErrorBoundaryWrapper: FC<PropsWithChildren> = ({ children }) => {
|
|
151
|
-
return <HomeErrorBoundary>{children}</HomeErrorBoundary>
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const SettingsErrorBoundaryWrapper: FC<PropsWithChildren> = ({ children }) => {
|
|
155
|
-
return <SettingsErrorBoundary>{children}</SettingsErrorBoundary>
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const appConfig: IAppConfig = {
|
|
159
|
-
pages: [
|
|
160
|
-
{
|
|
161
|
-
pathname: '/home',
|
|
162
|
-
Component: HomePage,
|
|
163
|
-
Layouts: [HomeErrorBoundaryWrapper],
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
pathname: '/settings',
|
|
167
|
-
Component: SettingsPage,
|
|
168
|
-
Layouts: [SettingsErrorBoundaryWrapper],
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
}
|
|
172
|
-
`})}),`
|
|
173
|
-
`,r.jsx(n.h3,{id:"kết-hợp-với-các-layouts-khác",children:"Kết hợp với các Layouts khác"}),`
|
|
174
|
-
`,r.jsx(n.p,{children:"Bạn có thể kết hợp ErrorBoundary với các layouts khác. Thứ tự trong array sẽ quyết định thứ tự wrap:"}),`
|
|
175
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`import { Component } from 'react'
|
|
176
|
-
import { FC, PropsWithChildren } from 'react'
|
|
177
|
-
|
|
178
|
-
// Tự viết ErrorBoundary hoặc sử dụng từ @v-miniapp/ui-react
|
|
179
|
-
class PageErrorBoundary extends Component<
|
|
180
|
-
PropsWithChildren,
|
|
181
|
-
{ hasError: boolean }
|
|
182
|
-
> {
|
|
183
|
-
constructor(props: PropsWithChildren) {
|
|
184
|
-
super(props)
|
|
185
|
-
this.state = { hasError: false }
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
static getDerivedStateFromError() {
|
|
189
|
-
return { hasError: true }
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
render() {
|
|
193
|
-
if (this.state.hasError) {
|
|
194
|
-
return <div>Page error occurred</div>
|
|
195
|
-
}
|
|
196
|
-
return this.props.children
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const PageErrorBoundaryWrapper: FC<PropsWithChildren> = ({ children }) => {
|
|
201
|
-
return <PageErrorBoundary>{children}</PageErrorBoundary>
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const HeaderLayout: FC<PropsWithChildren> = ({ children }) => {
|
|
205
|
-
return (
|
|
206
|
-
<div className="header-layout">
|
|
207
|
-
<header>Header</header>
|
|
208
|
-
{children}
|
|
209
|
-
</div>
|
|
210
|
-
)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const AuthLayout: FC<PropsWithChildren> = ({ children }) => {
|
|
214
|
-
return <div className="auth-layout">{children}</div>
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const appConfig: IAppConfig = {
|
|
218
|
-
pages: [
|
|
219
|
-
{
|
|
220
|
-
pathname: '/home',
|
|
221
|
-
Component: HomePage,
|
|
222
|
-
// Thứ tự wrap: AuthLayout → HeaderLayout → PageErrorBoundaryWrapper → HomePage
|
|
223
|
-
Layouts: [AuthLayout, HeaderLayout, PageErrorBoundaryWrapper],
|
|
224
|
-
},
|
|
225
|
-
],
|
|
226
|
-
}
|
|
227
|
-
`})}),`
|
|
228
|
-
`,r.jsxs(n.p,{children:[r.jsx(n.strong,{children:"Lưu ý:"})," Phần tử ",r.jsx(n.strong,{children:"cuối cùng"})," trong array sẽ wrap ở ",r.jsx(n.strong,{children:"trong cùng"})," (gần Component nhất). Với ",r.jsx(n.code,{children:"Layouts: [AuthLayout, HeaderLayout, PageErrorBoundaryWrapper]"}),", kết quả render sẽ là:"]}),`
|
|
229
|
-
`,r.jsx(n.pre,{children:r.jsx(n.code,{className:"language-tsx",children:`<AuthLayout>
|
|
230
|
-
<HeaderLayout>
|
|
231
|
-
<PageErrorBoundaryWrapper>
|
|
232
|
-
<HomePage />
|
|
233
|
-
</PageErrorBoundaryWrapper>
|
|
234
|
-
</HeaderLayout>
|
|
235
|
-
</AuthLayout>
|
|
236
|
-
`})}),`
|
|
237
|
-
`,r.jsx(n.h2,{id:"lưu-ý-quan-trọng",children:"Lưu ý quan trọng"}),`
|
|
238
|
-
`,r.jsxs(n.ul,{children:[`
|
|
239
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Wrap từng màn hình"}),": Layouts phải wrap từng page riêng biệt, không hỗ trợ nested routes hoặc group layout cho nhiều pages. Mỗi page cần wrap ErrorBoundary riêng nếu muốn xử lý lỗi độc lập."]}),`
|
|
240
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Không group Layout"}),": Không thể định nghĩa Layouts ở app-level để áp dụng cho nhiều pages. Layouts chỉ có thể được khai báo trong ",r.jsx(n.code,{children:"IPageConfig"})," của từng page."]}),`
|
|
241
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"ErrorBoundary scope"}),": ErrorBoundary trong Layouts chỉ catch lỗi của page component và các component con của nó, không catch lỗi của các pages khác."]}),`
|
|
242
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Bắt lỗi trước"}),": Page-level ErrorBoundary sẽ bắt lỗi trước Global ErrorBoundary, cho phép bạn xử lý lỗi chi tiết hơn cho từng page."]}),`
|
|
243
|
-
`]}),`
|
|
244
|
-
`,r.jsx(n.h2,{id:"best-practices",children:"Best Practices"}),`
|
|
245
|
-
`,r.jsxs(n.ol,{children:[`
|
|
246
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Chỉ bọc page cần thiết"}),": Không cần bọc ErrorBoundary cho tất cả pages, chỉ bọc những page có logic phức tạp hoặc cần xử lý lỗi riêng"]}),`
|
|
247
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Đặt ErrorBoundary ở trong cùng"}),": Nếu kết hợp với các layouts khác, thường nên đặt ErrorBoundary ở trong cùng (cuối array) để chỉ catch lỗi của page component"]}),`
|
|
248
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Custom error UI"}),": Tùy chỉnh error UI phù hợp với context của từng page để có UX tốt hơn"]}),`
|
|
249
|
-
`,r.jsxs(n.li,{children:[r.jsx(n.strong,{children:"Error logging"}),": Có thể thêm error logging trong ErrorBoundary để track lỗi"]}),`
|
|
250
|
-
`]})]})}function l(o={}){const{wrapper:n}={...t(),...o.components};return n?r.jsx(n,{...o,children:r.jsx(e,{...o})}):e(o)}export{l as default};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import{j as n}from"./iframe-CQAwSt4E.js";import{useMDXComponents as h}from"./index-CgMRTj-o.js";import{b as c,M as o}from"./blocks-BuaOUtiH.js";import"./preload-helper-PPVm8Dsz.js";import"./index-DHiZ-gXR.js";function t(d){const e={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...h(),...d.components};return n.jsxs(n.Fragment,{children:[`
|
|
2
|
-
`,`
|
|
3
|
-
`,n.jsx(c,{title:"App Framework/Dark Mode"}),`
|
|
4
|
-
`,n.jsx(e.h1,{id:"dark-mode",children:"Dark Mode"}),`
|
|
5
|
-
`,n.jsx(e.p,{children:"Dark Mode config cho phép bạn cấu hình dark mode mặc định cho ứng dụng."}),`
|
|
6
|
-
`,n.jsx(e.h2,{id:"cấu-trúc",children:"Cấu trúc"}),`
|
|
7
|
-
`,n.jsx(e.pre,{children:n.jsx(e.code,{className:"language-typescript",children:`type IDarkModeConfig = {
|
|
8
|
-
defaultEnabled?: boolean
|
|
9
|
-
}
|
|
10
|
-
`})}),`
|
|
11
|
-
`,n.jsx(e.h2,{id:"thuộc-tính",children:"Thuộc tính"}),`
|
|
12
|
-
`,n.jsx(o,{children:"\n| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |\n| :--- | :--- | :--- | :--- |\n| `defaultEnabled` | `boolean` | `false` | Bật dark mode mặc định khi khởi động ứng dụng |\n"}),`
|
|
13
|
-
`,n.jsx(e.h2,{id:"cách-hoạt-động",children:"Cách hoạt động"}),`
|
|
14
|
-
`,n.jsxs(e.p,{children:["Khi ",n.jsx(e.code,{children:"defaultEnabled: true"}),", ứng dụng sẽ tự động set ",n.jsx(e.code,{children:'data-theme="dark"'})," trên ",n.jsx(e.code,{children:"document.documentElement"})," khi khởi động, áp dụng dark mode cho toàn bộ ứng dụng."]}),`
|
|
15
|
-
`,n.jsx(e.h2,{id:"cấu-hình",children:"Cấu hình"}),`
|
|
16
|
-
`,n.jsx(e.h3,{id:"app-level-config",children:"App-level Config"}),`
|
|
17
|
-
`,n.jsx(e.p,{children:"Cấu hình dark mode mặc định:"}),`
|
|
18
|
-
`,n.jsx(e.pre,{children:n.jsx(e.code,{className:"language-tsx",children:`const appConfig: IAppConfig = {
|
|
19
|
-
darkMode: {
|
|
20
|
-
defaultEnabled: true, // Bật dark mode mặc định
|
|
21
|
-
},
|
|
22
|
-
pages: [
|
|
23
|
-
// Tất cả pages sẽ hiển thị dark mode
|
|
24
|
-
],
|
|
25
|
-
}
|
|
26
|
-
`})}),`
|
|
27
|
-
`,n.jsx(e.h3,{id:"ví-dụ",children:"Ví dụ"}),`
|
|
28
|
-
`,n.jsx(e.pre,{children:n.jsx(e.code,{className:"language-tsx",children:`const appConfig: IAppConfig = {
|
|
29
|
-
// Bật dark mode mặc định
|
|
30
|
-
darkMode: {
|
|
31
|
-
defaultEnabled: true,
|
|
32
|
-
},
|
|
33
|
-
pages: [
|
|
34
|
-
{
|
|
35
|
-
pathname: '/home',
|
|
36
|
-
Component: HomePage,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
pathname: '/settings',
|
|
40
|
-
Component: SettingsPage,
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
}
|
|
44
|
-
`})}),`
|
|
45
|
-
`,n.jsx(e.h2,{id:"lưu-ý",children:"Lưu ý"}),`
|
|
46
|
-
`,n.jsxs(e.ul,{children:[`
|
|
47
|
-
`,n.jsxs(e.li,{children:["Dark mode config chỉ có ở ",n.jsx(e.strong,{children:"app-level"}),", không có ở page-level"]}),`
|
|
48
|
-
`,n.jsxs(e.li,{children:["Khi ",n.jsx(e.code,{children:"defaultEnabled: true"}),", dark mode sẽ được áp dụng ngay khi ứng dụng khởi động"]}),`
|
|
49
|
-
`,n.jsxs(e.li,{children:["Dark mode sử dụng CSS variables và ",n.jsx(e.code,{children:"data-theme"})," attribute để thay đổi theme"]}),`
|
|
50
|
-
`,n.jsxs(e.li,{children:["Bạn có thể toggle dark mode động bằng cách thay đổi ",n.jsx(e.code,{children:"data-theme"})," attribute trên ",n.jsx(e.code,{children:"document.documentElement"}),":",`
|
|
51
|
-
`,n.jsx(e.pre,{children:n.jsx(e.code,{className:"language-tsx",children:`// Toggle dark mode
|
|
52
|
-
document.documentElement.setAttribute('data-theme', 'dark')
|
|
53
|
-
// hoặc
|
|
54
|
-
document.documentElement.setAttribute('data-theme', 'light')
|
|
55
|
-
`})}),`
|
|
56
|
-
`]}),`
|
|
57
|
-
`]})]})}function m(d={}){const{wrapper:e}={...h(),...d.components};return e?n.jsx(e,{...d,children:n.jsx(t,{...d})}):t(d)}export{m as default};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import{j as n}from"./iframe-CQAwSt4E.js";import{useMDXComponents as c}from"./index-CgMRTj-o.js";import{b as a}from"./blocks-BuaOUtiH.js";import"./preload-helper-PPVm8Dsz.js";import"./index-DHiZ-gXR.js";function t(e){const i={code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",...c(),...e.components};return n.jsxs(n.Fragment,{children:[`
|
|
2
|
-
`,`
|
|
3
|
-
`,n.jsx(a,{title:"Getting Started",parameters:{options:{nav:{icon:""}}}}),`
|
|
4
|
-
`,n.jsx(i.h1,{id:"getting-started-với-v-miniappui-react",children:"Getting Started với @v-miniapp/ui-react"}),`
|
|
5
|
-
`,n.jsxs(i.p,{children:[n.jsx(i.strong,{children:"@v-miniapp/ui-react"})," là bộ thư viện component React mạnh mẽ được thiết kế đặc biệt cho việc phát triển V-MiniApp."]}),`
|
|
6
|
-
`,n.jsx(i.h2,{id:"cài-đặt",children:"Cài đặt"}),`
|
|
7
|
-
`,n.jsx(i.pre,{children:n.jsx(i.code,{className:"language-bash",children:`npm install @v-miniapp/ui-react
|
|
8
|
-
# hoặc
|
|
9
|
-
pnpm add @v-miniapp/ui-react
|
|
10
|
-
# hoặc
|
|
11
|
-
yarn add @v-miniapp/ui-react
|
|
12
|
-
`})}),`
|
|
13
|
-
`,n.jsx(i.h2,{id:"import-styles",children:"Import Styles"}),`
|
|
14
|
-
`,n.jsx(i.h3,{id:"option-1-sử-dụng-css-chuẩn",children:"Option 1: Sử dụng CSS chuẩn"}),`
|
|
15
|
-
`,n.jsx(i.p,{children:"Đảm bảo bạn import CSS từ phía component để UI hoạt động tốt nhất:"}),`
|
|
16
|
-
`,n.jsx(i.pre,{children:n.jsx(i.code,{className:"language-tsx",children:`import '@v-miniapp/ui-react/styles.css'
|
|
17
|
-
`})}),`
|
|
18
|
-
`,n.jsx(i.h3,{id:"option-2-tích-hợp-với-tailwind-css",children:"Option 2: Tích hợp với Tailwind CSS"}),`
|
|
19
|
-
`,n.jsx(i.p,{children:"Nếu mini app của bạn đang sử dụng Tailwind CSS, bạn có thể tích hợp dễ dàng bằng cách thêm một dòng import vào file Tailwind config:"}),`
|
|
20
|
-
`,n.jsx(i.pre,{children:n.jsx(i.code,{className:"language-css",children:`/* tailwind.css hoặc file CSS chính của bạn */
|
|
21
|
-
@import '@v-miniapp/ui-react/tailwind';
|
|
22
|
-
`})}),`
|
|
23
|
-
`,n.jsxs(i.p,{children:[n.jsx(i.strong,{children:"Lưu ý:"})," Khi tích hợp với Tailwind, bạn không cần import ",n.jsx(i.code,{children:"@v-miniapp/ui-react/styles.css"})," nữa."]}),`
|
|
24
|
-
`,n.jsx(i.h2,{id:"ví-dụ-bắt-đầu-sử-dụng",children:"Ví dụ bắt đầu sử dụng"}),`
|
|
25
|
-
`,n.jsx(i.pre,{children:n.jsx(i.code,{className:"language-tsx",children:`import { App, type IAppConfig } from '@v-miniapp/ui-react'
|
|
26
|
-
|
|
27
|
-
// Tạo các page components
|
|
28
|
-
const HomePage = () => {
|
|
29
|
-
return <div>Trang chủ</div>
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const SettingsPage = () => {
|
|
33
|
-
return <div>Cài đặt</div>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const appConfig: IAppConfig = {
|
|
37
|
-
// Animation giữa các pages: 'none', 'slide_up', 'slide_left', 'fade_in'
|
|
38
|
-
animation: {
|
|
39
|
-
type: 'slide_left',
|
|
40
|
-
},
|
|
41
|
-
// Keep-alive: giữ state của pages khi navigate
|
|
42
|
-
keepAlive: {
|
|
43
|
-
enable: true,
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
pages: [
|
|
47
|
-
{
|
|
48
|
-
pathname: '/home',
|
|
49
|
-
Component: HomePage,
|
|
50
|
-
navigationBar: {
|
|
51
|
-
title: 'Trang chủ',
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
pathname: '/settings',
|
|
56
|
-
Component: SettingsPage,
|
|
57
|
-
navigationBar: {
|
|
58
|
-
title: 'Cài đặt',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const MiniApp: FC = () => {
|
|
65
|
-
return <App config={appConfig} />
|
|
66
|
-
}
|
|
67
|
-
`})}),`
|
|
68
|
-
`,n.jsx(i.h2,{id:"️-lưu-ý-quan-trọng",children:"⚠️ Lưu ý quan trọng"}),`
|
|
69
|
-
`,n.jsxs(i.p,{children:["Khi sử dụng component ",n.jsx(i.code,{children:"App"})," từ ",n.jsx(i.code,{children:"@v-miniapp/ui-react"}),", bạn đã có sẵn ",n.jsx(i.code,{children:"NavigationBar"})," component được quản lý bởi SDK. Nếu bạn cấu hình ",n.jsx(i.code,{children:"window"})," trong ",n.jsx(i.code,{children:"app-config.json"})," để hiển thị title bar/navigation bar từ native, sẽ có thể bị trùng lặp với component của ",n.jsx(i.code,{children:"ui-react"}),"."]}),`
|
|
70
|
-
`,n.jsxs(i.p,{children:[n.jsx(i.strong,{children:"Giải pháp:"})," Nếu bạn sử dụng ",n.jsx(i.code,{children:"NavigationBar"})," từ ",n.jsx(i.code,{children:"@v-miniapp/ui-react"}),", bạn nên cấu hình trong ",n.jsx(i.code,{children:"app-config.json"})," để ẩn native title bar:"]}),`
|
|
71
|
-
`,n.jsx(i.pre,{children:n.jsx(i.code,{className:"language-json",children:`{
|
|
72
|
-
"window": {
|
|
73
|
-
"defaultTitle": "",
|
|
74
|
-
"transparentTitle": "always"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
`})})]})}function h(e={}){const{wrapper:i}={...c(),...e.components};return i?n.jsx(i,{...e,children:n.jsx(t,{...e})}):t(e)}export{h as default};
|