@wssto2/vue-core 0.1.0 → 0.3.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/README.md +53 -9
- package/dist/AccessGate.vue_vue_type_script_setup_true_lang-DKX3PH2n.js +22 -0
- package/dist/AccountMenuItem.vue_vue_type_script_setup_true_lang-DIGqTLwd.js +76 -0
- package/dist/ActionRow.vue_vue_type_script_setup_true_lang-B7Lpfkf6.js +45 -0
- package/dist/Activity-DviO0VQ8.js +156 -0
- package/dist/{AdaptivePageShell.vue_vue_type_script_setup_true_lang-CKghARkW.js → AdaptivePageShell.vue_vue_type_script_setup_true_lang-CvAnzdc1.js} +48 -47
- package/dist/{AlertDialog.vue_vue_type_script_setup_true_lang-BZb4qKXo.js → AlertDialog.vue_vue_type_script_setup_true_lang-CJsMUIUg.js} +2 -2
- package/dist/{AsyncSection.vue_vue_type_script_setup_true_lang-B82bl36A.js → AsyncSection.vue_vue_type_script_setup_true_lang-CCtthMRd.js} +4 -4
- package/dist/Badge.vue_vue_type_script_setup_true_lang-DJyZc0C7.js +51 -0
- package/dist/{Banner.vue_vue_type_script_setup_true_lang-n_wGPIIu.js → Banner.vue_vue_type_script_setup_true_lang-Cib_YYpr.js} +1 -1
- package/dist/{BottomDock.vue_vue_type_script_setup_true_lang-DhlMnPC2.js → BottomDock.vue_vue_type_script_setup_true_lang-CjN7xYEr.js} +1 -1
- package/dist/Button.vue_vue_type_script_setup_true_lang-CYil8h9z.js +182 -0
- package/dist/Changes-DlT5mN9G.js +129 -0
- package/dist/CollectionPage.vue_vue_type_script_setup_true_lang-CXILftEc.js +1481 -0
- package/dist/CountryFlag.vue_vue_type_script_setup_true_lang-Kry_vPPZ.js +299 -0
- package/dist/DataTable.vue_vue_type_script_setup_true_lang-DSYgS9lC.js +52 -0
- package/dist/DateField.vue_vue_type_script_setup_true_lang-DMVjNsaM.js +1099 -0
- package/dist/{DiscardChangesModal.vue_vue_type_script_setup_true_lang-Bx5O1RZJ.js → DiscardChangesModal.vue_vue_type_script_setup_true_lang-Cb3xJI1x.js} +1 -1
- package/dist/{EmptyState.vue_vue_type_script_setup_true_lang-BeGpHMUP.js → EmptyState.vue_vue_type_script_setup_true_lang-C2ZYIT9F.js} +1 -1
- package/dist/FormErrors.vue_vue_type_script_setup_true_lang-DVgNBQ8p.js +276 -0
- package/dist/FormGroup.vue_vue_type_script_setup_true_lang-0mfG8TkU.js +136 -0
- package/dist/FormView.vue_vue_type_script_setup_true_lang-Bz2m3AtF.js +38 -0
- package/dist/General-BD-Hcz0a.js +145 -0
- package/dist/{Icon.vue_vue_type_script_lang-DtC4_mkz.js → Icon.vue_vue_type_script_lang-VvcV2Bzo.js} +46 -33
- package/dist/{IconTile.vue_vue_type_script_setup_true_lang-Csfv6Sel.js → IconTile.vue_vue_type_script_setup_true_lang-D7QgnUyN.js} +1 -1
- package/dist/KeyValue.vue_vue_type_script_setup_true_lang-wcZcvnow.js +35 -0
- package/dist/{LeaveGuardRoot.vue_vue_type_script_setup_true_lang-DH6EB8br.js → LeaveGuardRoot.vue_vue_type_script_setup_true_lang-C2udmeEA.js} +2 -2
- package/dist/{Menu.vue_vue_type_script_setup_true_lang-D44EHXQZ.js → Menu.vue_vue_type_script_setup_true_lang-BNAjx9tj.js} +61 -57
- package/dist/{Modal.vue_vue_type_script_setup_true_lang-DYQgaUtj.js → Modal.vue_vue_type_script_setup_true_lang-D7SwVPpL.js} +139 -129
- package/dist/NewRolePage-Dla4YnMs.js +42 -0
- package/dist/NoAccess.vue_vue_type_script_setup_true_lang-8m9cNptR.js +31 -0
- package/dist/NumberField.vue_vue_type_script_setup_true_lang-CYRg7Kfg.js +113 -0
- package/dist/OtpInput.vue_vue_type_script_setup_true_lang-gp4FfWAH.js +95 -0
- package/dist/PageBar.vue_vue_type_script_setup_true_lang-Cfr5xsJx.js +47 -0
- package/dist/{Panel.vue_vue_type_script_setup_true_lang-BQmv3cLb.js → Panel.vue_vue_type_script_setup_true_lang-BCRxRK4D.js} +1 -1
- package/dist/{PhotoViewer.vue_vue_type_script_setup_true_lang-DDVQXJRB.js → PhotoViewer.vue_vue_type_script_setup_true_lang-B3Q4dhqJ.js} +2 -2
- package/dist/Popover.vue_vue_type_script_setup_true_lang-Dx-tDhNE.js +125 -0
- package/dist/ProfilePage-OJMQ8cr8.js +691 -0
- package/dist/{ProgressTrack.vue_vue_type_script_setup_true_lang-1DDaNs2W.js → ProgressTrack.vue_vue_type_script_setup_true_lang-B6Prw9hi.js} +2 -2
- package/dist/RecordHeader.vue_vue_type_script_setup_true_lang-DKsaKlAq.js +64 -0
- package/dist/ResourcePage.vue_vue_type_script_setup_true_lang-CJcKa9SW.js +173 -0
- package/dist/RoleEditor.vue_vue_type_script_setup_true_lang-DuEPOmjI.js +299 -0
- package/dist/RolePage-bZzv_E4l.js +315 -0
- package/dist/RolesPage-BniZv0nB.js +115 -0
- package/dist/SectionIntro.vue_vue_type_script_setup_true_lang-CZtPrmXD.js +23 -0
- package/dist/SectionList.vue_vue_type_script_setup_true_lang-BKP_bge8.js +148 -0
- package/dist/SectionNavigator.vue_vue_type_script_setup_true_lang-BgGEGxSI.js +314 -0
- package/dist/SegmentedField.vue_vue_type_script_setup_true_lang-BZ9UdgA1.js +58 -0
- package/dist/SelectField.vue_vue_type_script_setup_true_lang-BiGaEKBQ.js +422 -0
- package/dist/SessionList.vue_vue_type_script_setup_true_lang-DUQpr7gb.js +111 -0
- package/dist/Sessions-Co5-xdeb.js +96 -0
- package/dist/Sheet.vue_vue_type_script_setup_true_lang-bHYzx7-J.js +142 -0
- package/dist/SignIn-BWwFbxki.js +140 -0
- package/dist/SignInPage-FnLtoi2q.js +60 -0
- package/dist/SignInTable.vue_vue_type_script_setup_true_lang-Dnx3T_42.js +79 -0
- package/dist/SignIns-3UcI64_h.js +66 -0
- package/dist/SwipeActions.vue_vue_type_script_setup_true_lang-4I8m27ol.js +93 -0
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-BeGaydRr.js +155 -0
- package/dist/TextField.vue_vue_type_script_setup_true_lang-C_FMf3Vc.js +269 -0
- package/dist/TextareaField.vue_vue_type_script_setup_true_lang-CU3KTKIJ.js +127 -0
- package/dist/{Timestamp.vue_vue_type_script_setup_true_lang-CSY_mMm1.js → Timestamp.vue_vue_type_script_setup_true_lang-1RJGKxbD.js} +1 -1
- package/dist/{Tooltip.vue_vue_type_script_setup_true_lang-BJWPVyfT.js → Tooltip.vue_vue_type_script_setup_true_lang-OOD_XNWx.js} +1 -1
- package/dist/UserRecord-Ci8HfwbX.js +267 -0
- package/dist/UsersList-vEJ-cgkT.js +155 -0
- package/dist/ViewTabs.vue_vue_type_script_setup_true_lang-ByqTU2JT.js +28 -0
- package/dist/access/AddRoleDialog.vue.d.ts +19 -0
- package/dist/access/BindingRow.vue.d.ts +19 -0
- package/dist/access/EffectiveAccess.vue.d.ts +12 -0
- package/dist/access/NewRolePage.vue.d.ts +2 -0
- package/dist/access/PermissionTree.vue.d.ts +13 -0
- package/dist/access/PersonAccess.vue.d.ts +21 -0
- package/dist/access/ReplaceRoleDialog.vue.d.ts +17 -0
- package/dist/access/RoleCompareDialog.vue.d.ts +14 -0
- package/dist/access/RoleEditor.vue.d.ts +28 -0
- package/dist/access/RolePage.vue.d.ts +2 -0
- package/dist/access/RolesPage.vue.d.ts +2 -0
- package/dist/access/api.d.ts +26 -0
- package/dist/access/catalogue.d.ts +64 -0
- package/dist/access/context.d.ts +20 -0
- package/dist/access/effective.d.ts +42 -0
- package/dist/access/feature.d.ts +27 -0
- package/dist/access/index.d.ts +13 -0
- package/dist/access/index.js +15 -0
- package/dist/access/labels.d.ts +35 -0
- package/dist/access/refusals.d.ts +6 -0
- package/dist/access/routes.d.ts +45 -0
- package/dist/access/scopes.d.ts +20 -0
- package/dist/app/application.d.ts +5 -0
- package/dist/app/contributions.d.ts +1 -1
- package/dist/app/environment.d.ts +2 -0
- package/dist/app/feature.d.ts +8 -0
- package/dist/app/index.js +260 -294
- package/dist/bottomDock-BZEiOPYZ.js +12 -0
- package/dist/button/Button.vue.d.ts +3 -3
- package/dist/button/index.d.ts +1 -1
- package/dist/button/index.js +5 -3
- package/dist/button/shortcut.d.ts +28 -2
- package/dist/chrome-BS3xJcad.js +93 -0
- package/dist/client/client.d.ts +13 -0
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.js +19 -138
- package/dist/client/route.d.ts +59 -0
- package/dist/client-Bw0aM5Gu.js +147 -0
- package/dist/closeOverlays-CjVsIrpL.js +8 -0
- package/dist/collection/CollectionPage.vue.d.ts +1 -0
- package/dist/collection/CollectionRows.vue.d.ts +59 -0
- package/dist/collection/CollectionTable.vue.d.ts +1 -1
- package/dist/collection/DataTable.vue.d.ts +47 -0
- package/dist/collection/RowActions.vue.d.ts +19 -0
- package/dist/collection/columns.d.ts +2 -0
- package/dist/collection/http.d.ts +4 -2
- package/dist/collection/index.d.ts +4 -2
- package/dist/collection/index.js +87 -2299
- package/dist/collection/rowLayout.d.ts +10 -0
- package/dist/collection/slots.d.ts +6 -3
- package/dist/content/index.js +37 -66
- package/dist/contributions-CDDg3fKp.js +26 -0
- package/dist/controls/DateButton.vue.d.ts +1 -1
- package/dist/controls/PopupButton.vue.d.ts +1 -1
- package/dist/controls/index.js +11 -10
- package/dist/defineRoutes-BGAdiIrt.js +19 -0
- package/dist/describeError-Ctga6GcS.js +41 -0
- package/dist/dialogStack-DZZg55w0.js +31 -0
- package/dist/environment-Dva-SG8D.js +6 -0
- package/dist/{error-Bb_dr_Ay.js → error-CD7x0Jrz.js} +2 -2
- package/dist/feature-DdUAfyi4.js +25 -0
- package/dist/fieldMessages-C3Rpbktw.js +25 -0
- package/dist/form/CheckboxField.vue.d.ts +1 -1
- package/dist/form/CommandDialog.vue.d.ts +13 -2
- package/dist/form/DateField.vue.d.ts +1 -1
- package/dist/form/DateTimeField.vue.d.ts +1 -1
- package/dist/form/EditorPage.vue.d.ts +1 -1
- package/dist/form/Field.vue.d.ts +1 -1
- package/dist/form/FileField.vue.d.ts +1 -1
- package/dist/form/FormGroup.vue.d.ts +1 -1
- package/dist/form/FormGroupButton.vue.d.ts +1 -1
- package/dist/form/FormRow.vue.d.ts +1 -1
- package/dist/form/I18nField.vue.d.ts +3 -3
- package/dist/form/MoneyField.vue.d.ts +1 -1
- package/dist/form/MonthYearField.vue.d.ts +1 -1
- package/dist/form/MultiSelectField.vue.d.ts +4 -1
- package/dist/form/NumberCell.vue.d.ts +1 -1
- package/dist/form/NumberField.vue.d.ts +8 -2
- package/dist/form/OptionList.vue.d.ts +6 -2
- package/dist/form/OtpInput.vue.d.ts +2 -2
- package/dist/form/PhotoField.vue.d.ts +1 -1
- package/dist/form/SelectField.vue.d.ts +4 -1
- package/dist/form/SwitchField.vue.d.ts +1 -1
- package/dist/form/TextField.vue.d.ts +3 -3
- package/dist/form/TextareaField.vue.d.ts +3 -3
- package/dist/form/TimeField.vue.d.ts +1 -1
- package/dist/form/date/DatePickerSheet.vue.d.ts +1 -1
- package/dist/form/date/MonthYearPanel.vue.d.ts +1 -1
- package/dist/form/index.d.ts +2 -0
- package/dist/form/index.js +1273 -3509
- package/dist/form/suggestions.d.ts +11 -0
- package/dist/form/useOptions.d.ts +60 -0
- package/dist/guards-Cd1V28oG.js +51 -0
- package/dist/http-DGGSKWvU.js +193 -0
- package/dist/i18n/describeError.d.ts +31 -0
- package/dist/i18n/index.d.ts +307 -0
- package/dist/i18n/index.js +54 -52
- package/dist/icon/core.d.ts +13 -0
- package/dist/icon/index.js +1 -1
- package/dist/identity/ImpersonationBanner.vue.d.ts +2 -0
- package/dist/identity/LocaleSync.vue.d.ts +2 -0
- package/dist/identity/SessionExpiry.vue.d.ts +2 -0
- package/dist/identity/SignInAsButton.vue.d.ts +15 -0
- package/dist/identity/SignInPage.vue.d.ts +2 -0
- package/dist/identity/context.d.ts +7 -0
- package/dist/identity/feature.d.ts +16 -0
- package/dist/identity/fieldMessages.d.ts +15 -0
- package/dist/identity/index.d.ts +16 -0
- package/dist/identity/index.js +18 -0
- package/dist/identity/profile/DetailsPanel.vue.d.ts +11 -0
- package/dist/identity/profile/EmailChangeDialog.vue.d.ts +14 -0
- package/dist/identity/profile/EmailPanel.vue.d.ts +11 -0
- package/dist/identity/profile/PanelActions.vue.d.ts +17 -0
- package/dist/identity/profile/PasswordPanel.vue.d.ts +2 -0
- package/dist/identity/profile/ProfileMenuItem.vue.d.ts +2 -0
- package/dist/identity/profile/ProfilePage.vue.d.ts +2 -0
- package/dist/identity/profile/SessionsPanel.vue.d.ts +2 -0
- package/dist/identity/profile/SignInsPanel.vue.d.ts +2 -0
- package/dist/identity/profile/VerifyCode.vue.d.ts +49 -0
- package/dist/identity/profile/routes.d.ts +13 -0
- package/dist/identity/session.d.ts +30 -0
- package/dist/identity/shared/ActionRow.vue.d.ts +20 -0
- package/dist/identity/shared/ChangeFeed.vue.d.ts +11 -0
- package/dist/identity/shared/PageBar.vue.d.ts +12 -0
- package/dist/identity/shared/SectionIntro.vue.d.ts +16 -0
- package/dist/identity/shared/SessionList.vue.d.ts +19 -0
- package/dist/{phone/CountryFlag.vue.d.ts → identity/shared/SignInTable.vue.d.ts} +5 -4
- package/dist/identity/shared/ViewTabs.vue.d.ts +23 -0
- package/dist/identity/shared/signInEvents.d.ts +9 -0
- package/dist/identity/signIn.d.ts +27 -0
- package/dist/identity/useSignInForm.d.ts +20 -0
- package/dist/identity/user.d.ts +6 -0
- package/dist/identity/users/DeactivateDialog.vue.d.ts +18 -0
- package/dist/identity/users/NewUserDialog.vue.d.ts +9 -0
- package/dist/identity/users/SetPasswordDialog.vue.d.ts +16 -0
- package/dist/identity/users/UserRecord.vue.d.ts +2 -0
- package/dist/identity/users/UsersList.vue.d.ts +2 -0
- package/dist/identity/users/access.d.ts +4 -0
- package/dist/identity/users/context.d.ts +9 -0
- package/dist/identity/users/feature.d.ts +34 -0
- package/dist/identity/users/languages.d.ts +4 -0
- package/dist/identity/users/list.d.ts +8 -0
- package/dist/identity/users/person.d.ts +26 -0
- package/dist/identity/users/personSections.d.ts +22 -0
- package/dist/identity/users/routes.d.ts +22 -0
- package/dist/identity/users/sections/Activity.vue.d.ts +2 -0
- package/dist/identity/users/sections/Changes.vue.d.ts +2 -0
- package/dist/identity/users/sections/General.vue.d.ts +2 -0
- package/dist/identity/users/sections/Sessions.vue.d.ts +2 -0
- package/dist/identity/users/sections/SignIn.vue.d.ts +2 -0
- package/dist/identity/users/sections/SignIns.vue.d.ts +2 -0
- package/dist/identity/users/status.d.ts +4 -0
- package/dist/index-B2dbYZR9.js +706 -0
- package/dist/index-BAcl44SC.js +459 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/CountryFlag.vue.d.ts +10 -0
- package/dist/internal/languageName.d.ts +2 -0
- package/dist/keepAlive-WYQGRhuz.js +48 -0
- package/dist/languageName-CItV_SOv.js +11 -0
- package/dist/languages-BShG9LpE.js +10 -0
- package/dist/leaveGuard-Cc8yeLxM.js +72 -0
- package/dist/modal/Modal.vue.d.ts +4 -0
- package/dist/modal/ShortcutHelp.vue.d.ts +2 -0
- package/dist/modal/index.d.ts +2 -0
- package/dist/modal/index.js +64 -6
- package/dist/modal/placement.d.ts +22 -0
- package/dist/modules/access/entities.d.ts +112 -0
- package/dist/modules/access/routes.d.ts +67 -0
- package/dist/modules/access/schemas.d.ts +73 -0
- package/dist/modules/identity/entities.d.ts +150 -0
- package/dist/modules/identity/routes.d.ts +118 -0
- package/dist/modules/identity/schemas.d.ts +145 -0
- package/dist/{navigation-B33ikiCS.js → navigation-BPWa63ge.js} +21 -20
- package/dist/neighbors-D0WRBxXI.js +86 -0
- package/dist/{options-CjSz2dQK.js → options-BXkMR63B.js} +48 -49
- package/dist/overlay/AlertDialog.vue.d.ts +3 -3
- package/dist/overlay/Popover.vue.d.ts +4 -1
- package/dist/overlay/closeOverlays.d.ts +7 -0
- package/dist/overlay/dialogStack.d.ts +9 -0
- package/dist/overlay/index.d.ts +1 -1
- package/dist/overlay/index.js +20 -18
- package/dist/page/AdaptivePageShell.vue.d.ts +2 -2
- package/dist/page/ResourceHeader.vue.d.ts +2 -2
- package/dist/page/index.js +99 -457
- package/dist/phone/PhoneField.vue.d.ts +2 -2
- package/dist/phone/index.js +247 -540
- package/dist/platform/AccessGate.vue.d.ts +50 -0
- package/dist/platform/index.d.ts +4 -2
- package/dist/platform/index.js +38 -35
- package/dist/platform/platform.d.ts +2 -2
- package/dist/platform/session.d.ts +22 -1
- package/dist/platform-hunMqFdB.js +255 -0
- package/dist/resource/index.js +8 -248
- package/dist/routeResource-DstM0hvf.js +82 -0
- package/dist/router/guards.d.ts +7 -1
- package/dist/router/index.js +23 -37
- package/dist/router/navigation.d.ts +1 -1
- package/dist/rowLayout-BI7a3Kom.js +603 -0
- package/dist/sectionIndex-BS0ic5W7.js +86 -0
- package/dist/{sections-LtxV5Mtk.js → sections-BEqW1dOc.js} +1 -1
- package/dist/shell/AccountMenuItem.vue.d.ts +4 -1
- package/dist/shell/BackofficeShell.vue.d.ts +2 -2
- package/dist/shell/ShellBrand.vue.d.ts +1 -1
- package/dist/shell/backofficeShell.d.ts +1 -1
- package/dist/shell/identity.d.ts +1 -1
- package/dist/shell/index.js +476 -532
- package/dist/state/Badge.vue.d.ts +17 -10
- package/dist/state/ProgressTrack.vue.d.ts +1 -1
- package/dist/state/hue.d.ts +8 -0
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.js +34 -31
- package/dist/state/useLoad.d.ts +41 -0
- package/dist/status-C9aXR-Jb.js +33 -0
- package/dist/styles.css +1 -1
- package/dist/suggestions-BJAqOj4c.js +138 -0
- package/dist/testing/app.d.ts +61 -0
- package/dist/testing/async.d.ts +12 -0
- package/dist/testing/collection.d.ts +18 -0
- package/dist/testing/format.d.ts +9 -0
- package/dist/testing/i18n.d.ts +16 -0
- package/dist/testing/index.d.ts +14 -0
- package/dist/testing/index.js +178 -0
- package/dist/testing/media.d.ts +23 -0
- package/dist/testing/platform.d.ts +40 -0
- package/dist/testing/transport.d.ts +40 -0
- package/dist/toast-D9Z5To38.js +13 -0
- package/dist/useCommand-BgRwnYlV.js +135 -0
- package/dist/{useDialog-wmyNx2j_.js → useDialog-CXR3hN0G.js} +1 -1
- package/dist/useLoad-CYRVx6HW.js +39 -0
- package/dist/useResourceForm-Bgc9jMcu.js +52 -0
- package/dist/useSaveChrome-chi6D3HY.js +25 -0
- package/dist/useSheetDrag-OsD6Eb6I.js +72 -0
- package/package.json +26 -5
- package/src/styles/theme.css +60 -0
- package/dist/Badge.vue_vue_type_script_setup_true_lang-DKc6ugmr.js +0 -31
- package/dist/Button.vue_vue_type_script_setup_true_lang-3f0emVNU.js +0 -141
- package/dist/NoAccess.vue_vue_type_script_setup_true_lang-OKW8pKYU.js +0 -78
- package/dist/SectionList.vue_vue_type_script_setup_true_lang-DGcKX_OJ.js +0 -230
- package/dist/SelectField.vue_vue_type_script_setup_true_lang-SyFWE33A.js +0 -422
- package/dist/Sheet.vue_vue_type_script_setup_true_lang-BLBD5ps8.js +0 -210
- package/dist/SwipeActions.vue_vue_type_script_setup_true_lang-CGTuEnTv.js +0 -243
- package/dist/chrome-D9pwD6iS.js +0 -101
- package/dist/dialogStack-DiTG1rZc.js +0 -26
- package/dist/environment-D3nozt9a.js +0 -75
- package/dist/feature-DyDtyMLU.js +0 -47
- package/dist/platform-jqlKVJ2e.js +0 -244
- package/dist/toast-BTeX0r66.js +0 -129
- /package/dist/{phone → internal}/flagLoaders.d.ts +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { inject as O, shallowRef as S, ref as p, computed as y, onBeforeUnmount as R } from "vue";
|
|
2
|
+
import { i as x } from "./error-CD7x0Jrz.js";
|
|
3
|
+
import { c as m } from "./options-BXkMR63B.js";
|
|
4
|
+
const W = Symbol("vue-core.recentChoices"), D = 5, j = (e) => {
|
|
5
|
+
if (typeof e != "object" || e === null) return !1;
|
|
6
|
+
const n = e;
|
|
7
|
+
return (typeof n.value == "string" || typeof n.value == "number") && typeof n.label == "string";
|
|
8
|
+
}, J = {
|
|
9
|
+
read(e) {
|
|
10
|
+
try {
|
|
11
|
+
const n = JSON.parse(localStorage.getItem(`vue-core.recent.${e}`) ?? "[]");
|
|
12
|
+
return Array.isArray(n) ? n.filter(j).slice(0, D) : [];
|
|
13
|
+
} catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
write(e, n) {
|
|
18
|
+
try {
|
|
19
|
+
localStorage.setItem(`vue-core.recent.${e}`, JSON.stringify(n));
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function _(e, n) {
|
|
25
|
+
const r = m(n.trim());
|
|
26
|
+
if (r === "") return { before: "", match: "", after: e };
|
|
27
|
+
let s = "";
|
|
28
|
+
const c = [];
|
|
29
|
+
let a = 0;
|
|
30
|
+
for (const d of e) {
|
|
31
|
+
const v = m(d);
|
|
32
|
+
for (let h = 0; h < v.length; h++) c.push(a);
|
|
33
|
+
s += v, a += d.length;
|
|
34
|
+
}
|
|
35
|
+
const o = s.indexOf(r);
|
|
36
|
+
if (o < 0) return { before: "", match: "", after: e };
|
|
37
|
+
const u = c[o] ?? 0, i = c[o + r.length] ?? e.length;
|
|
38
|
+
return { before: e.slice(0, u), match: e.slice(u, i), after: e.slice(i) };
|
|
39
|
+
}
|
|
40
|
+
function q(e, n) {
|
|
41
|
+
return e === "" || n.length <= e.length ? "" : n.toLocaleLowerCase().startsWith(e.toLocaleLowerCase()) ? n.slice(e.length) : "";
|
|
42
|
+
}
|
|
43
|
+
function K(e, n) {
|
|
44
|
+
const r = m(n.trim());
|
|
45
|
+
if (r === "") return [...e];
|
|
46
|
+
const s = [], c = [];
|
|
47
|
+
for (const a of e) {
|
|
48
|
+
const o = m(a.label);
|
|
49
|
+
o.startsWith(r) ? s.push(a) : (o.includes(r) || a.description !== void 0 && m(a.description).includes(r)) && c.push(a);
|
|
50
|
+
}
|
|
51
|
+
return [...s, ...c];
|
|
52
|
+
}
|
|
53
|
+
function z(e, n, r, s) {
|
|
54
|
+
return e && (n > 0 || r === "loading" || r === "failed" || r === "loaded" && s);
|
|
55
|
+
}
|
|
56
|
+
function P() {
|
|
57
|
+
const e = S([]), n = p("idle");
|
|
58
|
+
let r = 0, s = null;
|
|
59
|
+
function c() {
|
|
60
|
+
r++, s?.abort(), s = null;
|
|
61
|
+
}
|
|
62
|
+
async function a(o, u = (i) => i) {
|
|
63
|
+
c();
|
|
64
|
+
const i = r;
|
|
65
|
+
s = new AbortController(), n.value = "loading";
|
|
66
|
+
try {
|
|
67
|
+
const d = await o(s.signal);
|
|
68
|
+
if (i !== r) return;
|
|
69
|
+
e.value = u(d), n.value = "loaded";
|
|
70
|
+
} catch (d) {
|
|
71
|
+
if (i !== r || x(d)) return;
|
|
72
|
+
e.value = [], n.value = "failed";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { items: e, status: n, run: a, cancel: c };
|
|
76
|
+
}
|
|
77
|
+
function F(e) {
|
|
78
|
+
const n = O(W, J), r = P(), { items: s, status: c } = r, a = S([]), o = p(!1), u = p(0), i = p(!1);
|
|
79
|
+
let d = "", v = null;
|
|
80
|
+
const h = y(() => c.value === "idle" ? a.value : s.value), T = y(() => c.value === "idle" && a.value.length > 0), w = y(() => h.value[u.value]);
|
|
81
|
+
function g() {
|
|
82
|
+
r.cancel(), v && clearTimeout(v), v = null;
|
|
83
|
+
}
|
|
84
|
+
R(g);
|
|
85
|
+
function b(t) {
|
|
86
|
+
return u.value = 0, i.value = !1, t.slice(0, e.limit());
|
|
87
|
+
}
|
|
88
|
+
const E = (t, l) => r.run((f) => l(t, { signal: f }), b);
|
|
89
|
+
function L(t) {
|
|
90
|
+
d = t, g(), o.value = !0;
|
|
91
|
+
const l = e.source(), f = t.trim() === "";
|
|
92
|
+
if (!l || f && !e.listAllWhenEmpty || typeof l == "function" && t.trim().length < e.minLength()) {
|
|
93
|
+
c.value = "idle", s.value = [], u.value = 0, i.value = !1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
typeof l == "function" ? v = setTimeout(() => void E(t, l), e.debounce()) : (s.value = b(K(l, t)), c.value = "loaded");
|
|
97
|
+
}
|
|
98
|
+
function k(t) {
|
|
99
|
+
const l = e.recents();
|
|
100
|
+
a.value = l ? n.read(l) : [], L(t), o.value = h.value.length > 0;
|
|
101
|
+
}
|
|
102
|
+
function A() {
|
|
103
|
+
g(), o.value = !1, c.value === "loading" && (c.value = "idle");
|
|
104
|
+
}
|
|
105
|
+
function I(t) {
|
|
106
|
+
const l = e.recents();
|
|
107
|
+
if (!l) return;
|
|
108
|
+
const f = n.read(l).filter((N) => N.value !== t.value);
|
|
109
|
+
n.write(l, [{ value: t.value, label: t.label, ...t.description !== void 0 ? { description: t.description } : {} }, ...f].slice(0, D));
|
|
110
|
+
}
|
|
111
|
+
function C(t, l = !0) {
|
|
112
|
+
u.value = t, l && (i.value = !0);
|
|
113
|
+
}
|
|
114
|
+
function M(t, l) {
|
|
115
|
+
if (t.key === "Escape" && o.value)
|
|
116
|
+
t.stopPropagation(), t.preventDefault(), A();
|
|
117
|
+
else if (t.key === "ArrowDown" || t.key === "ArrowUp") {
|
|
118
|
+
if (t.preventDefault(), !o.value) {
|
|
119
|
+
k(d), o.value = !0;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const f = h.value.length - 1;
|
|
123
|
+
C(t.key === "ArrowDown" ? Math.min(u.value + 1, f) : Math.max(u.value - 1, 0));
|
|
124
|
+
} else if (t.key === "Enter" && o.value) {
|
|
125
|
+
const f = w.value;
|
|
126
|
+
f && !f.disabled && (i.value || !l.enterNeedsMove) && (t.preventDefault(), l.pick(f));
|
|
127
|
+
} else t.key === "Tab" && !t.shiftKey && o.value && l.complete?.() && t.preventDefault();
|
|
128
|
+
}
|
|
129
|
+
return { items: h, showingRecent: T, status: c, open: o, highlighted: u, moved: i, current: w, ask: L, show: k, close: A, cancel: g, remember: I, highlight: C, keydown: M };
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
P as a,
|
|
133
|
+
q as c,
|
|
134
|
+
z as l,
|
|
135
|
+
_ as m,
|
|
136
|
+
W as r,
|
|
137
|
+
F as u
|
|
138
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type App, type Plugin } from "vue";
|
|
2
|
+
import { type RouteRecordRaw, type Router } from "vue-router";
|
|
3
|
+
import { type Platform } from "../platform";
|
|
4
|
+
import { createTestI18n, type TestMessages } from "./i18n";
|
|
5
|
+
/**
|
|
6
|
+
* The route records with every page replaced by an empty stand-in (nested records still render
|
|
7
|
+
* their children), keeping names, paths, meta, redirects and guards: a view under test can link to
|
|
8
|
+
* and navigate among the application's real routes without loading the other pages.
|
|
9
|
+
*
|
|
10
|
+
* createTestApp({ routes: stubRoutes(ticketRoutes.records) })
|
|
11
|
+
*/
|
|
12
|
+
export declare function stubRoutes(records: readonly RouteRecordRaw[]): RouteRecordRaw[];
|
|
13
|
+
export interface TestAppOptions {
|
|
14
|
+
/** Default: `createTestPlatform()`, a signed-in user holding nothing. */
|
|
15
|
+
platform?: Platform;
|
|
16
|
+
/** The routes; default: one that matches every address with an empty page. */
|
|
17
|
+
routes?: readonly RouteRecordRaw[];
|
|
18
|
+
/** Where the router starts, query included; default `/`. */
|
|
19
|
+
location?: string;
|
|
20
|
+
/** Use this router instead of making one (`routes` and `location` are then not used). */
|
|
21
|
+
router?: Router;
|
|
22
|
+
/** Default `en`. */
|
|
23
|
+
locale?: string;
|
|
24
|
+
/** Your texts per locale, over the library's. */
|
|
25
|
+
messages?: TestMessages;
|
|
26
|
+
/** More plugins, installed last: provide a feature's context here (`{ install: (app) => app.provide(key, value) }`). */
|
|
27
|
+
plugins?: readonly Plugin[];
|
|
28
|
+
}
|
|
29
|
+
/** What a component needs around it to run as it does in the application. */
|
|
30
|
+
export interface TestApp {
|
|
31
|
+
/** For `render(Component, { global: { plugins: app.plugins } })` of @testing-library/vue, `mount` of @vue/test-utils, or `withSetup`. */
|
|
32
|
+
readonly plugins: readonly Plugin[];
|
|
33
|
+
readonly platform: Platform;
|
|
34
|
+
readonly router: Router;
|
|
35
|
+
readonly i18n: ReturnType<typeof createTestI18n>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The application's environment for a test: the platform, a memory-history router, vue-i18n with
|
|
39
|
+
* the library's texts and your own, and formatting that follows the locale. The router starts
|
|
40
|
+
* navigating to `location` when it is installed: `await app.router.isReady()` before asserting on
|
|
41
|
+
* what a route renders (or `await app.router.push(...)` to go elsewhere).
|
|
42
|
+
*
|
|
43
|
+
* const app = createTestApp({ platform: createTestPlatform({ permissions: ["tickets:view"] }), location: "/tickets" });
|
|
44
|
+
* render(TicketList, { global: { plugins: app.plugins } });
|
|
45
|
+
* await app.router.isReady();
|
|
46
|
+
*/
|
|
47
|
+
export declare function createTestApp(options?: TestAppOptions): TestApp;
|
|
48
|
+
/**
|
|
49
|
+
* Runs a composable inside a mounted component of an application (`environment`: a `createTestApp()`
|
|
50
|
+
* by default, or just `{ plugins }`), as it is used: injections, the router and `onScopeDispose`
|
|
51
|
+
* work. Unmount to stop what it started.
|
|
52
|
+
*
|
|
53
|
+
* const { result, unmount } = withSetup(() => useCollection(definition, { state: { kind: "memory" } }));
|
|
54
|
+
*/
|
|
55
|
+
export declare function withSetup<T>(setup: () => T, environment?: {
|
|
56
|
+
readonly plugins: readonly Plugin[];
|
|
57
|
+
}): {
|
|
58
|
+
result: T;
|
|
59
|
+
app: App;
|
|
60
|
+
unmount: () => void;
|
|
61
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** A promise you settle by hand: to make a request race or a slow answer deterministic. */
|
|
2
|
+
export interface Deferred<T> {
|
|
3
|
+
readonly promise: Promise<T>;
|
|
4
|
+
resolve(value: T): void;
|
|
5
|
+
reject(error: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
export declare function deferred<T>(): Deferred<T>;
|
|
8
|
+
/**
|
|
9
|
+
* Lets pending promises, timers of 0 ms, router navigations and Vue's update queue run: a macrotask
|
|
10
|
+
* and a render per round (`rounds`, default 5). For what a single `await nextTick()` does not reach.
|
|
11
|
+
*/
|
|
12
|
+
export declare function settle(rounds?: number): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CollectionQuery, ListPage, LoadContext } from "../collection";
|
|
2
|
+
/** One page of a list as a loader returns it: the rows and the counts a pager shows, from the rows alone (`overrides` for a page of many). */
|
|
3
|
+
export declare function listPage<Row>(rows: readonly Row[], overrides?: Partial<ListPage<Row>>): ListPage<Row>;
|
|
4
|
+
/**
|
|
5
|
+
* A collection loader that records every call (the query it was asked, the signal it was given) and
|
|
6
|
+
* answers from a function of the query, so a test can assert what a list asked the backend for.
|
|
7
|
+
*
|
|
8
|
+
* const { load, calls } = fakeLoader((query) => listPage(tickets));
|
|
9
|
+
* const list = defineCollection({ id: "tickets", stateVersion: 1, load, key: (ticket) => ticket.id, query: { sorts: [], filters: [] } });
|
|
10
|
+
* expect(calls[0]?.query.page).toBe(1);
|
|
11
|
+
*/
|
|
12
|
+
export declare function fakeLoader<Row>(answer: (query: CollectionQuery, context: LoadContext, call: number) => Promise<ListPage<Row>> | ListPage<Row>): {
|
|
13
|
+
load: (query: CollectionQuery, context: LoadContext) => Promise<ListPage<Row>>;
|
|
14
|
+
calls: {
|
|
15
|
+
query: CollectionQuery;
|
|
16
|
+
signal: AbortSignal;
|
|
17
|
+
}[];
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type I18n } from "vue-i18n";
|
|
2
|
+
/** Messages per locale: `{ en: { tickets: { title: "Tickets" } } }`. */
|
|
3
|
+
export type TestMessages = Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
4
|
+
export interface TestI18nOptions {
|
|
5
|
+
/** Default `en`. */
|
|
6
|
+
locale?: string;
|
|
7
|
+
/** Your texts, merged over the library's (`core.*`) per locale; a key you give wins. */
|
|
8
|
+
messages?: TestMessages;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A vue-i18n instance (composition API) with the library's messages in every locale it ships and
|
|
12
|
+
* yours merged on top, so a component under test says what it says in production.
|
|
13
|
+
*
|
|
14
|
+
* const i18n = createTestI18n({ messages: { en: { tickets: { title: "Tickets" } } } });
|
|
15
|
+
*/
|
|
16
|
+
export declare function createTestI18n(options?: TestI18nOptions): I18n<Record<string, unknown>, Record<string, unknown>, Record<string, unknown>, string, false>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { deferred, settle } from "./async";
|
|
2
|
+
export type { Deferred } from "./async";
|
|
3
|
+
export { createTestApp, stubRoutes, withSetup } from "./app";
|
|
4
|
+
export type { TestApp, TestAppOptions } from "./app";
|
|
5
|
+
export { fakeLoader, listPage } from "./collection";
|
|
6
|
+
export { testFormatting } from "./format";
|
|
7
|
+
export { createTestI18n } from "./i18n";
|
|
8
|
+
export type { TestI18nOptions, TestMessages } from "./i18n";
|
|
9
|
+
export { mockMedia } from "./media";
|
|
10
|
+
export type { MediaState } from "./media";
|
|
11
|
+
export { createTestPlatform, createTestSession, heldAccess } from "./platform";
|
|
12
|
+
export type { TestPlatformOptions, TestSessionOptions } from "./platform";
|
|
13
|
+
export { jsonResponse, routedTransport, scriptedTransport } from "./transport";
|
|
14
|
+
export type { Answer, RecordedCall } from "./transport";
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { nextTick as b, createApp as j, defineComponent as m, h as u } from "vue";
|
|
2
|
+
import { createMemoryHistory as P, createRouter as E, RouterView as $ } from "vue-router";
|
|
3
|
+
import { a as A, i as O } from "../platform-hunMqFdB.js";
|
|
4
|
+
import { createI18n as k } from "vue-i18n";
|
|
5
|
+
import { coreMessages as M } from "../i18n/index.js";
|
|
6
|
+
import { i as R, c as S } from "../format-B8mJm946.js";
|
|
7
|
+
function K() {
|
|
8
|
+
let e, t;
|
|
9
|
+
return { promise: new Promise((s, r) => {
|
|
10
|
+
e = s, t = r;
|
|
11
|
+
}), resolve: e, reject: t };
|
|
12
|
+
}
|
|
13
|
+
async function Q(e = 5) {
|
|
14
|
+
for (let t = 0; t < e; t++)
|
|
15
|
+
await new Promise((n) => setTimeout(n, 0)), await b();
|
|
16
|
+
}
|
|
17
|
+
const f = (e) => typeof e == "object" && e !== null && !Array.isArray(e);
|
|
18
|
+
function g(e, t) {
|
|
19
|
+
const n = { ...e };
|
|
20
|
+
for (const [s, r] of Object.entries(t)) {
|
|
21
|
+
const a = n[s];
|
|
22
|
+
n[s] = f(r) && f(a) ? g(a, r) : r;
|
|
23
|
+
}
|
|
24
|
+
return n;
|
|
25
|
+
}
|
|
26
|
+
function x(e = {}) {
|
|
27
|
+
const t = { ...M };
|
|
28
|
+
for (const [n, s] of Object.entries(e.messages ?? {})) t[n] = g(t[n] ?? {}, s);
|
|
29
|
+
return k({ legacy: !1, locale: e.locale ?? "en", fallbackLocale: "en", messages: t });
|
|
30
|
+
}
|
|
31
|
+
function L(e) {
|
|
32
|
+
return { install: (t) => R(t, S({ locale: () => e.global.locale.value })) };
|
|
33
|
+
}
|
|
34
|
+
function C(e, t, n = "all", s) {
|
|
35
|
+
const r = t === void 0 ? { level: e } : { level: e, id: t };
|
|
36
|
+
return { scope: r, qualifier: n, clauses: s ?? [{ scope: r, qualifier: n }] };
|
|
37
|
+
}
|
|
38
|
+
function B(e = {}) {
|
|
39
|
+
const { permissions: t = [] } = e, n = Array.isArray(t) ? Object.fromEntries(t.map((r) => [r, C("organization")])) : { ...t }, s = { root: e.root ?? !1, permissions: n, unavailable: e.unavailable ?? [] };
|
|
40
|
+
return {
|
|
41
|
+
user: e.user ?? { id: 1 },
|
|
42
|
+
expiresAt: e.expiresAt ?? null,
|
|
43
|
+
access: s,
|
|
44
|
+
...e.navigation ? { navigation: e.navigation } : {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const F = async (e, t) => {
|
|
48
|
+
throw new Error(`createTestPlatform: an unexpected request ${(t.method ?? "GET").toUpperCase()} ${e}. Pass a \`transport\` that answers it (scriptedTransport or routedTransport).`);
|
|
49
|
+
};
|
|
50
|
+
function U(e = {}) {
|
|
51
|
+
const { user: t, permissions: n, unavailable: s, root: r, navigation: a, expiresAt: o, transport: c, config: i, session: l, ...T } = e, p = t === null ? null : B({ user: t, permissions: n, unavailable: s, root: r, navigation: a, expiresAt: o }), y = l ?? { load: async () => p, signOut: async () => {
|
|
52
|
+
} }, d = A({
|
|
53
|
+
...T,
|
|
54
|
+
config: { apiBase: "", locale: "en", appName: "Test app", capabilities: [], ...i },
|
|
55
|
+
transport: c ?? F,
|
|
56
|
+
session: y
|
|
57
|
+
});
|
|
58
|
+
return !l && p && d.session.establish(p), d;
|
|
59
|
+
}
|
|
60
|
+
const z = m({ name: "TestBlankPage", render: () => u("div") }), h = m({ name: "TestRouteStub", render: () => u("div", [u($)]) });
|
|
61
|
+
function G(e) {
|
|
62
|
+
return e.map((t) => {
|
|
63
|
+
const { component: n, components: s, children: r, ...a } = t, o = { ...a };
|
|
64
|
+
return r && (o.children = G(r)), s ? o.components = Object.fromEntries(Object.keys(s).map((c) => [c, h])) : n !== void 0 && (o.component = h), o;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function H(e = {}) {
|
|
68
|
+
const t = e.platform ?? U();
|
|
69
|
+
let n = e.router;
|
|
70
|
+
if (!n) {
|
|
71
|
+
const a = P();
|
|
72
|
+
a.replace(e.location ?? "/"), n = E({ history: a, routes: [...e.routes ?? [{ path: "/:pathMatch(.*)*", component: z }]] });
|
|
73
|
+
}
|
|
74
|
+
const s = x({ locale: e.locale, messages: e.messages });
|
|
75
|
+
return { plugins: [n, s, L(s), { install: (a) => O(a, t) }, ...e.plugins ?? []], platform: t, router: n, i18n: s };
|
|
76
|
+
}
|
|
77
|
+
function W(e, t = H()) {
|
|
78
|
+
let n;
|
|
79
|
+
const s = j(
|
|
80
|
+
m({
|
|
81
|
+
setup() {
|
|
82
|
+
return n = e(), () => u("div");
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
for (const r of t.plugins) s.use(r);
|
|
87
|
+
return s.mount(document.createElement("div")), { result: n, app: s, unmount: () => s.unmount() };
|
|
88
|
+
}
|
|
89
|
+
function X(e, t = {}) {
|
|
90
|
+
return {
|
|
91
|
+
rows: e,
|
|
92
|
+
total: e.length,
|
|
93
|
+
page: 1,
|
|
94
|
+
pageSize: 25,
|
|
95
|
+
lastPage: e.length === 0 ? 0 : 1,
|
|
96
|
+
from: e.length === 0 ? 0 : 1,
|
|
97
|
+
to: e.length,
|
|
98
|
+
...t
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function Y(e) {
|
|
102
|
+
const t = [];
|
|
103
|
+
return { load: (s, r) => (t.push({ query: s, signal: r.signal }), Promise.resolve(e(s, r, t.length))), calls: t };
|
|
104
|
+
}
|
|
105
|
+
function Z(e = {}) {
|
|
106
|
+
const t = { compact: !1, narrow: !1, reducedMotion: !1, standalone: !1, ...e }, n = window.matchMedia, s = /* @__PURE__ */ new Set(), r = (o) => o.includes("prefers-reduced-motion") ? t.reducedMotion : o.includes("display-mode: standalone") ? t.standalone : o.includes("min-width: 48rem") ? !t.compact : o.includes("max-width: 1023px") ? t.narrow || t.compact : o.includes("pointer: coarse") || o.includes("max-width: 47.999rem") ? t.compact : !1, a = (o) => o.split(",").some(r);
|
|
107
|
+
return window.matchMedia = ((o) => {
|
|
108
|
+
const c = { query: o, last: a(o), listeners: /* @__PURE__ */ new Set() };
|
|
109
|
+
return s.add(c), {
|
|
110
|
+
media: o,
|
|
111
|
+
get matches() {
|
|
112
|
+
return a(o);
|
|
113
|
+
},
|
|
114
|
+
addEventListener: (i, l) => c.listeners.add(l),
|
|
115
|
+
removeEventListener: (i, l) => c.listeners.delete(l)
|
|
116
|
+
};
|
|
117
|
+
}), {
|
|
118
|
+
state: t,
|
|
119
|
+
set(o) {
|
|
120
|
+
Object.assign(t, o);
|
|
121
|
+
for (const c of s) {
|
|
122
|
+
const i = a(c.query);
|
|
123
|
+
i !== c.last && (c.last = i, c.listeners.forEach((l) => l()));
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
restore() {
|
|
127
|
+
window.matchMedia = n;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const q = (e, t, n = {}) => new Response(t === void 0 ? null : JSON.stringify(t), { status: e, headers: { "Content-Type": "application/json", ...n } }), w = (e, t) => ({
|
|
132
|
+
url: e,
|
|
133
|
+
method: (t.method ?? "GET").toUpperCase(),
|
|
134
|
+
headers: new Headers(t.headers),
|
|
135
|
+
init: t
|
|
136
|
+
});
|
|
137
|
+
async function v(e, t) {
|
|
138
|
+
if (e instanceof Error) throw e;
|
|
139
|
+
return typeof e == "function" ? e(t) : e.clone();
|
|
140
|
+
}
|
|
141
|
+
function ee(...e) {
|
|
142
|
+
const t = [], n = [...e];
|
|
143
|
+
return { transport: async (r, a) => {
|
|
144
|
+
const o = w(r, a);
|
|
145
|
+
t.push(o);
|
|
146
|
+
const c = n.length > 1 ? n.shift() : n[0];
|
|
147
|
+
if (c === void 0) throw new Error("scriptedTransport: no answer left");
|
|
148
|
+
return v(c, o);
|
|
149
|
+
}, calls: t };
|
|
150
|
+
}
|
|
151
|
+
function te(e) {
|
|
152
|
+
const t = [];
|
|
153
|
+
return { transport: async (s, r) => {
|
|
154
|
+
const a = w(s, r);
|
|
155
|
+
t.push(a);
|
|
156
|
+
const { pathname: o, search: c } = new URL(s, "http://test.invalid"), i = e[`${a.method} ${o}${c}`] ?? e[`${a.method} ${o}`];
|
|
157
|
+
if (i === void 0) throw new Error(`routedTransport: no route for ${a.method} ${o}${c}; it has ${Object.keys(e).join(", ") || "none"}`);
|
|
158
|
+
return v(i, a);
|
|
159
|
+
}, calls: t };
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
H as createTestApp,
|
|
163
|
+
x as createTestI18n,
|
|
164
|
+
U as createTestPlatform,
|
|
165
|
+
B as createTestSession,
|
|
166
|
+
K as deferred,
|
|
167
|
+
Y as fakeLoader,
|
|
168
|
+
C as heldAccess,
|
|
169
|
+
q as jsonResponse,
|
|
170
|
+
X as listPage,
|
|
171
|
+
Z as mockMedia,
|
|
172
|
+
te as routedTransport,
|
|
173
|
+
ee as scriptedTransport,
|
|
174
|
+
Q as settle,
|
|
175
|
+
G as stubRoutes,
|
|
176
|
+
L as testFormatting,
|
|
177
|
+
W as withSetup
|
|
178
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** What the mocked `matchMedia` answers. */
|
|
2
|
+
export interface MediaState {
|
|
3
|
+
/** Phones and touch-first screens (the `compact:` condition). */
|
|
4
|
+
compact: boolean;
|
|
5
|
+
/** Below 1024 px, phones and tablets: where lists turn into phone rows. */
|
|
6
|
+
narrow: boolean;
|
|
7
|
+
reducedMotion: boolean;
|
|
8
|
+
/** Running as an installed app (`display-mode: standalone`). */
|
|
9
|
+
standalone: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Replaces `window.matchMedia` for a test: the library's conditions (compact, narrow, reduced motion, standalone) are answered from
|
|
13
|
+
* `state`, everything else is false. Change `state` through `set` to fire `change` listeners.
|
|
14
|
+
* Returns `restore`: call it in `afterEach`.
|
|
15
|
+
*
|
|
16
|
+
* const media = mockMedia({ compact: true });
|
|
17
|
+
* afterEach(() => media.restore());
|
|
18
|
+
*/
|
|
19
|
+
export declare function mockMedia(initial?: Partial<MediaState>): {
|
|
20
|
+
state: MediaState;
|
|
21
|
+
set(next: Partial<MediaState>): void;
|
|
22
|
+
restore(): void;
|
|
23
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type AccessClause, type AccessQualifier, type BootstrapConfig, type HeldAccess, type NavigationNode, type Platform, type PlatformOptions, type SessionAdapter, type SessionSnapshot, type SessionUser } from "../platform";
|
|
2
|
+
import type { Transport } from "../client";
|
|
3
|
+
/**
|
|
4
|
+
* How a permission is held: at a level of your scope hierarchy (`organization`, `dealer`, ...) with an
|
|
5
|
+
* optional id, for `all` records, only the user's `own` or those of their `own_location`. For the
|
|
6
|
+
* `permissions` record of `createTestSession`; a plain permission name there means "everything, at the organization".
|
|
7
|
+
*/
|
|
8
|
+
export declare function heldAccess(level: string, id?: number, qualifier?: AccessQualifier, clauses?: readonly AccessClause[]): HeldAccess;
|
|
9
|
+
export interface TestSessionOptions<U extends SessionUser = SessionUser> {
|
|
10
|
+
/** Default `{ id: 1 }`. */
|
|
11
|
+
user?: U;
|
|
12
|
+
/** Permissions held at the organization for every record (names), or exactly how each is held (`heldAccess`). */
|
|
13
|
+
permissions?: readonly string[] | Readonly<Record<string, HeldAccess>>;
|
|
14
|
+
/** Granted by a role but switched off for the tenant: not held. */
|
|
15
|
+
unavailable?: readonly string[];
|
|
16
|
+
/** Some binding is at the root scope. */
|
|
17
|
+
root?: boolean;
|
|
18
|
+
navigation?: readonly NavigationNode[];
|
|
19
|
+
expiresAt?: Date | null;
|
|
20
|
+
}
|
|
21
|
+
/** What `/auth/me` would say for a user: for `session.establish(...)` mid-test, or an adapter that answers it. */
|
|
22
|
+
export declare function createTestSession<U extends SessionUser = SessionUser>(options?: TestSessionOptions<U>): SessionSnapshot<U>;
|
|
23
|
+
export interface TestPlatformOptions<U extends SessionUser = SessionUser> extends Omit<TestSessionOptions<U>, "user">, Omit<PlatformOptions<U, BootstrapConfig>, "config" | "transport" | "session"> {
|
|
24
|
+
/** `null`: nobody is signed in (the session answers "none" when asked). Default: the user of `createTestSession`. */
|
|
25
|
+
user?: U | null;
|
|
26
|
+
/** Answers the requests the code under test makes: `scriptedTransport` or `routedTransport`. Default: any request fails the test. */
|
|
27
|
+
transport?: Transport;
|
|
28
|
+
/** Fields of the bootstrap config over the test's (`apiBase: ""`, `locale: "en"`, `appName: "Test app"`). */
|
|
29
|
+
config?: Partial<BootstrapConfig>;
|
|
30
|
+
/** A session adapter of your own; then `user`, `permissions` and the like are not used and the session starts unasked. */
|
|
31
|
+
session?: SessionAdapter<U>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A platform for a test: an HTTP client over a fake transport, a session that is already signed in
|
|
35
|
+
* (no request) and the access it grants. Independent of every other platform, as production's.
|
|
36
|
+
*
|
|
37
|
+
* const platform = createTestPlatform({ user: { id: 7 }, permissions: ["tickets:view"], transport });
|
|
38
|
+
* platform.access.can("tickets:view"); // true, at once
|
|
39
|
+
*/
|
|
40
|
+
export declare function createTestPlatform<U extends SessionUser = SessionUser>(options?: TestPlatformOptions<U>): Platform<U>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Transport } from "../client";
|
|
2
|
+
/** One request a fake transport received. */
|
|
3
|
+
export interface RecordedCall {
|
|
4
|
+
/** The URL as the client sent it, with the API base and the query string. */
|
|
5
|
+
readonly url: string;
|
|
6
|
+
/** Upper case; `GET` when the client set none. */
|
|
7
|
+
readonly method: string;
|
|
8
|
+
readonly headers: Headers;
|
|
9
|
+
/** The request as `fetch` received it (body, signal). */
|
|
10
|
+
readonly init: RequestInit;
|
|
11
|
+
}
|
|
12
|
+
/** What a fake transport answers: a response (served again for every matching call), a failure to throw, or a function of the call. */
|
|
13
|
+
export type Answer = Response | Error | ((call: RecordedCall) => Response | Promise<Response>);
|
|
14
|
+
/** A JSON response, as go-core answers: `jsonResponse(404, { error: "…" })`. A body of `undefined` is an empty one (204). */
|
|
15
|
+
export declare const jsonResponse: (status: number, body?: unknown, headers?: Record<string, string>) => Response;
|
|
16
|
+
/**
|
|
17
|
+
* A transport answering from a queue, one answer per call in order (the last one repeats), and
|
|
18
|
+
* recording what it was sent. For a test about a sequence: a retry, a 401 then a renewal, a race.
|
|
19
|
+
*
|
|
20
|
+
* const { transport, calls } = scriptedTransport(jsonResponse(503, {}), jsonResponse(200, { id: 1 }));
|
|
21
|
+
*/
|
|
22
|
+
export declare function scriptedTransport(...answers: Answer[]): {
|
|
23
|
+
transport: Transport;
|
|
24
|
+
calls: RecordedCall[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A transport answering by route, whatever the order: keys are `"METHOD /path"` (the path with the
|
|
28
|
+
* API base, the query string optional: `"GET /api/v1/tickets"` matches `/api/v1/tickets?page=2` unless a
|
|
29
|
+
* key with that exact query exists). A request nothing matches fails the test with the routes it
|
|
30
|
+
* knows, so a view that asks for something unexpected is never answered by accident.
|
|
31
|
+
*
|
|
32
|
+
* const { transport, calls } = routedTransport({
|
|
33
|
+
* "GET /tickets": jsonResponse(200, { data: [] }),
|
|
34
|
+
* "POST /tickets": (call) => jsonResponse(201, { id: 7 }),
|
|
35
|
+
* });
|
|
36
|
+
*/
|
|
37
|
+
export declare function routedTransport(routes: Readonly<Record<string, Answer>>): {
|
|
38
|
+
transport: Transport;
|
|
39
|
+
calls: RecordedCall[];
|
|
40
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { toast as i } from "vue-sonner";
|
|
2
|
+
const t = {
|
|
3
|
+
success: (s, o) => i.success(s, o),
|
|
4
|
+
info: (s, o) => i.info(s, o),
|
|
5
|
+
warning: (s, o) => i.warning(s, o),
|
|
6
|
+
error: (s, o) => i.error(s, o),
|
|
7
|
+
loading: (s, o) => i.loading(s, o),
|
|
8
|
+
/** Dismisses one toast, or all of them without an id. */
|
|
9
|
+
dismiss: (s) => void i.dismiss(s)
|
|
10
|
+
};
|
|
11
|
+
export {
|
|
12
|
+
t
|
|
13
|
+
};
|