@multiplatform.one/frappe-ui 7.7.6 → 7.8.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/dist/cjs/ChartCard.native.js.map +1 -1
- package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
- package/dist/cjs/FileBrowser/index.native.js.map +1 -1
- package/dist/cjs/FileBrowser/types.native.js.map +1 -1
- package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
- package/dist/cjs/FormSidebar.native.js.map +1 -1
- package/dist/cjs/FrappeAssignment.native.js.map +1 -1
- package/dist/cjs/FrappeCalendar.cjs +20 -17
- package/dist/cjs/FrappeCalendar.native.js +22 -21
- package/dist/cjs/FrappeCalendar.native.js.map +1 -1
- package/dist/cjs/FrappeChartCard.native.js.map +1 -1
- package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
- package/dist/cjs/FrappeDashboard.native.js.map +1 -1
- package/dist/cjs/FrappeForm.cjs +1 -1
- package/dist/cjs/FrappeForm.native.js +2 -2
- package/dist/cjs/FrappeForm.native.js.map +1 -1
- package/dist/cjs/FrappeGantt.cjs +25 -34
- package/dist/cjs/FrappeGantt.native.js +27 -38
- package/dist/cjs/FrappeGantt.native.js.map +1 -1
- package/dist/cjs/FrappeImageView.cjs +4 -2
- package/dist/cjs/FrappeImageView.native.js +8 -4
- package/dist/cjs/FrappeImageView.native.js.map +1 -1
- package/dist/cjs/FrappeKPICard.cjs +26 -1
- package/dist/cjs/FrappeKPICard.native.js +26 -1
- package/dist/cjs/FrappeKPICard.native.js.map +1 -1
- package/dist/cjs/FrappeKanban.cjs +16 -17
- package/dist/cjs/FrappeKanban.native.js +18 -21
- package/dist/cjs/FrappeKanban.native.js.map +1 -1
- package/dist/cjs/FrappeLikedBy.cjs +1 -1
- package/dist/cjs/FrappeLikedBy.native.js +1 -1
- package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
- package/dist/cjs/FrappeList.cjs +2 -2
- package/dist/cjs/FrappeList.native.js +2 -2
- package/dist/cjs/FrappeList.native.js.map +1 -1
- package/dist/cjs/FrappeListView.native.js.map +1 -1
- package/dist/cjs/FrappeProvider.native.js.map +1 -1
- package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
- package/dist/cjs/FrappeReportBuilder.cjs +2 -2
- package/dist/cjs/FrappeReportBuilder.native.js +2 -2
- package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
- package/dist/cjs/FrappeReportView.native.js +3 -3
- package/dist/cjs/FrappeReportView.native.js.map +1 -1
- package/dist/cjs/FrappeTable.cjs +35 -38
- package/dist/cjs/FrappeTable.native.js +38 -39
- package/dist/cjs/FrappeTable.native.js.map +1 -1
- package/dist/cjs/FrappeTreeView.cjs +85 -50
- package/dist/cjs/FrappeTreeView.native.js +129 -50
- package/dist/cjs/FrappeTreeView.native.js.map +1 -1
- package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
- package/dist/cjs/commentActions.cjs +1 -1
- package/dist/cjs/commentActions.native.js +1 -1
- package/dist/cjs/commentActions.native.js.map +1 -1
- package/dist/cjs/components/attachments.native.js.map +1 -1
- package/dist/cjs/components/tags.native.js.map +1 -1
- package/dist/cjs/components/timeline.cjs +1 -1
- package/dist/cjs/components/timeline.native.js +1 -1
- package/dist/cjs/components/timeline.native.js.map +1 -1
- package/dist/cjs/dependsOn.native.js.map +1 -1
- package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
- package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
- package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
- package/dist/cjs/desk/DeskShell.cjs +2 -0
- package/dist/cjs/desk/DeskShell.native.js +2 -0
- package/dist/cjs/desk/DeskShell.native.js.map +1 -1
- package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
- package/dist/cjs/desk/awesomebar.cjs +1 -1
- package/dist/cjs/desk/awesomebar.native.js +1 -1
- package/dist/cjs/desk/awesomebar.native.js.map +1 -1
- package/dist/cjs/fieldOverrides.native.js.map +1 -1
- package/dist/cjs/fieldRegistry.native.js +31 -31
- package/dist/cjs/fieldRegistry.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
- package/dist/cjs/fields/Check/index.native.js.map +1 -1
- package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/cjs/fields/Color/index.native.js.map +1 -1
- package/dist/cjs/fields/Data/index.native.js.map +1 -1
- package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/cjs/fields/Date/types.native.js.map +1 -1
- package/dist/cjs/fields/Date/wire.native.js.map +1 -1
- package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
- package/dist/cjs/fields/Duration/index.native.js.map +1 -1
- package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
- package/dist/cjs/fields/FileUpload.native.js.map +1 -1
- package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
- package/dist/cjs/fields/HTML/index.native.js.map +1 -1
- package/dist/cjs/fields/Heading/index.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.native.js.map +1 -1
- package/dist/cjs/fields/Link.native.js.map +1 -1
- package/dist/cjs/fields/LinkTree.native.js.map +1 -1
- package/dist/cjs/fields/LongText/index.native.js.map +1 -1
- package/dist/cjs/fields/MentionInput/index.cjs +4 -1
- package/dist/cjs/fields/MentionInput/index.native.js +4 -1
- package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
- package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Password/index.native.js.map +1 -1
- package/dist/cjs/fields/Phone/index.native.js.map +1 -1
- package/dist/cjs/fields/Progress/index.native.js.map +1 -1
- package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/Rating/index.native.js.map +1 -1
- package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Signature/index.native.js.map +1 -1
- package/dist/cjs/fields/Slider/index.native.js.map +1 -1
- package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
- package/dist/cjs/fields/Switch/index.native.js.map +1 -1
- package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
- package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
- package/dist/cjs/filterFields.native.js.map +1 -1
- package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
- package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
- package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
- package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
- package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
- package/dist/cjs/formEngine/formActions.native.js.map +1 -1
- package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
- package/dist/cjs/formEngine/index.native.js.map +1 -1
- package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
- package/dist/cjs/frappeEventColor.native.js.map +1 -1
- package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
- package/dist/cjs/frappeUsers.native.js.map +1 -1
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.native.js +38 -34
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/liveErrors.native.js.map +1 -1
- package/dist/cjs/resolveControl.native.js.map +1 -1
- package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
- package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
- package/dist/cjs/schemaForm/index.cjs +10 -9
- package/dist/cjs/schemaForm/index.native.js +11 -10
- package/dist/cjs/schemaForm/index.native.js.map +1 -1
- package/dist/cjs/shared/devWarn.cjs +40 -0
- package/dist/cjs/shared/devWarn.native.js +45 -0
- package/dist/cjs/shared/devWarn.native.js.map +1 -0
- package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/cjs/syncError.native.js.map +1 -1
- package/dist/cjs/useFrappeAggregate.cjs +15 -8
- package/dist/cjs/useFrappeAggregate.native.js +15 -9
- package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
- package/dist/cjs/useFrappeFacets.cjs +10 -9
- package/dist/cjs/useFrappeFacets.native.js +10 -10
- package/dist/cjs/useFrappeFacets.native.js.map +1 -1
- package/dist/cjs/useFrappePagination.native.js.map +1 -1
- package/dist/cjs/useFrappeRows.cjs +113 -0
- package/dist/cjs/useFrappeRows.native.js +129 -0
- package/dist/cjs/useFrappeRows.native.js.map +1 -0
- package/dist/esm/ChartCard.native.js.map +1 -1
- package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
- package/dist/esm/FileBrowser/index.native.js.map +1 -1
- package/dist/esm/FileBrowser/types.native.js.map +1 -1
- package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
- package/dist/esm/FormSidebar.native.js.map +1 -1
- package/dist/esm/FrappeAssignment.native.js.map +1 -1
- package/dist/esm/FrappeCalendar.mjs +20 -17
- package/dist/esm/FrappeCalendar.mjs.map +1 -1
- package/dist/esm/FrappeCalendar.native.js +22 -21
- package/dist/esm/FrappeCalendar.native.js.map +1 -1
- package/dist/esm/FrappeChartCard.native.js.map +1 -1
- package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
- package/dist/esm/FrappeDashboard.native.js.map +1 -1
- package/dist/esm/FrappeForm.mjs +1 -1
- package/dist/esm/FrappeForm.mjs.map +1 -1
- package/dist/esm/FrappeForm.native.js +1 -1
- package/dist/esm/FrappeForm.native.js.map +1 -1
- package/dist/esm/FrappeGantt.mjs +27 -36
- package/dist/esm/FrappeGantt.mjs.map +1 -1
- package/dist/esm/FrappeGantt.native.js +29 -40
- package/dist/esm/FrappeGantt.native.js.map +1 -1
- package/dist/esm/FrappeImageView.mjs +5 -3
- package/dist/esm/FrappeImageView.mjs.map +1 -1
- package/dist/esm/FrappeImageView.native.js +9 -5
- package/dist/esm/FrappeImageView.native.js.map +1 -1
- package/dist/esm/FrappeKPICard.mjs +27 -2
- package/dist/esm/FrappeKPICard.mjs.map +1 -1
- package/dist/esm/FrappeKPICard.native.js +27 -2
- package/dist/esm/FrappeKPICard.native.js.map +1 -1
- package/dist/esm/FrappeKanban.mjs +16 -17
- package/dist/esm/FrappeKanban.mjs.map +1 -1
- package/dist/esm/FrappeKanban.native.js +18 -21
- package/dist/esm/FrappeKanban.native.js.map +1 -1
- package/dist/esm/FrappeLikedBy.mjs +1 -1
- package/dist/esm/FrappeLikedBy.mjs.map +1 -1
- package/dist/esm/FrappeLikedBy.native.js +1 -1
- package/dist/esm/FrappeLikedBy.native.js.map +1 -1
- package/dist/esm/FrappeList.mjs +2 -2
- package/dist/esm/FrappeList.mjs.map +1 -1
- package/dist/esm/FrappeList.native.js +2 -2
- package/dist/esm/FrappeList.native.js.map +1 -1
- package/dist/esm/FrappeListView.native.js.map +1 -1
- package/dist/esm/FrappeProvider.mjs.map +1 -1
- package/dist/esm/FrappeProvider.native.js.map +1 -1
- package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
- package/dist/esm/FrappeReportBuilder.mjs +2 -2
- package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
- package/dist/esm/FrappeReportBuilder.native.js +2 -2
- package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
- package/dist/esm/FrappeReportView.native.js.map +1 -1
- package/dist/esm/FrappeTable.mjs +36 -39
- package/dist/esm/FrappeTable.mjs.map +1 -1
- package/dist/esm/FrappeTable.native.js +39 -40
- package/dist/esm/FrappeTable.native.js.map +1 -1
- package/dist/esm/FrappeTreeView.mjs +89 -55
- package/dist/esm/FrappeTreeView.mjs.map +1 -1
- package/dist/esm/FrappeTreeView.native.js +133 -55
- package/dist/esm/FrappeTreeView.native.js.map +1 -1
- package/dist/esm/SyncErrorNotice.native.js.map +1 -1
- package/dist/esm/commentActions.mjs +1 -1
- package/dist/esm/commentActions.mjs.map +1 -1
- package/dist/esm/commentActions.native.js +1 -1
- package/dist/esm/commentActions.native.js.map +1 -1
- package/dist/esm/components/attachments.native.js.map +1 -1
- package/dist/esm/components/tags.native.js.map +1 -1
- package/dist/esm/components/timeline.mjs +1 -1
- package/dist/esm/components/timeline.mjs.map +1 -1
- package/dist/esm/components/timeline.native.js +1 -1
- package/dist/esm/components/timeline.native.js.map +1 -1
- package/dist/esm/dependsOn.native.js.map +1 -1
- package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
- package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
- package/dist/esm/desk/DeskListPage.native.js.map +1 -1
- package/dist/esm/desk/DeskShell.mjs +2 -0
- package/dist/esm/desk/DeskShell.mjs.map +1 -1
- package/dist/esm/desk/DeskShell.native.js +2 -0
- package/dist/esm/desk/DeskShell.native.js.map +1 -1
- package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
- package/dist/esm/desk/awesomebar.mjs +1 -1
- package/dist/esm/desk/awesomebar.mjs.map +1 -1
- package/dist/esm/desk/awesomebar.native.js +1 -1
- package/dist/esm/desk/awesomebar.native.js.map +1 -1
- package/dist/esm/fieldOverrides.native.js.map +1 -1
- package/dist/esm/fieldRegistry.native.js.map +1 -1
- package/dist/esm/fields/Barcode/index.native.js.map +1 -1
- package/dist/esm/fields/Check/index.native.js.map +1 -1
- package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/esm/fields/Color/index.native.js.map +1 -1
- package/dist/esm/fields/Data/index.native.js.map +1 -1
- package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/esm/fields/Date/types.native.js.map +1 -1
- package/dist/esm/fields/Date/wire.native.js.map +1 -1
- package/dist/esm/fields/DateRange/index.native.js.map +1 -1
- package/dist/esm/fields/Duration/index.native.js.map +1 -1
- package/dist/esm/fields/DynamicLink.native.js.map +1 -1
- package/dist/esm/fields/FileUpload.native.js.map +1 -1
- package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
- package/dist/esm/fields/HTML/index.native.js.map +1 -1
- package/dist/esm/fields/Heading/index.native.js.map +1 -1
- package/dist/esm/fields/Icon/index.native.js.map +1 -1
- package/dist/esm/fields/Link.native.js.map +1 -1
- package/dist/esm/fields/LinkTree.native.js.map +1 -1
- package/dist/esm/fields/LongText/index.native.js.map +1 -1
- package/dist/esm/fields/MentionInput/index.mjs +4 -1
- package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
- package/dist/esm/fields/MentionInput/index.native.js +4 -1
- package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
- package/dist/esm/fields/Numeric/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
- package/dist/esm/fields/Password/index.native.js.map +1 -1
- package/dist/esm/fields/Phone/index.native.js.map +1 -1
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/index.native.js.map +1 -1
- package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Signature/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/SmallText/index.native.js.map +1 -1
- package/dist/esm/fields/Switch/index.native.js.map +1 -1
- package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
- package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
- package/dist/esm/filterFields.native.js.map +1 -1
- package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
- package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
- package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
- package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
- package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
- package/dist/esm/formEngine/formActions.native.js.map +1 -1
- package/dist/esm/formEngine/formLayout.native.js.map +1 -1
- package/dist/esm/formEngine/index.native.js.map +1 -1
- package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
- package/dist/esm/frappeEventColor.native.js.map +1 -1
- package/dist/esm/frappeStoryTarget.native.js.map +1 -1
- package/dist/esm/frappeUsers.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/liveErrors.native.js.map +1 -1
- package/dist/esm/resolveControl.native.js.map +1 -1
- package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
- package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
- package/dist/esm/schemaForm/index.mjs +8 -7
- package/dist/esm/schemaForm/index.mjs.map +1 -1
- package/dist/esm/schemaForm/index.native.js +8 -7
- package/dist/esm/schemaForm/index.native.js.map +1 -1
- package/dist/esm/shared/devWarn.mjs +14 -0
- package/dist/esm/shared/devWarn.mjs.map +1 -0
- package/dist/esm/shared/devWarn.native.js +16 -0
- package/dist/esm/shared/devWarn.native.js.map +1 -0
- package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/esm/syncError.native.js.map +1 -1
- package/dist/esm/useFrappeAggregate.mjs +15 -8
- package/dist/esm/useFrappeAggregate.mjs.map +1 -1
- package/dist/esm/useFrappeAggregate.native.js +15 -9
- package/dist/esm/useFrappeAggregate.native.js.map +1 -1
- package/dist/esm/useFrappeFacets.mjs +10 -9
- package/dist/esm/useFrappeFacets.mjs.map +1 -1
- package/dist/esm/useFrappeFacets.native.js +10 -10
- package/dist/esm/useFrappeFacets.native.js.map +1 -1
- package/dist/esm/useFrappePagination.native.js.map +1 -1
- package/dist/esm/useFrappeRows.mjs +86 -0
- package/dist/esm/useFrappeRows.mjs.map +1 -0
- package/dist/esm/useFrappeRows.native.js +99 -0
- package/dist/esm/useFrappeRows.native.js.map +1 -0
- package/dist/jsx/FrappeCalendar.mjs +20 -17
- package/dist/jsx/FrappeCalendar.mjs.map +1 -1
- package/dist/jsx/FrappeCalendar.native.js +22 -21
- package/dist/jsx/FrappeCalendar.native.js.map +1 -1
- package/dist/jsx/FrappeForm.mjs +1 -1
- package/dist/jsx/FrappeForm.mjs.map +1 -1
- package/dist/jsx/FrappeForm.native.js +1 -1
- package/dist/jsx/FrappeForm.native.js.map +1 -1
- package/dist/jsx/FrappeGantt.mjs +27 -36
- package/dist/jsx/FrappeGantt.mjs.map +1 -1
- package/dist/jsx/FrappeGantt.native.js +27 -38
- package/dist/jsx/FrappeGantt.native.js.map +1 -1
- package/dist/jsx/FrappeImageView.mjs +5 -3
- package/dist/jsx/FrappeImageView.mjs.map +1 -1
- package/dist/jsx/FrappeImageView.native.js +8 -4
- package/dist/jsx/FrappeImageView.native.js.map +1 -1
- package/dist/jsx/FrappeKPICard.mjs +27 -2
- package/dist/jsx/FrappeKPICard.mjs.map +1 -1
- package/dist/jsx/FrappeKPICard.native.js +26 -1
- package/dist/jsx/FrappeKPICard.native.js.map +1 -1
- package/dist/jsx/FrappeKanban.mjs +16 -17
- package/dist/jsx/FrappeKanban.mjs.map +1 -1
- package/dist/jsx/FrappeKanban.native.js +18 -21
- package/dist/jsx/FrappeKanban.native.js.map +1 -1
- package/dist/jsx/FrappeLikedBy.mjs +1 -1
- package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
- package/dist/jsx/FrappeLikedBy.native.js +1 -1
- package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
- package/dist/jsx/FrappeList.mjs +2 -2
- package/dist/jsx/FrappeList.mjs.map +1 -1
- package/dist/jsx/FrappeList.native.js +2 -2
- package/dist/jsx/FrappeList.native.js.map +1 -1
- package/dist/jsx/FrappeProvider.mjs.map +1 -1
- package/dist/jsx/FrappeProvider.native.js.map +1 -1
- package/dist/jsx/FrappeReportBuilder.mjs +2 -2
- package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
- package/dist/jsx/FrappeReportBuilder.native.js +2 -2
- package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
- package/dist/jsx/FrappeTable.mjs +36 -39
- package/dist/jsx/FrappeTable.mjs.map +1 -1
- package/dist/jsx/FrappeTable.native.js +38 -39
- package/dist/jsx/FrappeTable.native.js.map +1 -1
- package/dist/jsx/FrappeTreeView.mjs +89 -55
- package/dist/jsx/FrappeTreeView.mjs.map +1 -1
- package/dist/jsx/FrappeTreeView.native.js +129 -50
- package/dist/jsx/FrappeTreeView.native.js.map +1 -1
- package/dist/jsx/commentActions.mjs +1 -1
- package/dist/jsx/commentActions.mjs.map +1 -1
- package/dist/jsx/commentActions.native.js +1 -1
- package/dist/jsx/commentActions.native.js.map +1 -1
- package/dist/jsx/components/timeline.mjs +1 -1
- package/dist/jsx/components/timeline.mjs.map +1 -1
- package/dist/jsx/components/timeline.native.js +1 -1
- package/dist/jsx/desk/DeskShell.mjs +2 -0
- package/dist/jsx/desk/DeskShell.mjs.map +1 -1
- package/dist/jsx/desk/DeskShell.native.js +2 -0
- package/dist/jsx/desk/DeskShell.native.js.map +1 -1
- package/dist/jsx/desk/awesomebar.mjs +1 -1
- package/dist/jsx/desk/awesomebar.mjs.map +1 -1
- package/dist/jsx/desk/awesomebar.native.js +1 -1
- package/dist/jsx/desk/awesomebar.native.js.map +1 -1
- package/dist/jsx/fields/MentionInput/index.mjs +4 -1
- package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
- package/dist/jsx/fields/MentionInput/index.native.js +4 -1
- package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
- package/dist/jsx/index.js +2 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +4 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/schemaForm/index.mjs +8 -7
- package/dist/jsx/schemaForm/index.mjs.map +1 -1
- package/dist/jsx/schemaForm/index.native.js +10 -9
- package/dist/jsx/schemaForm/index.native.js.map +1 -1
- package/dist/jsx/shared/devWarn.mjs +14 -0
- package/dist/jsx/shared/devWarn.mjs.map +1 -0
- package/dist/jsx/shared/devWarn.native.js +45 -0
- package/dist/jsx/shared/devWarn.native.js.map +1 -0
- package/dist/jsx/useFrappeAggregate.mjs +15 -8
- package/dist/jsx/useFrappeAggregate.mjs.map +1 -1
- package/dist/jsx/useFrappeAggregate.native.js +15 -9
- package/dist/jsx/useFrappeAggregate.native.js.map +1 -1
- package/dist/jsx/useFrappeFacets.mjs +10 -9
- package/dist/jsx/useFrappeFacets.mjs.map +1 -1
- package/dist/jsx/useFrappeFacets.native.js +10 -10
- package/dist/jsx/useFrappeFacets.native.js.map +1 -1
- package/dist/jsx/useFrappeRows.mjs +86 -0
- package/dist/jsx/useFrappeRows.mjs.map +1 -0
- package/dist/jsx/useFrappeRows.native.js +129 -0
- package/dist/jsx/useFrappeRows.native.js.map +1 -0
- package/package.json +17 -16
- package/src/FileBrowser/FileBrowser.spec.tsx +11 -1
- package/src/FrappeCalendar.tsx +25 -22
- package/src/FrappeForm.tsx +7 -3
- package/src/FrappeGantt.tsx +29 -39
- package/src/FrappeImageView.tsx +5 -3
- package/src/FrappeKPICard.spec.tsx +128 -0
- package/src/FrappeKPICard.tsx +44 -4
- package/src/FrappeKanban.tsx +24 -17
- package/src/FrappeLikedBy.tsx +1 -1
- package/src/FrappeList.tsx +3 -2
- package/src/FrappeProvider.fixturesOnly.spec.tsx +129 -0
- package/src/FrappeProvider.tsx +16 -6
- package/src/FrappeReportBuilder.tsx +4 -2
- package/src/FrappeTable.autoHeight.spec.tsx +142 -0
- package/src/FrappeTable.rowAccumulator.spec.tsx +110 -0
- package/src/FrappeTable.tsx +75 -48
- package/src/FrappeTreeView.stories.tsx +59 -0
- package/src/FrappeTreeView.tsx +166 -56
- package/src/commentActions.ts +1 -1
- package/src/components/timeline.tsx +1 -1
- package/src/desk/DeskShell.tsx +2 -0
- package/src/desk/awesomebar.tsx +5 -2
- package/src/fields/CodeEditor/CodeEditor.spec.tsx +10 -9
- package/src/fields/Date/typeParity.spec.tsx +19 -9
- package/src/fields/Duration/Duration.spec.tsx +73 -0
- package/src/fields/MentionInput/MentionInput.spec.tsx +110 -0
- package/src/fields/MentionInput/index.tsx +4 -1
- package/src/fields/Password/index.tsx +1 -1
- package/src/fields/Progress/Progress.spec.tsx +9 -0
- package/src/fields/RadioGroup/RadioGroup.spec.tsx +93 -0
- package/src/fields/Signature/Signature.spec.tsx +105 -0
- package/src/fields/Slider/Slider.spec.tsx +73 -0
- package/src/fields/Switch/Switch.spec.tsx +65 -0
- package/src/fields/TextEditor/TextEditor.spec.tsx +2 -3
- package/src/fields/TextEditor/TextEditor.stories.tsx +31 -1
- package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +110 -0
- package/src/frappeViews.designLaw.spec.ts +11 -7
- package/src/index.ts +13 -0
- package/src/schemaForm/index.tsx +6 -7
- package/src/shared/devWarn.ts +42 -0
- package/src/useFrappeAggregate.ts +17 -11
- package/src/useFrappeFacets.ts +17 -10
- package/src/useFrappeRows.spec.tsx +176 -0
- package/src/useFrappeRows.ts +293 -0
- package/types/FrappeCalendar.d.ts.map +1 -1
- package/types/FrappeForm.d.ts +6 -2
- package/types/FrappeForm.d.ts.map +1 -1
- package/types/FrappeGantt.d.ts.map +1 -1
- package/types/FrappeImageView.d.ts.map +1 -1
- package/types/FrappeKPICard.d.ts +9 -1
- package/types/FrappeKPICard.d.ts.map +1 -1
- package/types/FrappeKanban.d.ts.map +1 -1
- package/types/FrappeList.d.ts.map +1 -1
- package/types/FrappeProvider.d.ts +16 -6
- package/types/FrappeProvider.d.ts.map +1 -1
- package/types/FrappeReportBuilder.d.ts.map +1 -1
- package/types/FrappeTable.d.ts +20 -1
- package/types/FrappeTable.d.ts.map +1 -1
- package/types/FrappeTreeView.d.ts +38 -1
- package/types/FrappeTreeView.d.ts.map +1 -1
- package/types/desk/DeskShell.d.ts.map +1 -1
- package/types/desk/awesomebar.d.ts.map +1 -1
- package/types/fields/MentionInput/index.d.ts.map +1 -1
- package/types/fields/Password/index.d.ts +1 -1
- package/types/fields/Password/index.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/schemaForm/index.d.ts.map +1 -1
- package/types/shared/devWarn.d.ts +23 -0
- package/types/shared/devWarn.d.ts.map +1 -0
- package/types/useFrappeAggregate.d.ts +2 -1
- package/types/useFrappeAggregate.d.ts.map +1 -1
- package/types/useFrappeFacets.d.ts +2 -1
- package/types/useFrappeFacets.d.ts.map +1 -1
- package/types/useFrappeRows.d.ts +186 -0
- package/types/useFrappeRows.d.ts.map +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MentionInputField contract specs. The registry hands `value` and `onChange`
|
|
3
|
+
* straight to this adapter (MentionAdapter in fieldRegistry). The failure
|
|
4
|
+
* mode of a thin adapter is dropping those two, so a saved comment never
|
|
5
|
+
* paints and a typed comment never emits (LC-14). Pin the hop.
|
|
6
|
+
*/
|
|
7
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
8
|
+
import { act, cleanup, fireEvent } from "@testing-library/react";
|
|
9
|
+
import type React from "react";
|
|
10
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
11
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
12
|
+
import { MentionInputField, type MentionValue } from ".";
|
|
13
|
+
|
|
14
|
+
afterEach(cleanup);
|
|
15
|
+
|
|
16
|
+
const mentions = [{ trigger: "@", data: [{ id: "u1", display: "Ada" }] }];
|
|
17
|
+
|
|
18
|
+
const seeded: MentionValue = { text: "hello ada", mentions: [] };
|
|
19
|
+
|
|
20
|
+
const textarea = (container: HTMLElement) =>
|
|
21
|
+
container.querySelector("textarea") as HTMLTextAreaElement | null;
|
|
22
|
+
|
|
23
|
+
describe("MentionInputField composes the forms MentionInput", () => {
|
|
24
|
+
it("paints a controlled value onto the textarea", () => {
|
|
25
|
+
const result = renderWithProviders(
|
|
26
|
+
<MentionInputField label="Comment" mentions={mentions} value={seeded} onChange={() => {}} />,
|
|
27
|
+
);
|
|
28
|
+
expect(textarea(result.container)?.value).toBe("hello ada");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("emits a MentionValue through canonical onChange", async () => {
|
|
32
|
+
const onChange = vi.fn();
|
|
33
|
+
const result = renderWithProviders(
|
|
34
|
+
<MentionInputField
|
|
35
|
+
label="Comment"
|
|
36
|
+
mentions={mentions}
|
|
37
|
+
value={{ text: "", mentions: [] }}
|
|
38
|
+
onChange={onChange}
|
|
39
|
+
/>,
|
|
40
|
+
);
|
|
41
|
+
await act(async () => {
|
|
42
|
+
fireEvent.change(textarea(result.container) as HTMLTextAreaElement, {
|
|
43
|
+
target: { value: "typed" },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
expect(onChange).toHaveBeenCalled();
|
|
47
|
+
const emitted = onChange.mock.calls.at(-1)?.[0] as MentionValue;
|
|
48
|
+
expect(emitted.text).toBe("typed");
|
|
49
|
+
expect(Array.isArray(emitted.mentions)).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("forwards disabled onto the textarea", () => {
|
|
53
|
+
const result = renderWithProviders(
|
|
54
|
+
<MentionInputField
|
|
55
|
+
label="Comment"
|
|
56
|
+
mentions={mentions}
|
|
57
|
+
value={seeded}
|
|
58
|
+
disabled
|
|
59
|
+
onChange={() => {}}
|
|
60
|
+
/>,
|
|
61
|
+
);
|
|
62
|
+
const el = textarea(result.container);
|
|
63
|
+
expect(el?.disabled || el?.getAttribute("aria-disabled") === "true").toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("forwards readOnly onto the textarea", () => {
|
|
67
|
+
const result = renderWithProviders(
|
|
68
|
+
<MentionInputField
|
|
69
|
+
label="Comment"
|
|
70
|
+
mentions={mentions}
|
|
71
|
+
value={seeded}
|
|
72
|
+
readOnly
|
|
73
|
+
onChange={() => {}}
|
|
74
|
+
/>,
|
|
75
|
+
);
|
|
76
|
+
const el = textarea(result.container);
|
|
77
|
+
expect(el?.readOnly || el?.getAttribute("aria-readonly") === "true").toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("shows the label and error", () => {
|
|
81
|
+
const result = renderWithProviders(
|
|
82
|
+
<MentionInputField
|
|
83
|
+
label="Comment"
|
|
84
|
+
mentions={mentions}
|
|
85
|
+
value={seeded}
|
|
86
|
+
error="too short"
|
|
87
|
+
onChange={() => {}}
|
|
88
|
+
/>,
|
|
89
|
+
);
|
|
90
|
+
expect(result.container.textContent).toContain("Comment");
|
|
91
|
+
expect(result.container.textContent).toContain("too short");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("registry resolution (Mention fieldtype)", () => {
|
|
96
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
97
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
it("resolves 'Mention' to MentionInputField and hands value through", () => {
|
|
101
|
+
const Component = getFieldComponent("Mention")!;
|
|
102
|
+
expect(Component).toBeTruthy();
|
|
103
|
+
const element = (Component as Function)(
|
|
104
|
+
propsFor({ value: "hello ada", label: "Comment" }),
|
|
105
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
106
|
+
expect(element.type).toBe(MentionInputField);
|
|
107
|
+
expect(element.props.value).toBe("hello ada");
|
|
108
|
+
expect(element.props.label).toBe("Comment");
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -79,7 +79,8 @@ export function MentionInputField<
|
|
|
79
79
|
_preserveValue,
|
|
80
80
|
validators,
|
|
81
81
|
disabled,
|
|
82
|
-
|
|
82
|
+
value,
|
|
83
|
+
onChange,
|
|
83
84
|
mentions,
|
|
84
85
|
placeholder,
|
|
85
86
|
onMentionSelect,
|
|
@@ -103,6 +104,8 @@ export function MentionInputField<
|
|
|
103
104
|
id={fieldProps.id}
|
|
104
105
|
size={fieldProps.size}
|
|
105
106
|
disabled={disabled}
|
|
107
|
+
value={value}
|
|
108
|
+
onChange={onChange}
|
|
106
109
|
mentions={mentions ?? []}
|
|
107
110
|
placeholder={placeholder}
|
|
108
111
|
onMentionSelect={onMentionSelect}
|
|
@@ -57,6 +57,15 @@ describe("ProgressField chrome", () => {
|
|
|
57
57
|
expect(container.firstElementChild).toBeTruthy();
|
|
58
58
|
expect(container.textContent).toContain("Completion");
|
|
59
59
|
});
|
|
60
|
+
|
|
61
|
+
it("forwards the controlled value onto the progressbar", () => {
|
|
62
|
+
const { container } = renderWithProviders(
|
|
63
|
+
<ProgressField label="Completion" value={65} max={100} />,
|
|
64
|
+
);
|
|
65
|
+
expect(container.querySelector("[role='progressbar']")?.getAttribute("aria-valuenow")).toBe(
|
|
66
|
+
"65",
|
|
67
|
+
);
|
|
68
|
+
});
|
|
60
69
|
});
|
|
61
70
|
|
|
62
71
|
/**
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RadioGroupField contract specs. The adapter maps `onChange` onto the forms
|
|
3
|
+
* RadioGroup's `onValueChange`. Pin that value, onChange, disabled, label
|
|
4
|
+
* and error survive the hop.
|
|
5
|
+
*/
|
|
6
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
7
|
+
import { act, cleanup, fireEvent } from "@testing-library/react";
|
|
8
|
+
import type React from "react";
|
|
9
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
11
|
+
import { RadioGroupField } from ".";
|
|
12
|
+
|
|
13
|
+
afterEach(cleanup);
|
|
14
|
+
|
|
15
|
+
const options = [
|
|
16
|
+
{ label: "Red", value: "red" },
|
|
17
|
+
{ label: "Blue", value: "blue" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const radios = (container: HTMLElement) =>
|
|
21
|
+
Array.from(container.querySelectorAll('[role="radio"]')) as HTMLElement[];
|
|
22
|
+
|
|
23
|
+
describe("RadioGroupField composes the forms RadioGroup", () => {
|
|
24
|
+
it("paints a controlled value onto the matching radio", () => {
|
|
25
|
+
const result = renderWithProviders(
|
|
26
|
+
<RadioGroupField label="Color" value="blue" options={options} onChange={() => {}} />,
|
|
27
|
+
);
|
|
28
|
+
const all = radios(result.container);
|
|
29
|
+
const checked = all.find((el) => el.getAttribute("aria-checked") === "true");
|
|
30
|
+
expect(checked).toBeTruthy();
|
|
31
|
+
// option order is Red, Blue — the disc itself has no text
|
|
32
|
+
expect(checked).toBe(all[1]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("emits the option value through canonical onChange", async () => {
|
|
36
|
+
const onChange = vi.fn();
|
|
37
|
+
const result = renderWithProviders(
|
|
38
|
+
<RadioGroupField label="Color" value="red" options={options} onChange={onChange} />,
|
|
39
|
+
);
|
|
40
|
+
const blue = radios(result.container).find((el) => (el.textContent || "").includes("Blue"));
|
|
41
|
+
expect(blue || radios(result.container)[1]).toBeTruthy();
|
|
42
|
+
await act(async () => {
|
|
43
|
+
fireEvent.click(blue ?? radios(result.container)[1]);
|
|
44
|
+
});
|
|
45
|
+
expect(onChange).toHaveBeenCalledWith("blue");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("forwards disabled onto the radios", () => {
|
|
49
|
+
const result = renderWithProviders(
|
|
50
|
+
<RadioGroupField label="Color" value="red" options={options} disabled onChange={() => {}} />,
|
|
51
|
+
);
|
|
52
|
+
const el = radios(result.container)[0];
|
|
53
|
+
expect(el?.getAttribute("aria-disabled") === "true" || el?.hasAttribute("disabled")).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("shows the label and error", () => {
|
|
57
|
+
const result = renderWithProviders(
|
|
58
|
+
<RadioGroupField
|
|
59
|
+
label="Color"
|
|
60
|
+
value="red"
|
|
61
|
+
options={options}
|
|
62
|
+
error="pick one"
|
|
63
|
+
onChange={() => {}}
|
|
64
|
+
/>,
|
|
65
|
+
);
|
|
66
|
+
expect(result.container.textContent).toContain("Color");
|
|
67
|
+
expect(result.container.textContent).toContain("pick one");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("registry resolution (Radio fieldtype)", () => {
|
|
72
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
73
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
it("resolves 'Radio' to RadioGroupField and splits df.options on newlines", () => {
|
|
77
|
+
const Component = getFieldComponent("Radio")!;
|
|
78
|
+
const element = (Component as Function)(
|
|
79
|
+
propsFor({
|
|
80
|
+
value: "Red",
|
|
81
|
+
label: "Color",
|
|
82
|
+
fieldMeta: { options: "Red\nBlue" },
|
|
83
|
+
} as Partial<FieldRenderProps>),
|
|
84
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
85
|
+
expect(element.type).toBe(RadioGroupField);
|
|
86
|
+
expect(element.props.value).toBe("Red");
|
|
87
|
+
expect(element.props.label).toBe("Color");
|
|
88
|
+
expect(element.props.options).toEqual([
|
|
89
|
+
{ label: "Red", value: "Red" },
|
|
90
|
+
{ label: "Blue", value: "Blue" },
|
|
91
|
+
]);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signature adapter contract specs. The Frappe Signature field stores a
|
|
3
|
+
* data URL; this adapter must hand value / onChange / disabled / label /
|
|
4
|
+
* error to the forms Signature pad. Drawing lives in the forms spec.
|
|
5
|
+
*/
|
|
6
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
7
|
+
import { cleanup, fireEvent } from "@testing-library/react";
|
|
8
|
+
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
9
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
10
|
+
import type React from "react";
|
|
11
|
+
import { Signature } from ".";
|
|
12
|
+
|
|
13
|
+
function encodeSignature(strokes: number[][][]): string {
|
|
14
|
+
const json = JSON.stringify({ v: 2, s: strokes });
|
|
15
|
+
return `data:application/json;base64,${btoa(json)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const inkedValue = encodeSignature([
|
|
19
|
+
[
|
|
20
|
+
[0.1, 0.2, 0.5],
|
|
21
|
+
[0.4, 0.3, 0.5],
|
|
22
|
+
[0.7, 0.25, 0.5],
|
|
23
|
+
],
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
function getPad(container: HTMLElement): HTMLElement {
|
|
27
|
+
const label = container.querySelector("label[for]") as HTMLLabelElement | null;
|
|
28
|
+
const id = label?.htmlFor;
|
|
29
|
+
const pad = id ? (container.querySelector(`#${CSS.escape(id)}`) as HTMLElement | null) : null;
|
|
30
|
+
if (!pad) throw new Error("signature pad not found");
|
|
31
|
+
return pad;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
beforeAll(() => {
|
|
35
|
+
HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
|
|
36
|
+
clearRect: vi.fn(),
|
|
37
|
+
beginPath: vi.fn(),
|
|
38
|
+
moveTo: vi.fn(),
|
|
39
|
+
lineTo: vi.fn(),
|
|
40
|
+
stroke: vi.fn(),
|
|
41
|
+
fillRect: vi.fn(),
|
|
42
|
+
drawImage: vi.fn(),
|
|
43
|
+
})) as unknown as typeof HTMLCanvasElement.prototype.getContext;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterEach(cleanup);
|
|
47
|
+
|
|
48
|
+
describe("Signature composes the forms Signature", () => {
|
|
49
|
+
it("paints a controlled value as a signed pad", () => {
|
|
50
|
+
const result = renderWithProviders(
|
|
51
|
+
<Signature label="Sign here" value={inkedValue} onChange={() => {}} />,
|
|
52
|
+
);
|
|
53
|
+
expect(getPad(result.container).getAttribute("data-signed")).toBe("true");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("emits an empty string through canonical onChange on Delete", () => {
|
|
57
|
+
const onChange = vi.fn();
|
|
58
|
+
const result = renderWithProviders(
|
|
59
|
+
<Signature label="Sign here" value={inkedValue} onChange={onChange} />,
|
|
60
|
+
);
|
|
61
|
+
const pad = getPad(result.container);
|
|
62
|
+
fireEvent.focus(pad);
|
|
63
|
+
fireEvent.keyDown(pad, { key: "Delete" });
|
|
64
|
+
expect(onChange).toHaveBeenCalledWith("");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("forwards readOnly onto the pad", () => {
|
|
68
|
+
const result = renderWithProviders(
|
|
69
|
+
<Signature label="Sign here" value={inkedValue} readOnly onChange={() => {}} />,
|
|
70
|
+
);
|
|
71
|
+
expect(getPad(result.container).getAttribute("aria-readonly")).toBe("true");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("forwards disabled onto the pad", () => {
|
|
75
|
+
const result = renderWithProviders(
|
|
76
|
+
<Signature label="Sign here" value={inkedValue} disabled onChange={() => {}} />,
|
|
77
|
+
);
|
|
78
|
+
const pad = getPad(result.container);
|
|
79
|
+
expect(pad.getAttribute("aria-disabled") === "true" || pad.hasAttribute("disabled")).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("shows the label and error", () => {
|
|
83
|
+
const result = renderWithProviders(
|
|
84
|
+
<Signature label="Sign here" value="" error="signature required" onChange={() => {}} />,
|
|
85
|
+
);
|
|
86
|
+
expect(result.container.textContent).toContain("Sign here");
|
|
87
|
+
expect(result.container.textContent).toContain("signature required");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("registry resolution (Signature fieldtype)", () => {
|
|
92
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
93
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
it("resolves 'Signature' to the Signature adapter and hands value through", () => {
|
|
97
|
+
const Component = getFieldComponent("Signature")!;
|
|
98
|
+
const element = (Component as Function)(
|
|
99
|
+
propsFor({ value: inkedValue, label: "Sign here" }),
|
|
100
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
101
|
+
expect(element.type).toBe(Signature);
|
|
102
|
+
expect(element.props.value).toBe(inkedValue);
|
|
103
|
+
expect(element.props.label).toBe("Sign here");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SliderField contract specs. The adapter wraps a scalar number as the
|
|
3
|
+
* forms Slider's `[number]` tuple. Pin that value, onChange, disabled,
|
|
4
|
+
* label and error survive the hop.
|
|
5
|
+
*/
|
|
6
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
7
|
+
import { cleanup, fireEvent } from "@testing-library/react";
|
|
8
|
+
import type React from "react";
|
|
9
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
11
|
+
import { SliderField } from ".";
|
|
12
|
+
|
|
13
|
+
afterEach(cleanup);
|
|
14
|
+
|
|
15
|
+
const thumb = (container: HTMLElement) =>
|
|
16
|
+
container.querySelector('[role="slider"]') as HTMLElement | null;
|
|
17
|
+
|
|
18
|
+
describe("SliderField composes the forms Slider", () => {
|
|
19
|
+
it("paints a controlled value onto the thumb", () => {
|
|
20
|
+
const result = renderWithProviders(
|
|
21
|
+
<SliderField label="Volume" value={40} min={0} max={100} onChange={() => {}} />,
|
|
22
|
+
);
|
|
23
|
+
expect(thumb(result.container)?.getAttribute("aria-valuenow")).toBe("40");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("emits a scalar through canonical onChange", () => {
|
|
27
|
+
const onChange = vi.fn();
|
|
28
|
+
const result = renderWithProviders(
|
|
29
|
+
<SliderField label="Volume" value={40} min={0} max={100} step={1} onChange={onChange} />,
|
|
30
|
+
);
|
|
31
|
+
const el = thumb(result.container) as HTMLElement;
|
|
32
|
+
el.focus();
|
|
33
|
+
fireEvent.keyDown(el, { key: "ArrowRight" });
|
|
34
|
+
expect(onChange).toHaveBeenCalled();
|
|
35
|
+
expect(typeof onChange.mock.calls.at(-1)?.[0]).toBe("number");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("forwards disabled onto the thumb", () => {
|
|
39
|
+
const result = renderWithProviders(
|
|
40
|
+
<SliderField label="Volume" value={40} disabled onChange={() => {}} />,
|
|
41
|
+
);
|
|
42
|
+
const el = thumb(result.container);
|
|
43
|
+
const disabledMarker =
|
|
44
|
+
el?.getAttribute("aria-disabled") === "true" ||
|
|
45
|
+
el?.hasAttribute("data-disabled") ||
|
|
46
|
+
Boolean(el?.closest("[data-disabled]"));
|
|
47
|
+
expect(disabledMarker).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("shows the label and error", () => {
|
|
51
|
+
const result = renderWithProviders(
|
|
52
|
+
<SliderField label="Volume" value={40} error="out of range" onChange={() => {}} />,
|
|
53
|
+
);
|
|
54
|
+
expect(result.container.textContent).toContain("Volume");
|
|
55
|
+
expect(result.container.textContent).toContain("out of range");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("registry resolution (Slider fieldtype)", () => {
|
|
60
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
61
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
it("resolves 'Slider' to SliderField and coerces a non-number to 0", () => {
|
|
65
|
+
const Component = getFieldComponent("Slider")!;
|
|
66
|
+
const element = (Component as Function)(
|
|
67
|
+
propsFor({ value: "nope", label: "Volume" }),
|
|
68
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
69
|
+
expect(element.type).toBe(SliderField);
|
|
70
|
+
expect(element.props.value).toBe(0);
|
|
71
|
+
expect(element.props.label).toBe("Volume");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SwitchField contract specs. Frappe Switch is 1/0 in the doc; this adapter
|
|
3
|
+
* maps that onto the forms Switch's boolean checked/onCheckedChange. Pin
|
|
4
|
+
* that value, onChange, disabled, label and error survive the hop.
|
|
5
|
+
*/
|
|
6
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
7
|
+
import { act, cleanup, fireEvent } from "@testing-library/react";
|
|
8
|
+
import type React from "react";
|
|
9
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
11
|
+
import { SwitchField } from ".";
|
|
12
|
+
|
|
13
|
+
afterEach(cleanup);
|
|
14
|
+
|
|
15
|
+
describe("SwitchField composes the forms Switch", () => {
|
|
16
|
+
it("paints a controlled true value as aria-checked=true", () => {
|
|
17
|
+
const result = renderWithProviders(
|
|
18
|
+
<SwitchField label="Enabled" value={true} onChange={() => {}} />,
|
|
19
|
+
);
|
|
20
|
+
expect(result.getSwitch()?.getAttribute("aria-checked")).toBe("true");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("emits a boolean through canonical onChange", async () => {
|
|
24
|
+
const onChange = vi.fn();
|
|
25
|
+
const result = renderWithProviders(
|
|
26
|
+
<SwitchField label="Enabled" value={false} onChange={onChange} />,
|
|
27
|
+
);
|
|
28
|
+
await act(async () => {
|
|
29
|
+
fireEvent.click(result.getSwitch() as HTMLElement);
|
|
30
|
+
});
|
|
31
|
+
expect(onChange).toHaveBeenCalledWith(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("forwards disabled onto the switch", () => {
|
|
35
|
+
const result = renderWithProviders(
|
|
36
|
+
<SwitchField label="Enabled" value={false} disabled onChange={() => {}} />,
|
|
37
|
+
);
|
|
38
|
+
const el = result.getSwitch();
|
|
39
|
+
expect(el?.hasAttribute("disabled") || el?.getAttribute("aria-disabled") === "true").toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("shows the label and error", () => {
|
|
43
|
+
const result = renderWithProviders(
|
|
44
|
+
<SwitchField label="Enabled" value={false} error="cannot enable" onChange={() => {}} />,
|
|
45
|
+
);
|
|
46
|
+
expect(result.container.textContent).toContain("Enabled");
|
|
47
|
+
expect(result.container.textContent).toContain("cannot enable");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("registry resolution (Switch fieldtype)", () => {
|
|
52
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
53
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
it("resolves 'Switch' to SwitchField and maps a truthy doc value to true", () => {
|
|
57
|
+
const Component = getFieldComponent("Switch")!;
|
|
58
|
+
const element = (Component as Function)(
|
|
59
|
+
propsFor({ value: 1, label: "Enabled" }),
|
|
60
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
61
|
+
expect(element.type).toBe(SwitchField);
|
|
62
|
+
expect(element.props.value).toBe(true);
|
|
63
|
+
expect(element.props.label).toBe("Enabled");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -51,11 +51,10 @@ describe("TextEditor initialization emissions", () => {
|
|
|
51
51
|
await waitFor(() => {
|
|
52
52
|
expect(utils.container.querySelector(".ProseMirror")).toBeTruthy();
|
|
53
53
|
});
|
|
54
|
-
//
|
|
55
|
-
// sync is the house editor's contract, not a forked TipTap in this wrapper.
|
|
54
|
+
// An external update changes the actual document without echoing an edit.
|
|
56
55
|
utils.rerender(<TextEditor label="Description" value="<p>second</p>" onChange={onChange} />);
|
|
57
56
|
await waitFor(() => {
|
|
58
|
-
expect(utils.container.querySelector(".ProseMirror")).
|
|
57
|
+
expect(utils.container.querySelector(".ProseMirror")?.textContent).toBe("second");
|
|
59
58
|
});
|
|
60
59
|
expect(onChange).not.toHaveBeenCalled();
|
|
61
60
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { action } from "@multiplatform.one/storybook";
|
|
2
|
+
import { Button } from "@multiplatform.one/forms";
|
|
2
3
|
import { DataTable, type DataTableColumn } from "@multiplatform.one/table";
|
|
3
4
|
import { useState } from "react";
|
|
4
|
-
import { YStack } from "tamagui";
|
|
5
|
+
import { Text, YStack } from "tamagui";
|
|
5
6
|
import { fieldtypeToTableField } from "../../fieldRegistry";
|
|
6
7
|
import { FrappeStoryProvider } from "../../frappeStoryTarget";
|
|
7
8
|
import { TextEditor, type TextEditorProps } from ".";
|
|
@@ -51,6 +52,35 @@ Main.args = {
|
|
|
51
52
|
} as Partial<StoryProps>;
|
|
52
53
|
Main.storyName = "Main";
|
|
53
54
|
|
|
55
|
+
export const ExternalValueUpdates = {
|
|
56
|
+
name: "External value updates",
|
|
57
|
+
render: function ExternalValueUpdatesStory() {
|
|
58
|
+
const [value, setValue] = useState("<p>Original note</p>");
|
|
59
|
+
const [edits, setEdits] = useState(0);
|
|
60
|
+
return (
|
|
61
|
+
<YStack gap="$3" maxWidth={640}>
|
|
62
|
+
<TextEditor
|
|
63
|
+
label="Note"
|
|
64
|
+
value={value}
|
|
65
|
+
onChange={(next) => {
|
|
66
|
+
setValue(next);
|
|
67
|
+
setEdits((count) => count + 1);
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
<Button
|
|
71
|
+
onPress={() => {
|
|
72
|
+
setEdits(0);
|
|
73
|
+
setValue("<p>Saved note</p>");
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
Load saved note
|
|
77
|
+
</Button>
|
|
78
|
+
<Text testID="editor-user-edits">User edits: {edits}</Text>
|
|
79
|
+
</YStack>
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
54
84
|
export const Empty = (args: StoryProps) => <Controlled {...args} />;
|
|
55
85
|
Empty.args = {
|
|
56
86
|
label: "Empty editor",
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToggleGroupField contract specs. The adapter maps `onChange` onto the forms
|
|
3
|
+
* ToggleGroup's `onValueChange`. Pin that value, onChange, disabled, label
|
|
4
|
+
* and error survive the hop.
|
|
5
|
+
*/
|
|
6
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
7
|
+
import { cleanup, fireEvent } from "@testing-library/react";
|
|
8
|
+
import type React from "react";
|
|
9
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
11
|
+
import { ToggleGroupField } from ".";
|
|
12
|
+
|
|
13
|
+
afterEach(cleanup);
|
|
14
|
+
|
|
15
|
+
const options = [
|
|
16
|
+
{ label: "Left", value: "left" },
|
|
17
|
+
{ label: "Center", value: "center" },
|
|
18
|
+
{ label: "Right", value: "right" },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
describe("ToggleGroupField composes the forms ToggleGroup", () => {
|
|
22
|
+
it("paints a controlled value onto the matching item", () => {
|
|
23
|
+
const result = renderWithProviders(
|
|
24
|
+
<ToggleGroupField
|
|
25
|
+
label="Align"
|
|
26
|
+
type="single"
|
|
27
|
+
value="center"
|
|
28
|
+
options={options}
|
|
29
|
+
onChange={() => {}}
|
|
30
|
+
/>,
|
|
31
|
+
);
|
|
32
|
+
expect(result.container.textContent).toContain("Center");
|
|
33
|
+
const pressed = result.container.querySelector('[aria-pressed="true"], [data-state="on"]');
|
|
34
|
+
expect(pressed).toBeTruthy();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("emits the item value through canonical onChange", () => {
|
|
38
|
+
const onChange = vi.fn();
|
|
39
|
+
const result = renderWithProviders(
|
|
40
|
+
<ToggleGroupField
|
|
41
|
+
label="Align"
|
|
42
|
+
type="single"
|
|
43
|
+
value="left"
|
|
44
|
+
options={options}
|
|
45
|
+
onChange={onChange}
|
|
46
|
+
/>,
|
|
47
|
+
);
|
|
48
|
+
const center = result.findTextElement("Center");
|
|
49
|
+
expect(center).toBeTruthy();
|
|
50
|
+
fireEvent.click(center as HTMLElement);
|
|
51
|
+
expect(onChange).toHaveBeenCalledWith("center");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("forwards disabled onto the group", () => {
|
|
55
|
+
const result = renderWithProviders(
|
|
56
|
+
<ToggleGroupField
|
|
57
|
+
label="Align"
|
|
58
|
+
type="single"
|
|
59
|
+
value="left"
|
|
60
|
+
options={options}
|
|
61
|
+
disabled
|
|
62
|
+
onChange={() => {}}
|
|
63
|
+
/>,
|
|
64
|
+
);
|
|
65
|
+
const el =
|
|
66
|
+
result.container.querySelector('[role="group"]') ||
|
|
67
|
+
result.container.querySelector('[data-disabled="true"]') ||
|
|
68
|
+
result.container.querySelector("[disabled]");
|
|
69
|
+
expect(el).toBeTruthy();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("shows the label and error", () => {
|
|
73
|
+
const result = renderWithProviders(
|
|
74
|
+
<ToggleGroupField
|
|
75
|
+
label="Align"
|
|
76
|
+
type="single"
|
|
77
|
+
value="left"
|
|
78
|
+
options={options}
|
|
79
|
+
error="pick a side"
|
|
80
|
+
onChange={() => {}}
|
|
81
|
+
/>,
|
|
82
|
+
);
|
|
83
|
+
expect(result.container.textContent).toContain("Align");
|
|
84
|
+
expect(result.container.textContent).toContain("pick a side");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("registry resolution (Toggle Group fieldtype)", () => {
|
|
89
|
+
function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
|
|
90
|
+
return { value: "", onChange: () => {}, ...overrides };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
it("resolves 'Toggle Group' to ToggleGroupField and splits df.options on newlines", () => {
|
|
94
|
+
const Component = getFieldComponent("Toggle Group")!;
|
|
95
|
+
const element = (Component as Function)(
|
|
96
|
+
propsFor({
|
|
97
|
+
value: "Left",
|
|
98
|
+
label: "Align",
|
|
99
|
+
fieldMeta: { options: "Left\nCenter" },
|
|
100
|
+
} as Partial<FieldRenderProps>),
|
|
101
|
+
) as React.ReactElement<Record<string, unknown>>;
|
|
102
|
+
expect(element.type).toBe(ToggleGroupField);
|
|
103
|
+
expect(element.props.value).toBe("Left");
|
|
104
|
+
expect(element.props.label).toBe("Align");
|
|
105
|
+
expect(element.props.options).toEqual([
|
|
106
|
+
{ label: "Left", value: "Left" },
|
|
107
|
+
{ label: "Center", value: "Center" },
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
});
|