@multiplatform.one/frappe-ui 7.7.6 → 7.10.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.cjs +7 -7
- package/dist/cjs/FormSidebar.native.js +7 -7
- 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.cjs +29 -3
- package/dist/cjs/FrappeChartCard.native.js +29 -3
- 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 +29 -3
- package/dist/cjs/FrappeKPICard.native.js +29 -3
- 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.cjs +6 -6
- package/dist/cjs/FrappeListView.native.js +6 -6
- 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.cjs +30 -2
- package/dist/cjs/fields/DateRange/index.native.js +34 -2
- 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.mjs +7 -7
- package/dist/esm/FormSidebar.mjs.map +1 -1
- package/dist/esm/FormSidebar.native.js +7 -7
- 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.mjs +30 -4
- package/dist/esm/FrappeChartCard.mjs.map +1 -1
- package/dist/esm/FrappeChartCard.native.js +30 -4
- 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 +30 -4
- package/dist/esm/FrappeKPICard.mjs.map +1 -1
- package/dist/esm/FrappeKPICard.native.js +30 -4
- 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.mjs +6 -6
- package/dist/esm/FrappeListView.mjs.map +1 -1
- package/dist/esm/FrappeListView.native.js +6 -6
- 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.mjs +30 -2
- package/dist/esm/fields/DateRange/index.mjs.map +1 -1
- package/dist/esm/fields/DateRange/index.native.js +34 -2
- 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/FormSidebar.mjs +7 -7
- package/dist/jsx/FormSidebar.mjs.map +1 -1
- package/dist/jsx/FormSidebar.native.js +7 -7
- package/dist/jsx/FormSidebar.native.js.map +1 -1
- 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/FrappeChartCard.mjs +30 -4
- package/dist/jsx/FrappeChartCard.mjs.map +1 -1
- package/dist/jsx/FrappeChartCard.native.js +29 -3
- package/dist/jsx/FrappeChartCard.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 +30 -4
- package/dist/jsx/FrappeKPICard.mjs.map +1 -1
- package/dist/jsx/FrappeKPICard.native.js +29 -3
- 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/FrappeListView.mjs +6 -6
- package/dist/jsx/FrappeListView.mjs.map +1 -1
- package/dist/jsx/FrappeListView.native.js +6 -6
- package/dist/jsx/FrappeListView.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/DateRange/index.mjs +30 -2
- package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
- package/dist/jsx/fields/DateRange/index.native.js +34 -2
- package/dist/jsx/fields/DateRange/index.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/FormSidebar.tsx +7 -7
- package/src/FrappeCalendar.tsx +25 -22
- package/src/FrappeChartCard.spec.tsx +179 -0
- package/src/FrappeChartCard.tsx +55 -6
- package/src/FrappeForm.tsx +7 -3
- package/src/FrappeGantt.tsx +29 -39
- package/src/FrappeImageView.tsx +5 -3
- package/src/FrappeKPICard.spec.tsx +153 -0
- package/src/FrappeKPICard.tsx +52 -6
- package/src/FrappeKanban.tsx +24 -17
- package/src/FrappeLikedBy.tsx +1 -1
- package/src/FrappeList.tsx +3 -2
- package/src/FrappeListView.tsx +6 -6
- 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/Date.spec.tsx +8 -1
- package/src/fields/Date/nativePresentation.spec.tsx +8 -1
- package/src/fields/Date/typeParity.spec.tsx +27 -10
- package/src/fields/DateRange/DateRange.spec.tsx +87 -15
- package/src/fields/DateRange/index.tsx +47 -3
- 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 +44 -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/FrappeChartCard.d.ts +17 -1
- package/types/FrappeChartCard.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 +14 -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/DateRange/index.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
package/src/FrappeTreeView.tsx
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { useDocTypeMeta
|
|
2
|
-
import { AsyncBoundary, TreeView, type TreeNode } from "@multiplatform.one/components";
|
|
1
|
+
import { useDocTypeMeta } from "@multiplatform.one/frappe";
|
|
2
|
+
import { AsyncBoundary, EmptyState, TreeView, type TreeNode } from "@multiplatform.one/components";
|
|
3
3
|
import { TreeStructureIcon } from "@phosphor-icons/react";
|
|
4
|
-
import React, { useCallback,
|
|
4
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
import { Text, YStack, type YStackProps } from "tamagui";
|
|
7
|
-
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
7
|
+
import { useGlyphColor, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
8
8
|
import { formCommonColors } from "@multiplatform.one/forms";
|
|
9
9
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
10
10
|
import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
|
|
11
|
-
import {
|
|
11
|
+
import { useFrappeRows } from "./useFrappeRows";
|
|
12
12
|
|
|
13
13
|
export interface FrappeTreeViewProps<TDoc extends { name: string; doctype: string }> extends Omit<
|
|
14
14
|
YStackProps,
|
|
@@ -16,11 +16,32 @@ export interface FrappeTreeViewProps<TDoc extends { name: string; doctype: strin
|
|
|
16
16
|
> {
|
|
17
17
|
doctype: string;
|
|
18
18
|
parentField?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Separator that splits {@link FrappeTreeViewProps.pathField} into levels,
|
|
21
|
+
* e.g. ":" for an account named `Assets:Personal:Bank:Checking`. Setting it
|
|
22
|
+
* switches the tree to path mode: the branches between root and leaf are
|
|
23
|
+
* synthesised from the segments, `parentField` is neither read nor fetched,
|
|
24
|
+
* and the `is_tree` gate is skipped. A doctype whose hierarchy lives in the
|
|
25
|
+
* row's own key has no parent field and the server will never report
|
|
26
|
+
* `is_tree`.
|
|
27
|
+
*/
|
|
28
|
+
pathSeparator?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Row field holding the path. Path mode only; defaults to `name`. Path mode
|
|
31
|
+
* fetches `name`, this field, `valueField` and whatever `fields` adds, so a
|
|
32
|
+
* caller who needs more on the `onNodeClick` document asks for it there.
|
|
33
|
+
*/
|
|
34
|
+
pathField?: string;
|
|
19
35
|
titleField?: string;
|
|
20
36
|
valueField?: string;
|
|
21
37
|
fields?: readonly (keyof TDoc & string)[];
|
|
22
38
|
filters?: Partial<TDoc> | Array<[keyof TDoc & string, string, any]>;
|
|
23
39
|
onNodeClick?: (doc: Partial<TDoc>) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Path-mode selection, fired for synthesised branches as well as documents.
|
|
42
|
+
* `doc` is present only when a document actually sits at that path.
|
|
43
|
+
*/
|
|
44
|
+
onPathSelect?: (path: string, doc?: Partial<TDoc>) => void;
|
|
24
45
|
/** Reserved for future DnD reparenting; not wired yet. */
|
|
25
46
|
enableDragDrop?: boolean;
|
|
26
47
|
/** Expand every branch on first paint (passed through to TreeView). */
|
|
@@ -88,20 +109,94 @@ export function buildTreeNodes<TDoc extends { name: string }>(
|
|
|
88
109
|
return sortDocs(roots).map(buildNode);
|
|
89
110
|
}
|
|
90
111
|
|
|
112
|
+
/** One level of the path forest, before it becomes TreeNodes. */
|
|
113
|
+
interface PathBucket<TDoc> {
|
|
114
|
+
path: string;
|
|
115
|
+
segment: string;
|
|
116
|
+
doc?: TDoc;
|
|
117
|
+
children: Map<string, PathBucket<TDoc>>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Build a TreeNode forest from paths held on the rows themselves, e.g.
|
|
122
|
+
* `Assets:Personal:Bank:Checking` split on ":".
|
|
123
|
+
*
|
|
124
|
+
* The branches between root and leaf are not rows, so they are synthesised:
|
|
125
|
+
* a synthesised node carries no `data` and its `id` is the path prefix it
|
|
126
|
+
* stands for. A row whose path value is empty falls back to a single segment
|
|
127
|
+
* of its own name, so nothing is silently dropped.
|
|
128
|
+
*/
|
|
129
|
+
export function buildPathTreeNodes<TDoc extends { name: string }>(
|
|
130
|
+
docs: TDoc[],
|
|
131
|
+
pathField: string,
|
|
132
|
+
separator: string,
|
|
133
|
+
): TreeNode<Record<string, unknown>>[] {
|
|
134
|
+
const roots = new Map<string, PathBucket<TDoc>>();
|
|
135
|
+
|
|
136
|
+
const splitPath = (doc: TDoc): string[] => {
|
|
137
|
+
const raw = (doc as Record<string, unknown>)[pathField];
|
|
138
|
+
const value = raw == null ? "" : String(raw);
|
|
139
|
+
// An empty separator would split the value into single characters.
|
|
140
|
+
const segments = separator ? value.split(separator) : [value];
|
|
141
|
+
const cleaned = segments.map((segment) => segment.trim()).filter((segment) => segment !== "");
|
|
142
|
+
return cleaned.length > 0 ? cleaned : [doc.name];
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
for (const doc of docs) {
|
|
146
|
+
let level = roots;
|
|
147
|
+
let prefix = "";
|
|
148
|
+
let bucket: PathBucket<TDoc> | undefined;
|
|
149
|
+
for (const segment of splitPath(doc)) {
|
|
150
|
+
prefix = prefix ? `${prefix}${separator}${segment}` : segment;
|
|
151
|
+
bucket = level.get(segment);
|
|
152
|
+
if (!bucket) {
|
|
153
|
+
bucket = { path: prefix, segment, children: new Map() };
|
|
154
|
+
level.set(segment, bucket);
|
|
155
|
+
}
|
|
156
|
+
level = bucket.children;
|
|
157
|
+
}
|
|
158
|
+
// Two rows on one path: the first keeps the node rather than the last
|
|
159
|
+
// row the live query happened to deliver.
|
|
160
|
+
if (bucket && !bucket.doc) bucket.doc = doc;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const toNodes = (level: Map<string, PathBucket<TDoc>>): TreeNode<Record<string, unknown>>[] =>
|
|
164
|
+
Array.from(level.values())
|
|
165
|
+
.sort((a, b) => a.segment.localeCompare(b.segment))
|
|
166
|
+
.map((bucket) => {
|
|
167
|
+
const children = toNodes(bucket.children);
|
|
168
|
+
return {
|
|
169
|
+
id: bucket.path,
|
|
170
|
+
label: bucket.segment,
|
|
171
|
+
data: bucket.doc as unknown as Record<string, unknown> | undefined,
|
|
172
|
+
children: children.length > 0 ? children : undefined,
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return toNodes(roots);
|
|
177
|
+
}
|
|
178
|
+
|
|
91
179
|
/**
|
|
92
180
|
* Thin Frappe wrapper around the generic TreeView component.
|
|
93
181
|
*
|
|
94
182
|
* Fetches the full DocType list via `useFrappeCollection` / `useLiveQuery`
|
|
95
183
|
* (realtime-backed), then builds a `TreeNode` forest from the parent field.
|
|
184
|
+
*
|
|
185
|
+
* Pass `pathSeparator` instead when the hierarchy lives in the row's own key
|
|
186
|
+
* (`Assets:Personal:Bank:Checking`). The branches are synthesised client-side,
|
|
187
|
+
* so no parent field and no `is_tree` are needed.
|
|
96
188
|
*/
|
|
97
189
|
export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
98
190
|
doctype,
|
|
99
191
|
parentField: parentFieldProp,
|
|
192
|
+
pathSeparator,
|
|
193
|
+
pathField,
|
|
100
194
|
titleField: titleFieldProp,
|
|
101
195
|
valueField,
|
|
102
196
|
fields,
|
|
103
197
|
filters,
|
|
104
198
|
onNodeClick,
|
|
199
|
+
onPathSelect,
|
|
105
200
|
enableDragDrop: _enableDragDrop = false,
|
|
106
201
|
expandByDefault = false,
|
|
107
202
|
display = "default",
|
|
@@ -116,6 +211,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
116
211
|
|
|
117
212
|
const config = useFrappeConfig();
|
|
118
213
|
const { knobProps } = useResolvedKnobs();
|
|
214
|
+
const emptyIconColor = useGlyphColor(formCommonColors.muted);
|
|
119
215
|
const { t } = useTranslation();
|
|
120
216
|
const [selectedId, setSelectedId] = useState<string | undefined>();
|
|
121
217
|
|
|
@@ -123,8 +219,10 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
123
219
|
const finalAuth = auth ?? config?.auth;
|
|
124
220
|
const finalSyncOptions = syncOptions ?? config?.syncOptions;
|
|
125
221
|
|
|
126
|
-
if (!finalBaseURL) {
|
|
127
|
-
throw new Error(
|
|
222
|
+
if (!finalBaseURL && !config?.fixtures) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
"FrappeTreeView requires baseURL prop or FrappeProvider with baseURL or fixtures",
|
|
225
|
+
);
|
|
128
226
|
}
|
|
129
227
|
|
|
130
228
|
const appConfig = useMemo(
|
|
@@ -152,6 +250,8 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
152
250
|
|
|
153
251
|
const { meta, isLoading: isMetaLoading, error: metaError } = useDocTypeMeta(appConfig, doctype);
|
|
154
252
|
|
|
253
|
+
const isPathMode = !!pathSeparator;
|
|
254
|
+
const effectivePathField = pathField ?? "name";
|
|
155
255
|
const effectiveTitleField = titleFieldProp ?? meta?.title_field ?? "name";
|
|
156
256
|
const effectiveParentField =
|
|
157
257
|
parentFieldProp ?? `parent_${doctype.toLowerCase().replace(/ /g, "_")}`;
|
|
@@ -160,67 +260,75 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
160
260
|
// lets callers continue (Guest peek / offline). Successful meta always
|
|
161
261
|
// wins for the is_tree gate — including rejecting flat DocTypes that
|
|
162
262
|
// happened to pass parentField.
|
|
163
|
-
|
|
164
|
-
|
|
263
|
+
//
|
|
264
|
+
// Path mode is the exception: the hierarchy comes from the row's own key,
|
|
265
|
+
// so there is nothing for is_tree to be right about.
|
|
266
|
+
const isKnownNotTree = !isPathMode && !!meta && !meta.is_tree;
|
|
267
|
+
const canProceed = isPathMode || !!meta?.is_tree || (!!metaError && !meta && !!parentFieldProp);
|
|
165
268
|
|
|
166
269
|
const effectiveFields = useMemo(() => {
|
|
167
270
|
const fieldSet = new Set<string>(fields as string[] | undefined);
|
|
168
271
|
fieldSet.add("name");
|
|
169
|
-
|
|
170
|
-
|
|
272
|
+
if (isPathMode) {
|
|
273
|
+
// The parent field does not exist on a path-shaped doctype; asking for
|
|
274
|
+
// it would fail the read on a live bench.
|
|
275
|
+
fieldSet.add(effectivePathField);
|
|
276
|
+
} else {
|
|
277
|
+
fieldSet.add(effectiveTitleField);
|
|
278
|
+
fieldSet.add(effectiveParentField);
|
|
279
|
+
}
|
|
171
280
|
if (valueField) fieldSet.add(valueField);
|
|
172
281
|
return Array.from(fieldSet) as (keyof TDoc & string)[];
|
|
173
|
-
}, [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
toLiveLoadError(err, {
|
|
182
|
-
permissionMessage: t("You do not have permission to view {{doctype}}", { doctype }),
|
|
183
|
-
genericMessage: t("Failed to load {{doctype}} tree", { doctype }),
|
|
184
|
-
}),
|
|
185
|
-
);
|
|
186
|
-
},
|
|
187
|
-
[doctype, t],
|
|
188
|
-
);
|
|
282
|
+
}, [
|
|
283
|
+
fields,
|
|
284
|
+
isPathMode,
|
|
285
|
+
effectivePathField,
|
|
286
|
+
effectiveTitleField,
|
|
287
|
+
effectiveParentField,
|
|
288
|
+
valueField,
|
|
289
|
+
]);
|
|
189
290
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
291
|
+
// The shared doctype read (MPO-251): collection + live query + the honest
|
|
292
|
+
// error surface a bare collection swallows — without it a 403 or a network
|
|
293
|
+
// failure renders as an empty tree. `limit: null` keeps the tree on the
|
|
294
|
+
// bench's own page length, as it was before the hook existed.
|
|
295
|
+
const rowsMessages = useMemo(
|
|
296
|
+
() => ({
|
|
297
|
+
permission: t("You do not have permission to view {{doctype}}", { doctype }),
|
|
298
|
+
generic: t("Failed to load {{doctype}} tree", { doctype }),
|
|
299
|
+
}),
|
|
300
|
+
[doctype, t],
|
|
194
301
|
);
|
|
195
|
-
|
|
196
|
-
// A new collection (doctype/filter change) starts with a clean slate.
|
|
197
|
-
useEffect(() => {
|
|
198
|
-
setSyncError(null);
|
|
199
|
-
}, [collection]);
|
|
200
|
-
|
|
201
302
|
const {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
} =
|
|
206
|
-
|
|
207
|
-
|
|
303
|
+
rows: docs,
|
|
304
|
+
isQueryLoading: isDataLoading,
|
|
305
|
+
error: queryError,
|
|
306
|
+
} = useFrappeRows<TDoc>(appConfig, doctype, {
|
|
307
|
+
fields: effectiveFields,
|
|
308
|
+
filters,
|
|
309
|
+
limit: null,
|
|
310
|
+
enabled: canProceed && !isKnownNotTree,
|
|
311
|
+
messages: rowsMessages,
|
|
312
|
+
});
|
|
208
313
|
|
|
209
314
|
const treeNodes = useMemo(
|
|
210
|
-
() =>
|
|
211
|
-
|
|
315
|
+
() =>
|
|
316
|
+
pathSeparator
|
|
317
|
+
? buildPathTreeNodes(docs, effectivePathField, pathSeparator)
|
|
318
|
+
: buildTreeNodes(docs, effectiveParentField, effectiveTitleField),
|
|
319
|
+
[docs, pathSeparator, effectivePathField, effectiveParentField, effectiveTitleField],
|
|
212
320
|
);
|
|
213
321
|
|
|
214
|
-
const queryError =
|
|
215
|
-
syncError ?? (isError ? new Error(t("Failed to load {{doctype}} tree", { doctype })) : null);
|
|
216
|
-
|
|
217
322
|
const handleNodeSelect = useCallback(
|
|
218
323
|
(node: TreeNode<Record<string, unknown>>) => {
|
|
219
324
|
setSelectedId(node.id);
|
|
325
|
+
if (isPathMode) onPathSelect?.(node.id, node.data as Partial<TDoc> | undefined);
|
|
326
|
+
// A synthesised branch is not a document, so onNodeClick stays silent
|
|
327
|
+
// rather than handing a caller a name that would 404 on open.
|
|
220
328
|
if (!node.data) return;
|
|
221
329
|
onNodeClick?.(node.data as Partial<TDoc>);
|
|
222
330
|
},
|
|
223
|
-
[onNodeClick],
|
|
331
|
+
[isPathMode, onNodeClick, onPathSelect],
|
|
224
332
|
);
|
|
225
333
|
|
|
226
334
|
if (isMetaLoading) {
|
|
@@ -228,7 +336,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
228
336
|
return <AsyncBoundary layout="list" loading {...stackProps} />;
|
|
229
337
|
}
|
|
230
338
|
|
|
231
|
-
if (metaError && !meta && !parentFieldProp) {
|
|
339
|
+
if (metaError && !meta && !parentFieldProp && !isPathMode) {
|
|
232
340
|
if (error) return <>{error(metaError)}</>;
|
|
233
341
|
return (
|
|
234
342
|
<AsyncBoundary
|
|
@@ -243,12 +351,14 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
243
351
|
if (isKnownNotTree) {
|
|
244
352
|
const iconSize = Number(knobProps.controlIcon?.width) || 16;
|
|
245
353
|
return (
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
354
|
+
<EmptyState
|
|
355
|
+
title={t("This DocType does not support tree view")}
|
|
356
|
+
description={t(
|
|
357
|
+
"Pass pathSeparator and pathField to build the hierarchy from a path-shaped value on each row. parentField alone does not, because a flat DocType has no parent field.",
|
|
358
|
+
)}
|
|
359
|
+
icon={<TreeStructureIcon size={iconSize * 2} color={emptyIconColor} />}
|
|
360
|
+
{...stackProps}
|
|
361
|
+
/>
|
|
252
362
|
);
|
|
253
363
|
}
|
|
254
364
|
|
package/src/commentActions.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function useFrappeCommentActions(
|
|
|
67
67
|
): FrappeCommentActions {
|
|
68
68
|
return useMemo(() => {
|
|
69
69
|
const app =
|
|
70
|
-
config && !config.fixtures
|
|
70
|
+
config?.baseURL && !config.fixtures
|
|
71
71
|
? new FrappeApp(config.baseURL, (config.auth ?? {}) as Record<string, unknown>)
|
|
72
72
|
: undefined;
|
|
73
73
|
|
|
@@ -208,7 +208,7 @@ export function Timeline({
|
|
|
208
208
|
|
|
209
209
|
const resolveSessionUser = useCallback(async (): Promise<string> => {
|
|
210
210
|
if (sessionUserRef.current) return sessionUserRef.current;
|
|
211
|
-
if (config && !config.fixtures) {
|
|
211
|
+
if (config?.baseURL && !config.fixtures) {
|
|
212
212
|
const app = new FrappeApp(config.baseURL, (config.auth ?? {}) as Record<string, unknown>);
|
|
213
213
|
sessionUserRef.current = await app.auth().getLoggedInUser();
|
|
214
214
|
} else {
|
package/src/desk/DeskShell.tsx
CHANGED
|
@@ -209,6 +209,7 @@ export function DeskShell({
|
|
|
209
209
|
{showSidebar && !isNarrow && (
|
|
210
210
|
<YStack
|
|
211
211
|
role="navigation"
|
|
212
|
+
aria-label={t("Desk navigation")}
|
|
212
213
|
id="desk-sidebar"
|
|
213
214
|
flexShrink={0}
|
|
214
215
|
data-testid="desk-sidebar-rail"
|
|
@@ -234,6 +235,7 @@ export function DeskShell({
|
|
|
234
235
|
/>
|
|
235
236
|
<YStack
|
|
236
237
|
role="navigation"
|
|
238
|
+
aria-label={t("Desk navigation")}
|
|
237
239
|
id="desk-sidebar"
|
|
238
240
|
position="absolute"
|
|
239
241
|
top={0}
|
package/src/desk/awesomebar.tsx
CHANGED
|
@@ -101,7 +101,10 @@ async function addRecentSearch(query: string): Promise<void> {
|
|
|
101
101
|
// Helpers
|
|
102
102
|
// ---------------------------------------------------------------------------
|
|
103
103
|
|
|
104
|
-
function createHttpClientFromConfig(config:
|
|
104
|
+
function createHttpClientFromConfig(config: {
|
|
105
|
+
baseURL: string;
|
|
106
|
+
auth?: FrappeConnectionConfig["auth"];
|
|
107
|
+
}): HttpClient {
|
|
105
108
|
return new HttpClient(
|
|
106
109
|
config.baseURL,
|
|
107
110
|
config.auth as Parameters<typeof HttpClient.prototype.updateAuth>[0],
|
|
@@ -168,7 +171,7 @@ export function Awesomebar({ onNavigate, basePath = "/desk", ...stackProps }: Aw
|
|
|
168
171
|
// HttpClient ref for document search
|
|
169
172
|
const httpRef = useRef<HttpClient | undefined>(undefined);
|
|
170
173
|
const configKeyRef = useRef("");
|
|
171
|
-
if (config) {
|
|
174
|
+
if (config?.baseURL) {
|
|
172
175
|
const key = `${config.baseURL}:${config.auth?.token ?? ""}`;
|
|
173
176
|
if (key !== configKeyRef.current) {
|
|
174
177
|
httpRef.current = createHttpClientFromConfig({
|
|
@@ -29,12 +29,10 @@ function readCodeEditorSource() {
|
|
|
29
29
|
return readFileSync(join(codeEditorDir(), "index.tsx"), "utf8");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function readCodeEditorStories() {
|
|
33
|
-
return readFileSync(join(codeEditorDir(), "CodeEditor.stories.tsx"), "utf8");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
32
|
afterEach(cleanup);
|
|
37
33
|
|
|
34
|
+
vi.mock("@multiplatform.one/storybook", () => ({ action: () => vi.fn() }));
|
|
35
|
+
|
|
38
36
|
describe("frappeCodeLanguage (stock ControlCode language_map)", () => {
|
|
39
37
|
it("maps stock Frappe options case-insensitively", () => {
|
|
40
38
|
expect(frappeCodeLanguage("Python")).toBe("python");
|
|
@@ -102,11 +100,14 @@ describe("CodeEditorField (standalone)", () => {
|
|
|
102
100
|
expect(result.getTextArea()).toBeNull();
|
|
103
101
|
});
|
|
104
102
|
|
|
105
|
-
it("ships CSF3 story objects so native gallery keeps args (KS blank-pane)", () => {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
it("ships CSF3 story objects so native gallery keeps args (KS blank-pane)", async () => {
|
|
104
|
+
const { Main, Json, ReadOnly } = await import("./CodeEditor.stories");
|
|
105
|
+
for (const story of [Main, Json, ReadOnly]) {
|
|
106
|
+
expect(typeof story).toBe("object");
|
|
107
|
+
expect(story.render).toBeTypeOf("function");
|
|
108
|
+
expect(story.args.value?.trim().length).toBeGreaterThan(0);
|
|
109
|
+
}
|
|
110
|
+
expect(ReadOnly.args.readOnly).toBe(true);
|
|
110
111
|
});
|
|
111
112
|
|
|
112
113
|
it("forwards knob containerRadius onto the source textarea (F14)", () => {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* a seeded value is not a user edit).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { describe, it, expect, vi } from "vitest";
|
|
13
|
+
import { describe, it, expect, vi, beforeAll } from "vitest";
|
|
14
14
|
|
|
15
15
|
// The first field-module import in a cold fork transforms the whole fields
|
|
16
16
|
// graph (same budget as tests/fieldRenderers.spec.tsx).
|
|
@@ -79,6 +79,13 @@ function getDayButton(root: ParentNode, day: number): HTMLButtonElement | undefi
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// Warm the graph here, not inside the first `it`: the transform is setup cost
|
|
83
|
+
// (110-155s quiet, past 240s under load), and charging it to an assertion made
|
|
84
|
+
// whichever case ran first time out.
|
|
85
|
+
beforeAll(async () => {
|
|
86
|
+
await loadDateField();
|
|
87
|
+
}, 900_000);
|
|
88
|
+
|
|
82
89
|
describe("Date wrapper — late-arriving value display", () => {
|
|
83
90
|
it("a value arriving after mount displays, without onChange", async () => {
|
|
84
91
|
const DateField = await loadDateField();
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* than rendered) and the platform flags.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
21
|
+
import { describe, it, expect, vi, beforeAll, beforeEach } from "vitest";
|
|
22
22
|
|
|
23
23
|
// Same cold-fork budget as the sibling Date.spec.tsx: the first field-module
|
|
24
24
|
// import transforms the whole fields graph.
|
|
@@ -132,6 +132,13 @@ async function press(root: ParentNode, text: string) {
|
|
|
132
132
|
const lastPick = () => mockState.picks[mockState.picks.length - 1];
|
|
133
133
|
const waitForPick = (predicate: () => void) => waitFor(predicate, { timeout: 30_000 });
|
|
134
134
|
|
|
135
|
+
// Warm the graph here, not inside the first `it`: the transform is setup cost
|
|
136
|
+
// (110-155s quiet, past 240s under load), and charging it to an assertion made
|
|
137
|
+
// whichever case ran first time out.
|
|
138
|
+
beforeAll(async () => {
|
|
139
|
+
await loadNativeDateField();
|
|
140
|
+
}, 900_000);
|
|
141
|
+
|
|
135
142
|
beforeEach(() => {
|
|
136
143
|
// The iOS sheet is a portal, so a previous case's chrome would otherwise
|
|
137
144
|
// still be in the document when the next one asserts on it.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* rather than rendered) and the platform flags. The web half imports neither.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
20
|
+
import { describe, it, expect, vi, beforeAll, beforeEach } from "vitest";
|
|
21
21
|
|
|
22
22
|
// Same cold-fork budget as the sibling Date specs: the first field-module
|
|
23
23
|
// import transforms the whole fields graph.
|
|
@@ -168,6 +168,21 @@ async function pressText(root: ParentNode, text: string) {
|
|
|
168
168
|
});
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
async function selectPeriod(period: "AM" | "PM") {
|
|
172
|
+
const wheel = document.querySelector('[role="slider"][aria-label="AM/PM"]');
|
|
173
|
+
expect(wheel).toBeTruthy();
|
|
174
|
+
await act(async () => {
|
|
175
|
+
fireEvent.keyDown(wheel!, { key: period === "AM" ? "Home" : "End" });
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Warm the graph here, not inside the first `it`: the transform is setup cost
|
|
180
|
+
// (110-155s quiet, past 240s under load), and charging it to an assertion made
|
|
181
|
+
// whichever case ran first time out.
|
|
182
|
+
beforeAll(async () => {
|
|
183
|
+
await Promise.all([loadWebDateField(), loadNativeDateField()]);
|
|
184
|
+
}, 900_000);
|
|
185
|
+
|
|
171
186
|
beforeEach(() => {
|
|
172
187
|
// Both halves portal their surfaces, so a previous case's chrome would
|
|
173
188
|
// otherwise still be in the document when the next one queries it.
|
|
@@ -194,7 +209,7 @@ describe("web Date field — type=date keeps the calendar", () => {
|
|
|
194
209
|
await openPanel(triggerInput(result.container)!);
|
|
195
210
|
expect(panelText()).toContain("Su");
|
|
196
211
|
// A date-only control offers no clock.
|
|
197
|
-
expect(
|
|
212
|
+
expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeNull();
|
|
198
213
|
|
|
199
214
|
await waitFor(() => expect(dayCell(15)).toBeTruthy(), { timeout: 30_000 });
|
|
200
215
|
await act(async () => {
|
|
@@ -226,8 +241,8 @@ describe("web Date field — type=time renders a time control", () => {
|
|
|
226
241
|
);
|
|
227
242
|
await openPanel(triggerInput(result.container)!);
|
|
228
243
|
const text = panelText();
|
|
229
|
-
expect(
|
|
230
|
-
expect(
|
|
244
|
+
expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeTruthy();
|
|
245
|
+
expect(document.querySelector('[role="slider"][aria-label="Min"]')).toBeTruthy();
|
|
231
246
|
expect(text).not.toContain("Su");
|
|
232
247
|
});
|
|
233
248
|
|
|
@@ -239,11 +254,11 @@ describe("web Date field — type=time renders a time control", () => {
|
|
|
239
254
|
);
|
|
240
255
|
await openPanel(triggerInput(result.container)!);
|
|
241
256
|
// 9:00 AM → PM is a deterministic edit with no wheel animation in it.
|
|
242
|
-
await
|
|
257
|
+
await selectPeriod("PM");
|
|
243
258
|
|
|
244
259
|
// The control speaks `HH:mm`; the field re-serializes through the shared
|
|
245
260
|
// wire body, so what persists carries seconds like every other writer.
|
|
246
|
-
expect(onChange).toHaveBeenCalledWith("21:00:00");
|
|
261
|
+
await waitFor(() => expect(onChange).toHaveBeenCalledWith("21:00:00"));
|
|
247
262
|
});
|
|
248
263
|
|
|
249
264
|
it("adopts a seconds-less HH:mm value too (what Frappe hands a fresh field)", async () => {
|
|
@@ -292,7 +307,9 @@ describe("web Date field — type=datetime renders date AND time", () => {
|
|
|
292
307
|
await openPanel(triggerInput(result.container)!);
|
|
293
308
|
expect(panelText()).toContain("Su");
|
|
294
309
|
await pressText(document.body, "Time");
|
|
295
|
-
await waitFor(() =>
|
|
310
|
+
await waitFor(() =>
|
|
311
|
+
expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeTruthy(),
|
|
312
|
+
);
|
|
296
313
|
});
|
|
297
314
|
|
|
298
315
|
it("a day change keeps the existing time — and the picker, not the serializer, keeps it", async () => {
|
|
@@ -330,8 +347,8 @@ describe("web Date field — type=datetime renders date AND time", () => {
|
|
|
330
347
|
await pressText(document.body, "Time");
|
|
331
348
|
// 2:30 PM → AM. Carrying `previousValue` here would have pinned the old
|
|
332
349
|
// 14:30 back over the edit the user just made.
|
|
333
|
-
await
|
|
334
|
-
expect(onChange).toHaveBeenLastCalledWith("2026-03-05 02:30:00");
|
|
350
|
+
await selectPeriod("AM");
|
|
351
|
+
await waitFor(() => expect(onChange).toHaveBeenLastCalledWith("2026-03-05 02:30:00"));
|
|
335
352
|
});
|
|
336
353
|
});
|
|
337
354
|
|
|
@@ -412,7 +429,7 @@ describe("web and native persist byte-identical wire strings", () => {
|
|
|
412
429
|
|
|
413
430
|
it("time — moving 9:00 AM to 9:00 PM writes the same string on both halves", async () => {
|
|
414
431
|
const web = await webPick("time", "09:00:00", async () => {
|
|
415
|
-
await
|
|
432
|
+
await selectPeriod("PM");
|
|
416
433
|
});
|
|
417
434
|
cleanup();
|
|
418
435
|
mockState.picks.length = 0;
|