@morscherlab/mint-sdk 1.0.0-rc.2 → 1.0.0-rc.5
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/__tests__/components/AppTopBar.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/DoseCalculatorVolumeField.test.d.ts +1 -0
- package/dist/__tests__/components/PlateMapEditorToolbarInternal.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.controls.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.shell.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStep.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepEditor.state.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepParameterField.test.d.ts +1 -0
- package/dist/__tests__/components/ReagentList.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.colors.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.drag.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.groups.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.selection.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelectorSampleRow.test.d.ts +1 -0
- package/dist/__tests__/components/ScheduleCalendar.test.d.ts +1 -0
- package/dist/__tests__/components/SettingsModal.schema.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.colors.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.conditions.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.geometry.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.interaction.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.legend.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.rendering.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.sampleDrop.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/classify.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/columns.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/compose.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/cooccurrence.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/fingerprint.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/integration.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/template.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/tokenize.test.d.ts +1 -0
- package/dist/__tests__/composables/useAutoGroupInputSources.test.d.ts +1 -0
- package/dist/__tests__/composables/useScheduleCalendarLayout.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsComponents.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsExports.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsParsing.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTemplates.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTheme.test.d.ts +1 -0
- package/dist/components/AppTopBar.navigation.d.ts +11 -0
- package/dist/components/BaseButton.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +1 -1
- package/dist/components/BaseInput.vue.d.ts +2 -2
- package/dist/components/BasePill.vue.d.ts +1 -1
- package/dist/components/BaseRadioGroup.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseSlider.vue.d.ts +2 -2
- package/dist/components/BaseTextarea.vue.d.ts +2 -2
- package/dist/components/BaseToggle.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
- package/dist/components/ColorSlider.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +2 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -2
- package/dist/components/DoseCalculatorVolumeField.vue.d.ts +15 -0
- package/dist/components/DropdownButton.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/FormulaInput.vue.d.ts +2 -2
- package/dist/components/IconButton.vue.d.ts +1 -1
- package/dist/components/LoadingSpinner.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +2 -2
- package/dist/components/MultiSelect.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlateMapEditor.vue.d.ts +6 -6
- package/dist/components/PluginWorkspaceView.controls.d.ts +28 -0
- package/dist/components/PluginWorkspaceView.navigation.d.ts +29 -0
- package/dist/components/PluginWorkspaceView.props.d.ts +151 -0
- package/dist/components/PluginWorkspaceView.shell.d.ts +19 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +46 -195
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStep.presentation.d.ts +4 -0
- package/dist/components/ProtocolStepEditor.state.d.ts +18 -0
- package/dist/components/ProtocolStepParameterField.vue.d.ts +12 -0
- package/dist/components/ReagentList.presentation.d.ts +16 -0
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SampleSelector.colors.d.ts +13 -0
- package/dist/components/SampleSelector.drag.d.ts +24 -0
- package/dist/components/SampleSelector.groups.d.ts +15 -0
- package/dist/components/SampleSelector.selection.d.ts +26 -0
- package/dist/components/SampleSelector.vue.d.ts +4 -1
- package/dist/components/SampleSelectorSampleRow.vue.d.ts +21 -0
- package/dist/components/SegmentedControl.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +2 -2
- package/dist/components/SequenceProgressBar.vue.d.ts +1 -1
- package/dist/components/SettingsModal.schema.d.ts +9 -0
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +2 -2
- package/dist/components/TimePicker.vue.d.ts +2 -2
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +2 -2
- package/dist/components/WellPlate.colors.d.ts +9 -0
- package/dist/components/WellPlate.conditions.d.ts +26 -0
- package/dist/components/WellPlate.geometry.d.ts +23 -0
- package/dist/components/WellPlate.interaction.d.ts +71 -0
- package/dist/components/WellPlate.legend.d.ts +2 -0
- package/dist/components/WellPlate.rendering.d.ts +24 -0
- package/dist/components/WellPlate.sampleDrop.d.ts +8 -0
- package/dist/components/WellPlate.vue.d.ts +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/internal/ActionItemInternal.vue.d.ts +1 -1
- package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +28 -0
- package/dist/{components-BhK-dW99.js → components-DtHA2bgp.js} +3754 -2991
- package/dist/components-DtHA2bgp.js.map +1 -0
- package/dist/composables/autoGroup/classKey.d.ts +4 -0
- package/dist/composables/autoGroup/classify.d.ts +28 -0
- package/dist/composables/autoGroup/colors.d.ts +2 -0
- package/dist/composables/autoGroup/columns.d.ts +10 -0
- package/dist/composables/autoGroup/compose.d.ts +8 -0
- package/dist/composables/autoGroup/cooccurrence.d.ts +2 -0
- package/dist/composables/autoGroup/csv-shim.d.ts +2 -0
- package/dist/composables/autoGroup/fingerprint.d.ts +3 -0
- package/dist/composables/autoGroup/index.d.ts +16 -0
- package/dist/composables/autoGroup/replicatePreGroup.d.ts +38 -0
- package/dist/composables/autoGroup/template.d.ts +15 -0
- package/dist/composables/autoGroup/tokenize.d.ts +8 -0
- package/dist/composables/autoGroupConstants.d.ts +1 -0
- package/dist/composables/autoGroupGrouping.d.ts +3 -0
- package/dist/composables/controlComponentBindings.d.ts +7 -0
- package/dist/composables/controlSchemaAdapters.d.ts +20 -0
- package/dist/composables/controlSchemaDoseDesign.d.ts +11 -0
- package/dist/composables/controlSchemaFormFields.d.ts +3 -0
- package/dist/composables/controlSchemaLayout.d.ts +7 -0
- package/dist/composables/controlSchemaModel.d.ts +5 -0
- package/dist/composables/controlSchemaNormalize.d.ts +15 -0
- package/dist/composables/controlSchemaTypes.d.ts +305 -0
- package/dist/composables/controlSchemaUtils.d.ts +9 -0
- package/dist/composables/controlWorkspaceOptions.d.ts +2 -0
- package/dist/composables/formBuilderSchema.d.ts +18 -0
- package/dist/composables/index.js +3 -3
- package/dist/composables/pluginEndpointBuilder.d.ts +13 -0
- package/dist/composables/protocolTemplateCatalog.d.ts +26 -0
- package/dist/composables/useAutoGroup.d.ts +61 -74
- package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
- package/dist/composables/useBioTemplateControls.d.ts +1 -1
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +1 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +1 -1
- package/dist/composables/useControlSchema.d.ts +8 -346
- package/dist/composables/useControlWorkspace.d.ts +5 -0
- package/dist/composables/useForm.d.ts +2 -33
- package/dist/composables/useFormBuilder.d.ts +2 -9
- package/dist/composables/useFormValidation.d.ts +34 -0
- package/dist/composables/usePluginClient.d.ts +1 -4
- package/dist/composables/useProtocolTemplates.d.ts +2 -24
- package/dist/composables/useScheduleCalendarLayout.d.ts +49 -0
- package/dist/{composables-Bg7CFuNz.js → composables-Dlg8jenH.js} +33 -31
- package/dist/composables-Dlg8jenH.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/install.js +2 -2
- package/dist/styles.css +547 -516
- package/dist/templates/adapters.d.ts +14 -47
- package/dist/templates/assayLookups.d.ts +3 -0
- package/dist/templates/assayMatrixAdapters.d.ts +6 -0
- package/dist/templates/assayMatrixBuilder.d.ts +2 -0
- package/dist/templates/assayNormalizers.d.ts +4 -0
- package/dist/templates/builderDefaults.d.ts +1 -0
- package/dist/templates/builderIdUtils.d.ts +4 -0
- package/dist/templates/builderPresetControls.d.ts +10 -0
- package/dist/templates/builderReadUtils.d.ts +8 -0
- package/dist/templates/builders.d.ts +26 -67
- package/dist/templates/calibrationCurveAdapters.d.ts +4 -0
- package/dist/templates/calibrationCurveBuilder.d.ts +2 -0
- package/dist/templates/calibrationNormalizers.d.ts +5 -0
- package/dist/templates/componentBindingCatalog.d.ts +25 -0
- package/dist/templates/componentBindingHelpers.d.ts +17 -0
- package/dist/templates/componentDoseResponseProps.d.ts +3 -0
- package/dist/templates/componentGenericProps.d.ts +8 -0
- package/dist/templates/componentPlateHelpers.d.ts +5 -0
- package/dist/templates/componentPlateMapProps.d.ts +3 -0
- package/dist/templates/componentPropsFactory.d.ts +3 -0
- package/dist/templates/componentQpcrPlateProps.d.ts +3 -0
- package/dist/templates/componentTargetResolvers.d.ts +5 -0
- package/dist/templates/componentTemplateProps.d.ts +3 -0
- package/dist/templates/controlSchemaClone.d.ts +4 -0
- package/dist/templates/controlSchemaConstants.d.ts +10 -0
- package/dist/templates/controlSchemaMerge.d.ts +3 -0
- package/dist/templates/controlSchemaTargets.d.ts +17 -0
- package/dist/templates/controlSchemaTypes.d.ts +4 -0
- package/dist/templates/controlSchemas.d.ts +4 -4
- package/dist/templates/defaultBioTemplateBuilder.d.ts +2 -0
- package/dist/templates/doseResponseAdapters.d.ts +4 -0
- package/dist/templates/doseResponseBuilder.d.ts +2 -0
- package/dist/templates/elisaAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +2 -0
- package/dist/templates/flowCytometryPanelBuilder.d.ts +2 -0
- package/dist/templates/flowNormalizers.d.ts +8 -0
- package/dist/templates/flowPanelAdapters.d.ts +4 -0
- package/dist/templates/index.js +1 -1
- package/dist/templates/instrumentRunAdapterHelpers.d.ts +8 -0
- package/dist/templates/instrumentRunAdapters.d.ts +8 -0
- package/dist/templates/instrumentRunBuilder.d.ts +2 -0
- package/dist/templates/lcmsBatchCollectionBuilder.d.ts +2 -0
- package/dist/templates/plateGeometry.d.ts +4 -0
- package/dist/templates/plateMapAdapters.d.ts +3 -0
- package/dist/templates/plateMapBuilder.d.ts +2 -0
- package/dist/templates/presetControlSchemas.d.ts +534 -0
- package/dist/templates/protocolAdapters.d.ts +5 -0
- package/dist/templates/protocolNormalizers.d.ts +6 -0
- package/dist/templates/protocolStepsBuilder.d.ts +2 -0
- package/dist/templates/qpcrAdapters.d.ts +5 -0
- package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +2 -0
- package/dist/templates/qpcrPlateBuilder.d.ts +2 -0
- package/dist/templates/reagentAdapters.d.ts +5 -0
- package/dist/templates/reagentListBuilder.d.ts +2 -0
- package/dist/templates/runNormalizers.d.ts +10 -0
- package/dist/templates/sampleNormalizers.d.ts +4 -0
- package/dist/templates/samplePrepAdapters.d.ts +4 -0
- package/dist/templates/samplePrepBuilder.d.ts +2 -0
- package/dist/templates/sampleSheetAdapters.d.ts +5 -0
- package/dist/templates/sampleSheetBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +2 -0
- package/dist/templates/targetedMetabolomicsHelpers.d.ts +5 -0
- package/dist/templates/templateAdapterTypes.d.ts +48 -0
- package/dist/templates/templateControlSchemas.d.ts +400 -0
- package/dist/templates/templateCreateOptions.d.ts +165 -0
- package/dist/templates/templateEnvelopes.d.ts +9 -0
- package/dist/templates/templatePackCollectionBuilder.d.ts +2 -0
- package/dist/templates/templatePresetCollectionBuilder.d.ts +18 -0
- package/dist/templates/templateQpcrTypes.d.ts +42 -0
- package/dist/templates/templateValidators.d.ts +13 -0
- package/dist/templates/timeCourseAdapters.d.ts +5 -0
- package/dist/templates/timeCourseBuilder.d.ts +2 -0
- package/dist/templates/types.d.ts +5 -250
- package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +2 -0
- package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +2 -0
- package/dist/{templates-BorLR_7p.js → templates-DtdUvJ4c.js} +3565 -3411
- package/dist/templates-DtdUvJ4c.js.map +1 -0
- package/dist/types/auto-group.d.ts +79 -9
- package/dist/types/componentLabTypes.d.ts +161 -0
- package/dist/types/componentWorkflowTypes.d.ts +150 -0
- package/dist/types/components.d.ts +2 -311
- package/dist/{useProtocolTemplates-n6AJqSqv.js → useProtocolTemplates-Bm5vyH4_.js} +1220 -454
- package/dist/useProtocolTemplates-Bm5vyH4_.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.navigation.test.ts +70 -0
- package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
- package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
- package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
- package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
- package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +41 -0
- package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
- package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
- package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
- package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
- package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +100 -0
- package/src/__tests__/components/SampleSelector.groups.test.ts +81 -0
- package/src/__tests__/components/SampleSelector.selection.test.ts +70 -0
- package/src/__tests__/components/SampleSelector.test.ts +32 -0
- package/src/__tests__/components/SampleSelectorSampleRow.test.ts +37 -0
- package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
- package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
- package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
- package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
- package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
- package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
- package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
- package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
- package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
- package/src/__tests__/composables/autoGroup/compose.test.ts +227 -0
- package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
- package/src/__tests__/composables/autoGroup/fingerprint.test.ts +50 -0
- package/src/__tests__/composables/autoGroup/integration.test.ts +79 -0
- package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
- package/src/__tests__/composables/useAutoGroup.test.ts +129 -625
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +107 -0
- package/src/__tests__/composables/useControlSchema.test.ts +23 -0
- package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
- package/src/__tests__/docs/extractDocsComponents.test.ts +142 -0
- package/src/__tests__/docs/extractDocsExports.test.ts +77 -0
- package/src/__tests__/docs/extractDocsParsing.test.ts +69 -0
- package/src/__tests__/docs/extractDocsTemplates.test.ts +54 -0
- package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +1 -1
- package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
- package/src/components/AppSidebar.vue +2 -6
- package/src/components/AppTopBar.navigation.ts +62 -0
- package/src/components/AppTopBar.vue +17 -44
- package/src/components/AutoGroupModal.story.vue +50 -0
- package/src/components/AutoGroupModal.vue +441 -158
- package/src/components/ControlWorkspaceView.vue +2 -6
- package/src/components/DoseCalculator.vue +13 -73
- package/src/components/DoseCalculatorVolumeField.vue +61 -0
- package/src/components/ExperimentTimeline.vue +6 -31
- package/src/components/FormBuilder.vue +2 -7
- package/src/components/PlateMapEditor.vue +32 -106
- package/src/components/PluginWorkspaceView.controls.ts +182 -0
- package/src/components/PluginWorkspaceView.navigation.ts +106 -0
- package/src/components/PluginWorkspaceView.props.ts +174 -0
- package/src/components/PluginWorkspaceView.shell.ts +66 -0
- package/src/components/PluginWorkspaceView.vue +85 -404
- package/src/components/ProtocolStep.presentation.ts +31 -0
- package/src/components/ProtocolStepEditor.state.ts +104 -0
- package/src/components/ProtocolStepEditor.vue +48 -179
- package/src/components/ProtocolStepParameterField.vue +134 -0
- package/src/components/ReagentList.presentation.ts +105 -0
- package/src/components/ReagentList.vue +16 -79
- package/src/components/SampleSelector.colors.ts +43 -0
- package/src/components/SampleSelector.drag.ts +164 -0
- package/src/components/SampleSelector.groups.ts +109 -0
- package/src/components/SampleSelector.selection.ts +103 -0
- package/src/components/SampleSelector.vue +82 -349
- package/src/components/SampleSelectorSampleRow.vue +64 -0
- package/src/components/ScheduleCalendar.vue +44 -199
- package/src/components/SettingsModal.schema.ts +71 -0
- package/src/components/SettingsModal.vue +16 -46
- package/src/components/WellPlate.colors.ts +56 -0
- package/src/components/WellPlate.conditions.ts +100 -0
- package/src/components/WellPlate.geometry.ts +91 -0
- package/src/components/WellPlate.interaction.ts +272 -0
- package/src/components/WellPlate.legend.ts +8 -0
- package/src/components/WellPlate.rendering.ts +105 -0
- package/src/components/WellPlate.sampleDrop.ts +73 -0
- package/src/components/WellPlate.vue +102 -550
- package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
- package/src/composables/autoGroup/classKey.ts +5 -0
- package/src/composables/autoGroup/classify.ts +205 -0
- package/src/composables/autoGroup/colors.ts +6 -0
- package/src/composables/autoGroup/columns.ts +226 -0
- package/src/composables/autoGroup/compose.ts +156 -0
- package/src/composables/autoGroup/cooccurrence.ts +46 -0
- package/src/composables/autoGroup/csv-shim.ts +44 -0
- package/src/composables/autoGroup/fingerprint.ts +49 -0
- package/src/composables/autoGroup/index.ts +20 -0
- package/src/composables/autoGroup/replicatePreGroup.ts +90 -0
- package/src/composables/autoGroup/template.ts +126 -0
- package/src/composables/autoGroup/tokenize.ts +41 -0
- package/src/composables/autoGroup/vocab.json +67 -0
- package/src/composables/autoGroupConstants.ts +4 -0
- package/src/composables/autoGroupGrouping.ts +148 -0
- package/src/composables/controlComponentBindings.ts +80 -0
- package/src/composables/controlSchemaAdapters.ts +196 -0
- package/src/composables/controlSchemaDoseDesign.ts +215 -0
- package/src/composables/controlSchemaFormFields.ts +61 -0
- package/src/composables/controlSchemaLayout.ts +59 -0
- package/src/composables/controlSchemaModel.ts +163 -0
- package/src/composables/controlSchemaNormalize.ts +101 -0
- package/src/composables/controlSchemaTypes.ts +364 -0
- package/src/composables/controlSchemaUtils.ts +36 -0
- package/src/composables/controlWorkspaceOptions.ts +21 -0
- package/src/composables/formBuilderSchema.ts +153 -0
- package/src/composables/pluginEndpointBuilder.ts +203 -0
- package/src/composables/protocolTemplateCatalog.ts +325 -0
- package/src/composables/useAutoGroup.ts +395 -549
- package/src/composables/useAutoGroupInputSources.ts +147 -0
- package/src/composables/useBioTemplateControls.ts +1 -1
- package/src/composables/useBioTemplatePresetWorkspace.ts +1 -1
- package/src/composables/useBioTemplateWorkspace.ts +1 -1
- package/src/composables/useControlSchema.ts +64 -1312
- package/src/composables/useControlWorkspace.ts +201 -0
- package/src/composables/useForm.ts +5 -187
- package/src/composables/useFormBuilder.ts +11 -153
- package/src/composables/useFormValidation.ts +154 -0
- package/src/composables/usePluginClient.ts +10 -193
- package/src/composables/useProtocolTemplates.ts +10 -328
- package/src/composables/useScheduleCalendarLayout.ts +287 -0
- package/src/styles/components/auto-group-modal.css +248 -310
- package/src/templates/adapters.ts +89 -930
- package/src/templates/assayLookups.ts +33 -0
- package/src/templates/assayMatrixAdapters.ts +78 -0
- package/src/templates/assayMatrixBuilder.ts +59 -0
- package/src/templates/assayNormalizers.ts +34 -0
- package/src/templates/builderDefaults.ts +11 -0
- package/src/templates/builderIdUtils.ts +20 -0
- package/src/templates/builderPresetControls.ts +165 -0
- package/src/templates/builderReadUtils.ts +57 -0
- package/src/templates/builders.ts +122 -2350
- package/src/templates/calibrationCurveAdapters.ts +59 -0
- package/src/templates/calibrationCurveBuilder.ts +99 -0
- package/src/templates/calibrationNormalizers.ts +60 -0
- package/src/templates/componentBindingCatalog.ts +90 -0
- package/src/templates/componentBindingHelpers.ts +93 -0
- package/src/templates/componentBindings.ts +12 -461
- package/src/templates/componentDoseResponseProps.ts +42 -0
- package/src/templates/componentGenericProps.ts +77 -0
- package/src/templates/componentPlateHelpers.ts +29 -0
- package/src/templates/componentPlateMapProps.ts +32 -0
- package/src/templates/componentPropsFactory.ts +21 -0
- package/src/templates/componentQpcrPlateProps.ts +28 -0
- package/src/templates/componentTargetResolvers.ts +69 -0
- package/src/templates/componentTemplateProps.ts +78 -0
- package/src/templates/controlSchemaClone.ts +32 -0
- package/src/templates/controlSchemaConstants.ts +11 -0
- package/src/templates/controlSchemaMerge.ts +40 -0
- package/src/templates/controlSchemaTargets.ts +87 -0
- package/src/templates/controlSchemaTypes.ts +20 -0
- package/src/templates/controlSchemas.ts +22 -704
- package/src/templates/defaultBioTemplateBuilder.ts +124 -0
- package/src/templates/doseResponseAdapters.ts +45 -0
- package/src/templates/doseResponseBuilder.ts +44 -0
- package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
- package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
- package/src/templates/flowCytometryPanelBuilder.ts +53 -0
- package/src/templates/flowNormalizers.ts +58 -0
- package/src/templates/flowPanelAdapters.ts +58 -0
- package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
- package/src/templates/instrumentRunAdapters.ts +163 -0
- package/src/templates/instrumentRunBuilder.ts +97 -0
- package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
- package/src/templates/plateGeometry.ts +62 -0
- package/src/templates/plateMapAdapters.ts +36 -0
- package/src/templates/plateMapBuilder.ts +43 -0
- package/src/templates/presetControlSchemas.ts +258 -0
- package/src/templates/protocolAdapters.ts +69 -0
- package/src/templates/protocolNormalizers.ts +37 -0
- package/src/templates/protocolStepsBuilder.ts +36 -0
- package/src/templates/qpcrAdapters.ts +104 -0
- package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
- package/src/templates/qpcrPlateBuilder.ts +96 -0
- package/src/templates/reagentAdapters.ts +77 -0
- package/src/templates/reagentListBuilder.ts +30 -0
- package/src/templates/runNormalizers.ts +63 -0
- package/src/templates/sampleNormalizers.ts +58 -0
- package/src/templates/samplePrepAdapters.ts +63 -0
- package/src/templates/samplePrepBuilder.ts +51 -0
- package/src/templates/sampleSheetAdapters.ts +75 -0
- package/src/templates/sampleSheetBuilder.ts +23 -0
- package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
- package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
- package/src/templates/templateAdapterTypes.ts +58 -0
- package/src/templates/templateControlSchemas.ts +320 -0
- package/src/templates/templateCreateOptions.ts +208 -0
- package/src/templates/templateEnvelopes.ts +137 -0
- package/src/templates/templatePackCollectionBuilder.ts +23 -0
- package/src/templates/templatePresetCollectionBuilder.ts +139 -0
- package/src/templates/templateQpcrTypes.ts +48 -0
- package/src/templates/templateValidators.ts +414 -0
- package/src/templates/timeCourseAdapters.ts +73 -0
- package/src/templates/timeCourseBuilder.ts +64 -0
- package/src/templates/types.ts +79 -275
- package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
- package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
- package/src/types/auto-group.ts +107 -9
- package/src/types/componentLabTypes.ts +235 -0
- package/src/types/componentWorkflowTypes.ts +190 -0
- package/src/types/components.ts +74 -424
- package/dist/components-BhK-dW99.js.map +0 -1
- package/dist/composables-Bg7CFuNz.js.map +0 -1
- package/dist/templates-BorLR_7p.js.map +0 -1
- package/dist/useProtocolTemplates-n6AJqSqv.js.map +0 -1
|
@@ -1,374 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
defaultValueForControl,
|
|
3
|
+
normalizeControls,
|
|
4
|
+
} from './controlSchemaNormalize'
|
|
5
|
+
import {
|
|
6
|
+
controlToFormField,
|
|
7
|
+
} from './controlSchemaFormFields'
|
|
8
|
+
import {
|
|
9
|
+
controlsToFormSchema,
|
|
10
|
+
controlsToSectionFormSchema,
|
|
11
|
+
controlsToSectionFormSchemas,
|
|
12
|
+
controlsToSettingsSchema,
|
|
13
|
+
controlsToSidebarPanels,
|
|
14
|
+
controlsToTopBarSettingsConfig,
|
|
15
|
+
controlsToViewItems,
|
|
16
|
+
} from './controlSchemaAdapters'
|
|
2
17
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from '
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
href?: string
|
|
52
|
-
disabled?: boolean
|
|
53
|
-
children?: PillNavItem['children']
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface ControlSidebarConfig extends Omit<ControlSectionConfig, 'id' | 'title' | 'description' | 'columns'> {
|
|
57
|
-
enabled?: boolean
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface ControlDefinition {
|
|
61
|
-
type?: FormFieldType
|
|
62
|
-
label?: string
|
|
63
|
-
default?: unknown
|
|
64
|
-
defaultValue?: unknown
|
|
65
|
-
placeholder?: string
|
|
66
|
-
hint?: string
|
|
67
|
-
size?: 'sm' | 'md' | 'lg'
|
|
68
|
-
disabled?: boolean
|
|
69
|
-
readonly?: boolean
|
|
70
|
-
required?: boolean | string
|
|
71
|
-
min?: number | { value: number; message: string }
|
|
72
|
-
max?: number | { value: number; message: string }
|
|
73
|
-
minLength?: number | { value: number; message: string }
|
|
74
|
-
maxLength?: number | { value: number; message: string }
|
|
75
|
-
email?: boolean | string
|
|
76
|
-
pattern?: string | { value: string; message: string }
|
|
77
|
-
validation?: FieldValidation
|
|
78
|
-
condition?: FieldCondition
|
|
79
|
-
access?: AccessPolicy
|
|
80
|
-
visibleFor?: AccessAudienceInput
|
|
81
|
-
requiresAdmin?: boolean
|
|
82
|
-
permissions?: readonly string[]
|
|
83
|
-
anyPermissions?: readonly string[]
|
|
84
|
-
options?: readonly ControlOption[]
|
|
85
|
-
section?: string
|
|
86
|
-
sectionLabel?: string
|
|
87
|
-
sectionDescription?: string
|
|
88
|
-
sectionSubtitle?: string
|
|
89
|
-
view?: string
|
|
90
|
-
order?: number
|
|
91
|
-
colSpan?: number
|
|
92
|
-
props?: Record<string, unknown>
|
|
93
|
-
sidebar?: boolean | ControlSidebarConfig
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export type ControlSchema = Record<string, ControlInput>
|
|
97
|
-
export type ControlFormSchema = Extract<FormSchema, { sections: FormSectionSchema[] }>
|
|
98
|
-
|
|
99
|
-
export interface ControlSchemaOptions {
|
|
100
|
-
view?: string
|
|
101
|
-
views?: Record<string, ControlViewConfig>
|
|
102
|
-
section?: string
|
|
103
|
-
sectionLabel?: string
|
|
104
|
-
sections?: Record<string, ControlSectionConfig>
|
|
105
|
-
columns?: 1 | 2 | 3
|
|
106
|
-
submitLabel?: string
|
|
107
|
-
cancelLabel?: string
|
|
108
|
-
showCancel?: boolean
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export interface ControlWorkspaceOptions extends ControlSchemaOptions {
|
|
112
|
-
initialValues?: Record<string, unknown>
|
|
113
|
-
topBarSettings?: Omit<TopBarSettingsConfig, 'schema' | 'controls' | 'controlOptions' | 'values'>
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface ControlModelSectionConfig extends ControlSectionConfig {
|
|
117
|
-
controls: ControlSchema
|
|
118
|
-
sidebar?: boolean | ControlSidebarConfig
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export interface ControlModelViewConfig extends ControlViewConfig {
|
|
122
|
-
controls?: ControlSchema
|
|
123
|
-
section?: string
|
|
124
|
-
sectionLabel?: string
|
|
125
|
-
sectionDescription?: string
|
|
126
|
-
sections?: Record<string, ControlModelSectionConfig>
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export interface ControlModel extends Omit<ControlWorkspaceOptions, 'sections' | 'views'> {
|
|
130
|
-
controls?: ControlSchema
|
|
131
|
-
sections?: Record<string, ControlModelSectionConfig>
|
|
132
|
-
views?: Record<string, ControlModelViewConfig>
|
|
133
|
-
/** Optional SDK component bindings returned with generated component props for custom workspace slots. */
|
|
134
|
-
componentBindings?: ControlComponentBindingsConfig
|
|
135
|
-
/** Alias for componentBindings in raw control models. */
|
|
136
|
-
components?: ControlComponentBindingsConfig
|
|
137
|
-
/** Optional ControlWorkspaceView componentProps mapping returned with the generated controls/options. */
|
|
138
|
-
componentProps?: ControlComponentPropsMap
|
|
139
|
-
/** Optional named componentProps mappings returned for multiple SDK components. */
|
|
140
|
-
componentPropsById?: ControlComponentPropsByIdMap
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export interface ControlModelBinding {
|
|
144
|
-
controls: ControlSchema
|
|
145
|
-
controlOptions: ControlWorkspaceOptions
|
|
146
|
-
componentBindings?: ControlComponentBindingsConfig
|
|
147
|
-
componentProps?: ControlComponentPropsMap
|
|
148
|
-
componentPropsById?: ControlComponentPropsByIdMap
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export interface ControlSidebarBinding {
|
|
152
|
-
panels: Record<string, SidebarToolSection[]>
|
|
153
|
-
forms: Record<string, ControlFormSchema>
|
|
154
|
-
viewIds: string[]
|
|
155
|
-
viewItems: PillNavItem[]
|
|
156
|
-
defaultView: string
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export interface ControlFormBinding {
|
|
160
|
-
schema: ControlFormSchema
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export interface ControlSettingsBinding {
|
|
164
|
-
schema: SettingsModalSchema
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export interface ControlTopBarSettingsBinding {
|
|
168
|
-
showSettings: true
|
|
169
|
-
settingsConfig: TopBarSettingsConfig
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export interface ControlWorkspaceFormBinding extends ControlFormBinding {
|
|
173
|
-
modelValue: Record<string, unknown>
|
|
174
|
-
'onUpdate:modelValue': (values: Record<string, unknown>) => void
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export interface ControlWorkspaceSidebarBinding extends ControlSidebarBinding {
|
|
178
|
-
activeView: string
|
|
179
|
-
modelValue: Record<string, unknown>
|
|
180
|
-
'onUpdate:modelValue': (values: Record<string, unknown>) => void
|
|
181
|
-
values: Record<string, unknown>
|
|
182
|
-
'onUpdate:values': (values: Record<string, unknown>) => void
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export interface ControlWorkspaceTopBarSettingsBinding extends ControlTopBarSettingsBinding {
|
|
186
|
-
onSettingsValuesChange: (values: Record<string, unknown>) => void
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export interface ControlWorkspacePillNavBinding {
|
|
190
|
-
items: PillNavItem[]
|
|
191
|
-
currentItemId: string
|
|
192
|
-
onSelect: (item: PillNavItem) => void
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export interface ControlWorkspaceTopBarBinding extends ControlWorkspaceTopBarSettingsBinding {
|
|
196
|
-
pillNav: PillNavItem[]
|
|
197
|
-
currentPillId: string
|
|
198
|
-
onPillSelect: (item: PillNavItem) => void
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export type ControlWorkspaceAppTopBarPillBinding = ControlWorkspaceTopBarBinding
|
|
202
|
-
|
|
203
|
-
export interface ControlWorkspaceComponentBindings {
|
|
204
|
-
form: ControlWorkspaceFormBinding
|
|
205
|
-
sidebar: ControlWorkspaceSidebarBinding
|
|
206
|
-
topBar: ComputedRef<ControlWorkspaceTopBarBinding>
|
|
207
|
-
topBarSettings: ControlWorkspaceTopBarSettingsBinding
|
|
208
|
-
pillNav: ControlWorkspacePillNavBinding
|
|
209
|
-
componentBindings: ComputedRef<ControlComponentBinding[]>
|
|
210
|
-
componentBindingsById: ComputedRef<ControlComponentBindingsById>
|
|
211
|
-
componentProps: ComputedRef<Record<string, unknown>>
|
|
212
|
-
componentPropsById: ComputedRef<Record<string, Record<string, unknown>>>
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export type ControlComponentPropSource<TValues extends Record<string, unknown> = Record<string, unknown>> =
|
|
216
|
-
| (keyof TValues & string)
|
|
217
|
-
| ((values: TValues) => unknown)
|
|
218
|
-
|
|
219
|
-
export type ControlComponentPropsMap<TValues extends Record<string, unknown> = Record<string, unknown>> =
|
|
220
|
-
| readonly (keyof TValues & string)[]
|
|
221
|
-
| Record<string, ControlComponentPropSource<TValues>>
|
|
222
|
-
|
|
223
|
-
export type ControlComponentPropsByIdMap<TValues extends Record<string, unknown> = Record<string, unknown>> =
|
|
224
|
-
Record<string, ControlComponentPropsMap<TValues>>
|
|
225
|
-
|
|
226
|
-
export interface ControlComponentBindingConfig<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
227
|
-
id?: string
|
|
228
|
-
component: string
|
|
229
|
-
props?: ControlComponentPropsMap<TValues>
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export interface ControlComponentBindingRecordConfig<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
233
|
-
component: string
|
|
234
|
-
props?: ControlComponentPropsMap<TValues>
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export type ControlComponentBindingsConfig<TValues extends Record<string, unknown> = Record<string, unknown>> =
|
|
238
|
-
| readonly ControlComponentBindingConfig<TValues>[]
|
|
239
|
-
| Record<string, ControlComponentBindingRecordConfig<TValues>>
|
|
240
|
-
|
|
241
|
-
export interface ControlComponentBinding {
|
|
242
|
-
id: string
|
|
243
|
-
component: string
|
|
244
|
-
props: Record<string, unknown>
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export type ControlComponentBindingsById = Record<string, ControlComponentBinding>
|
|
248
|
-
|
|
249
|
-
export interface WellPlateControlPropsOptions<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
250
|
-
selectedWells?: ControlComponentPropSource<TValues>
|
|
251
|
-
format?: ControlComponentPropSource<TValues>
|
|
252
|
-
wells?: ControlComponentPropSource<TValues>
|
|
253
|
-
disabled?: ControlComponentPropSource<TValues>
|
|
254
|
-
readonly?: ControlComponentPropSource<TValues>
|
|
255
|
-
showLegend?: ControlComponentPropSource<TValues>
|
|
256
|
-
showSampleTypeIndicator?: ControlComponentPropSource<TValues>
|
|
257
|
-
/** Listener for WellPlate v-model updates. Set false to keep generated props one-way. */
|
|
258
|
-
onUpdateModelValue?: ((values: TValues) => (wellIds: string[]) => void) | false
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
export interface DoseCalculatorControlPropsOptions<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
262
|
-
mode?: ControlComponentPropSource<TValues>
|
|
263
|
-
targetWells?: ControlComponentPropSource<TValues>
|
|
264
|
-
/** Control value key used by the default apply-to-wells handler. */
|
|
265
|
-
wells?: ControlComponentPropSource<TValues>
|
|
266
|
-
disabled?: ControlComponentPropSource<TValues>
|
|
267
|
-
molecularWeight?: ControlComponentPropSource<TValues>
|
|
268
|
-
/** Listener for DoseCalculator apply-to-wells. Set false to keep generated props one-way. */
|
|
269
|
-
onApplyToWells?: ((values: TValues) => (results: WellConcentration[]) => void) | false
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export interface WellPlateDoseControlPropsOptions<TValues extends Record<string, unknown> = Record<string, unknown>> {
|
|
273
|
-
plateId?: string
|
|
274
|
-
doseId?: string
|
|
275
|
-
plate?: WellPlateControlPropsOptions<TValues>
|
|
276
|
-
dose?: DoseCalculatorControlPropsOptions<TValues>
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export interface DoseDesignControlModelOptions {
|
|
280
|
-
viewId?: string
|
|
281
|
-
viewLabel?: string
|
|
282
|
-
sectionId?: string
|
|
283
|
-
sectionLabel?: string
|
|
284
|
-
sectionDescription?: string
|
|
285
|
-
selectedWells?: readonly string[]
|
|
286
|
-
plateFormat?: number
|
|
287
|
-
plateFormats?: readonly number[]
|
|
288
|
-
doseMode?: 'serial' | 'dilution' | 'conversion'
|
|
289
|
-
doseModes?: readonly ('serial' | 'dilution' | 'conversion')[]
|
|
290
|
-
disabled?: boolean
|
|
291
|
-
includeMolecularWeight?: boolean
|
|
292
|
-
molecularWeight?: number
|
|
293
|
-
componentProps?: WellPlateDoseControlPropsOptions
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
export interface UseControlSchemaReturn<TControls extends ControlSchema> {
|
|
297
|
-
controls: TControls
|
|
298
|
-
fields: FormFieldSchema[]
|
|
299
|
-
formSchema: ControlFormSchema
|
|
300
|
-
form: ControlFormBinding
|
|
301
|
-
settingsSchema: SettingsModalSchema
|
|
302
|
-
settings: ControlSettingsBinding
|
|
303
|
-
topBarSettingsConfig: TopBarSettingsConfig
|
|
304
|
-
topBarSettings: ControlTopBarSettingsBinding
|
|
305
|
-
sidebarPanels: Record<string, SidebarToolSection[]>
|
|
306
|
-
viewIds: string[]
|
|
307
|
-
viewItems: PillNavItem[]
|
|
308
|
-
defaultView: string
|
|
309
|
-
sectionSchemas: Record<string, ControlFormSchema>
|
|
310
|
-
sidebar: ControlSidebarBinding
|
|
311
|
-
initialValues: ControlValues<TControls>
|
|
312
|
-
sectionSchema: (sectionId: string) => ControlFormSchema
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export interface UseControlWorkspaceReturn<TControls extends ControlSchema>
|
|
316
|
-
extends Omit<UseControlSchemaReturn<TControls>, 'form' | 'sidebar' | 'topBarSettings'> {
|
|
317
|
-
schema: UseControlSchemaReturn<TControls>
|
|
318
|
-
values: ControlValues<TControls> & Record<string, unknown>
|
|
319
|
-
activeView: Ref<string>
|
|
320
|
-
form: ControlWorkspaceFormBinding
|
|
321
|
-
sidebar: ControlWorkspaceSidebarBinding
|
|
322
|
-
topBar: ComputedRef<ControlWorkspaceTopBarBinding>
|
|
323
|
-
pillNav: ControlWorkspacePillNavBinding
|
|
324
|
-
topBarSettings: ControlWorkspaceTopBarSettingsBinding
|
|
325
|
-
bindings: ControlWorkspaceComponentBindings
|
|
326
|
-
componentBindings: ComputedRef<ControlComponentBinding[]>
|
|
327
|
-
componentBindingsById: ComputedRef<ControlComponentBindingsById>
|
|
328
|
-
componentProps: ComputedRef<Record<string, unknown>>
|
|
329
|
-
componentPropsById: ComputedRef<Record<string, Record<string, unknown>>>
|
|
330
|
-
setActiveView: (viewId: string) => void
|
|
331
|
-
setValues: (values: Record<string, unknown>) => void
|
|
332
|
-
resetValues: (values?: Record<string, unknown>) => void
|
|
333
|
-
getComponentProps: (
|
|
334
|
-
mapping?: ControlComponentPropsMap<ControlValues<TControls> & Record<string, unknown>>
|
|
335
|
-
) => Record<string, unknown>
|
|
336
|
-
getComponentPropsById: (
|
|
337
|
-
mappings?: ControlComponentPropsByIdMap<ControlValues<TControls> & Record<string, unknown>>
|
|
338
|
-
) => Record<string, Record<string, unknown>>
|
|
339
|
-
getComponentBindings: (
|
|
340
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>
|
|
341
|
-
) => ControlComponentBinding[]
|
|
342
|
-
getComponentBindingsById: (
|
|
343
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>
|
|
344
|
-
) => ControlComponentBindingsById
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export type ControlValues<TControls extends ControlSchema> = {
|
|
348
|
-
[K in keyof TControls]: ControlValue<TControls[K]>
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
type ControlValue<TControl> =
|
|
352
|
-
TControl extends { default: infer TDefault }
|
|
353
|
-
? TDefault
|
|
354
|
-
: TControl extends { defaultValue: infer TDefaultValue }
|
|
355
|
-
? TDefaultValue
|
|
356
|
-
: TControl extends readonly [infer First, ...unknown[]]
|
|
357
|
-
? OptionValue<First>
|
|
358
|
-
: TControl extends ControlPrimitive
|
|
359
|
-
? TControl
|
|
360
|
-
: unknown
|
|
361
|
-
|
|
362
|
-
type OptionValue<TOption> = TOption extends SelectOption<infer TValue> ? TValue : TOption
|
|
363
|
-
|
|
364
|
-
interface NormalizedControl {
|
|
365
|
-
name: string
|
|
366
|
-
definition: ControlDefinition
|
|
367
|
-
type: FormFieldType
|
|
368
|
-
sectionId: string
|
|
369
|
-
viewId: string
|
|
370
|
-
order: number
|
|
371
|
-
}
|
|
18
|
+
ControlComponentBindingsConfig,
|
|
19
|
+
ControlSchema,
|
|
20
|
+
ControlSchemaOptions,
|
|
21
|
+
ControlValues,
|
|
22
|
+
UseControlSchemaReturn,
|
|
23
|
+
} from './controlSchemaTypes'
|
|
24
|
+
|
|
25
|
+
export type * from './controlSchemaTypes'
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
mergeControlWorkspaceOptions,
|
|
29
|
+
} from './controlWorkspaceOptions'
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
useControlWorkspace,
|
|
33
|
+
} from './useControlWorkspace'
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
controlValuesToComponentBindings,
|
|
37
|
+
controlValuesToComponentBindingsById,
|
|
38
|
+
controlValuesToComponentProps,
|
|
39
|
+
} from './controlComponentBindings'
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
controlsToFormSchema,
|
|
43
|
+
controlsToSectionFormSchema,
|
|
44
|
+
controlsToSectionFormSchemas,
|
|
45
|
+
controlsToSettingsSchema,
|
|
46
|
+
controlsToSidebarPanels,
|
|
47
|
+
controlsToTopBarSettingsConfig,
|
|
48
|
+
controlsToViewIds,
|
|
49
|
+
controlsToViewItems,
|
|
50
|
+
getDefaultControlView,
|
|
51
|
+
} from './controlSchemaAdapters'
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
defineControlModel,
|
|
55
|
+
isControlModelBinding,
|
|
56
|
+
resolveControlModel,
|
|
57
|
+
} from './controlSchemaModel'
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
defineDoseCalculatorControlProps,
|
|
61
|
+
defineDoseDesignControlModel,
|
|
62
|
+
defineWellPlateControlProps,
|
|
63
|
+
defineWellPlateDoseComponentBindings,
|
|
64
|
+
defineWellPlateDoseControlProps,
|
|
65
|
+
} from './controlSchemaDoseDesign'
|
|
372
66
|
|
|
373
67
|
/** Preserve literal control keys while marking an object as a MINT control schema. */
|
|
374
68
|
export function defineControls<TControls extends ControlSchema>(controls: TControls): TControls {
|
|
@@ -382,94 +76,6 @@ export function defineControlComponentBindings<TBindings extends ControlComponen
|
|
|
382
76
|
return bindings
|
|
383
77
|
}
|
|
384
78
|
|
|
385
|
-
/** Create a complete workspace component binding from a simple controls data model for ControlWorkspaceView, generated forms, and sidebars. */
|
|
386
|
-
export function defineControlModel(model: ControlModel): ControlModelBinding {
|
|
387
|
-
const {
|
|
388
|
-
controls: rootControls,
|
|
389
|
-
sections: rootSections,
|
|
390
|
-
views: modelViews,
|
|
391
|
-
components,
|
|
392
|
-
componentBindings,
|
|
393
|
-
componentProps,
|
|
394
|
-
componentPropsById,
|
|
395
|
-
...baseOptions
|
|
396
|
-
} = model
|
|
397
|
-
const resolvedComponentBindings = componentBindings ?? components
|
|
398
|
-
const controls: ControlSchema = {}
|
|
399
|
-
const views: Record<string, ControlViewConfig> = {}
|
|
400
|
-
const sections: Record<string, ControlSectionConfig> = {}
|
|
401
|
-
|
|
402
|
-
const defaultViewId = model.view ?? 'default'
|
|
403
|
-
const defaultSectionId = model.section ?? 'controls'
|
|
404
|
-
|
|
405
|
-
if (rootControls) {
|
|
406
|
-
registerSectionOptions(sections, defaultSectionId, {
|
|
407
|
-
id: defaultSectionId,
|
|
408
|
-
label: model.sectionLabel,
|
|
409
|
-
title: model.sectionLabel,
|
|
410
|
-
columns: model.columns,
|
|
411
|
-
})
|
|
412
|
-
appendModelControls(controls, rootControls, defaultViewId, defaultSectionId)
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
for (const [sectionId, section] of Object.entries(rootSections ?? {})) {
|
|
416
|
-
registerSectionOptions(sections, sectionId, controlModelSectionOptions(section))
|
|
417
|
-
appendModelControls(controls, section.controls, defaultViewId, sectionId, section.sidebar)
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
for (const [viewId, view] of Object.entries(modelViews ?? {})) {
|
|
421
|
-
const {
|
|
422
|
-
controls: viewControls,
|
|
423
|
-
sections: viewSections,
|
|
424
|
-
section,
|
|
425
|
-
sectionLabel,
|
|
426
|
-
sectionDescription,
|
|
427
|
-
...viewConfig
|
|
428
|
-
} = view
|
|
429
|
-
|
|
430
|
-
views[viewId] = omitUndefined(viewConfig)
|
|
431
|
-
|
|
432
|
-
if (viewControls) {
|
|
433
|
-
const sectionId = section ?? `${viewId}-controls`
|
|
434
|
-
const label = sectionLabel ?? view.label
|
|
435
|
-
registerSectionOptions(sections, sectionId, {
|
|
436
|
-
id: sectionId,
|
|
437
|
-
label,
|
|
438
|
-
title: label,
|
|
439
|
-
description: sectionDescription,
|
|
440
|
-
columns: model.columns,
|
|
441
|
-
})
|
|
442
|
-
appendModelControls(controls, viewControls, viewId, sectionId)
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
for (const [sectionKey, sectionConfig] of Object.entries(viewSections ?? {})) {
|
|
446
|
-
const sectionId = sectionConfig.id ?? `${viewId}-${sectionKey}`
|
|
447
|
-
registerSectionOptions(sections, sectionId, controlModelSectionOptions(sectionConfig))
|
|
448
|
-
appendModelControls(controls, sectionConfig.controls, viewId, sectionId, sectionConfig.sidebar)
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
const controlOptions: ControlWorkspaceOptions = {
|
|
453
|
-
...baseOptions,
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (Object.keys(views).length > 0) {
|
|
457
|
-
controlOptions.views = views
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (Object.keys(sections).length > 0) {
|
|
461
|
-
controlOptions.sections = sections
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
return {
|
|
465
|
-
controls,
|
|
466
|
-
controlOptions,
|
|
467
|
-
...(resolvedComponentBindings === undefined ? {} : { componentBindings: resolvedComponentBindings }),
|
|
468
|
-
...(componentProps === undefined ? {} : { componentProps }),
|
|
469
|
-
...(componentPropsById === undefined ? {} : { componentPropsById }),
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
79
|
/** Build default values for a control schema, matching FormBuilder field defaults. */
|
|
474
80
|
export function getControlDefaults<TControls extends ControlSchema>(
|
|
475
81
|
controls: TControls,
|
|
@@ -481,380 +87,6 @@ export function getControlDefaults<TControls extends ControlSchema>(
|
|
|
481
87
|
return values as ControlValues<TControls>
|
|
482
88
|
}
|
|
483
89
|
|
|
484
|
-
/** Map control workspace values into component props for direct `v-bind` usage. */
|
|
485
|
-
export function controlValuesToComponentProps<TValues extends Record<string, unknown>>(
|
|
486
|
-
values: TValues,
|
|
487
|
-
mapping?: ControlComponentPropsMap<TValues>,
|
|
488
|
-
): Record<string, unknown> {
|
|
489
|
-
if (mapping === undefined) return { ...values }
|
|
490
|
-
|
|
491
|
-
if (Array.isArray(mapping)) {
|
|
492
|
-
const props: Record<string, unknown> = {}
|
|
493
|
-
for (const key of mapping) {
|
|
494
|
-
props[key] = values[key]
|
|
495
|
-
}
|
|
496
|
-
return props
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const props: Record<string, unknown> = {}
|
|
500
|
-
for (const [prop, source] of Object.entries(mapping) as Array<[string, ControlComponentPropSource<TValues>]>) {
|
|
501
|
-
props[prop] = typeof source === 'function' ? source(values) : values[source]
|
|
502
|
-
}
|
|
503
|
-
return props
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/** Map control workspace values into named SDK component bindings for direct slot rendering. */
|
|
507
|
-
export function controlValuesToComponentBindings<TValues extends Record<string, unknown>>(
|
|
508
|
-
values: TValues,
|
|
509
|
-
bindings?: ControlComponentBindingsConfig<TValues>,
|
|
510
|
-
): ControlComponentBinding[] {
|
|
511
|
-
if (bindings === undefined) return []
|
|
512
|
-
|
|
513
|
-
return normalizeControlComponentBindingConfigs(bindings).map(binding => ({
|
|
514
|
-
id: binding.id,
|
|
515
|
-
component: binding.component,
|
|
516
|
-
props: controlValuesToComponentProps(values, binding.props),
|
|
517
|
-
}))
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
/** Map control workspace values into SDK component bindings keyed by binding id. */
|
|
521
|
-
export function controlValuesToComponentBindingsById<TValues extends Record<string, unknown>>(
|
|
522
|
-
values: TValues,
|
|
523
|
-
bindings?: ControlComponentBindingsConfig<TValues>,
|
|
524
|
-
): ControlComponentBindingsById {
|
|
525
|
-
return Object.fromEntries(
|
|
526
|
-
controlValuesToComponentBindings(values, bindings).map(binding => [binding.id, binding]),
|
|
527
|
-
)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/** Return a default WellPlate prop mapping for generated control workspaces. */
|
|
531
|
-
export function defineWellPlateControlProps<TValues extends Record<string, unknown> = Record<string, unknown>>(
|
|
532
|
-
options: WellPlateControlPropsOptions<TValues> = {},
|
|
533
|
-
): ControlComponentPropsMap<TValues> {
|
|
534
|
-
const selectedWells = options.selectedWells ?? sourceKey<TValues>('selectedWells')
|
|
535
|
-
const onUpdateModelValue = options.onUpdateModelValue === false
|
|
536
|
-
? undefined
|
|
537
|
-
: options.onUpdateModelValue ?? updateControlValueSource(selectedWells)
|
|
538
|
-
|
|
539
|
-
return compactComponentPropsMap<TValues>({
|
|
540
|
-
modelValue: selectedWells,
|
|
541
|
-
'onUpdate:modelValue': onUpdateModelValue,
|
|
542
|
-
format: options.format ?? sourceKey<TValues>('plateFormat'),
|
|
543
|
-
wells: options.wells ?? sourceKey<TValues>('wells'),
|
|
544
|
-
disabled: options.disabled ?? sourceKey<TValues>('disabled'),
|
|
545
|
-
readonly: options.readonly ?? sourceKey<TValues>('readonly'),
|
|
546
|
-
showLegend: options.showLegend,
|
|
547
|
-
showSampleTypeIndicator: options.showSampleTypeIndicator,
|
|
548
|
-
})
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/** Return a default DoseCalculator prop mapping for generated control workspaces. */
|
|
552
|
-
export function defineDoseCalculatorControlProps<TValues extends Record<string, unknown> = Record<string, unknown>>(
|
|
553
|
-
options: DoseCalculatorControlPropsOptions<TValues> = {},
|
|
554
|
-
): ControlComponentPropsMap<TValues> {
|
|
555
|
-
const targetWells = options.targetWells ?? sourceKey<TValues>('selectedWells')
|
|
556
|
-
const wells = options.wells ?? sourceKey<TValues>('wells')
|
|
557
|
-
const onApplyToWells = options.onApplyToWells === false
|
|
558
|
-
? undefined
|
|
559
|
-
: options.onApplyToWells ?? defaultDoseApplyHandler(wells, targetWells)
|
|
560
|
-
|
|
561
|
-
return compactComponentPropsMap<TValues>({
|
|
562
|
-
mode: options.mode ?? sourceKey<TValues>('doseMode'),
|
|
563
|
-
targetWells,
|
|
564
|
-
disabled: options.disabled ?? sourceKey<TValues>('disabled'),
|
|
565
|
-
molecularWeight: options.molecularWeight,
|
|
566
|
-
onApplyToWells,
|
|
567
|
-
})
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/** Return named WellPlate + DoseCalculator prop mappings for one dose-design control model. */
|
|
571
|
-
export function defineWellPlateDoseControlProps<TValues extends Record<string, unknown> = Record<string, unknown>>(
|
|
572
|
-
options: WellPlateDoseControlPropsOptions<TValues> = {},
|
|
573
|
-
): ControlComponentPropsByIdMap<TValues> {
|
|
574
|
-
return {
|
|
575
|
-
[options.plateId ?? 'plate']: defineWellPlateControlProps(options.plate),
|
|
576
|
-
[options.doseId ?? 'dose']: defineDoseCalculatorControlProps(options.dose),
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
/** Return named WellPlate + DoseCalculator component bindings for one dose-design control model. */
|
|
581
|
-
export function defineWellPlateDoseComponentBindings<TValues extends Record<string, unknown> = Record<string, unknown>>(
|
|
582
|
-
options: WellPlateDoseControlPropsOptions<TValues> = {},
|
|
583
|
-
): ControlComponentBindingsConfig<TValues> {
|
|
584
|
-
return [
|
|
585
|
-
{
|
|
586
|
-
id: options.plateId ?? 'plate',
|
|
587
|
-
component: 'WellPlate',
|
|
588
|
-
props: defineWellPlateControlProps(options.plate),
|
|
589
|
-
},
|
|
590
|
-
{
|
|
591
|
-
id: options.doseId ?? 'dose',
|
|
592
|
-
component: 'DoseCalculator',
|
|
593
|
-
props: defineDoseCalculatorControlProps(options.dose),
|
|
594
|
-
},
|
|
595
|
-
]
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/** Return a complete ControlWorkspaceView model for WellPlate + DoseCalculator dose design. */
|
|
599
|
-
export function defineDoseDesignControlModel(
|
|
600
|
-
options: DoseDesignControlModelOptions = {},
|
|
601
|
-
): ControlModelBinding {
|
|
602
|
-
const viewId = options.viewId ?? 'design'
|
|
603
|
-
const sectionId = options.sectionId ?? 'dose'
|
|
604
|
-
const doseControls: ControlSchema = {
|
|
605
|
-
selectedWells: {
|
|
606
|
-
type: 'tags',
|
|
607
|
-
label: 'Selected wells',
|
|
608
|
-
default: [...(options.selectedWells ?? ['A1', 'A2'])],
|
|
609
|
-
},
|
|
610
|
-
plateFormat: {
|
|
611
|
-
label: 'Plate format',
|
|
612
|
-
default: options.plateFormat ?? 96,
|
|
613
|
-
options: options.plateFormats ?? [96, 384],
|
|
614
|
-
},
|
|
615
|
-
doseMode: {
|
|
616
|
-
label: 'Dose mode',
|
|
617
|
-
default: options.doseMode ?? 'serial',
|
|
618
|
-
options: options.doseModes ?? ['serial', 'dilution', 'conversion'],
|
|
619
|
-
},
|
|
620
|
-
disabled: {
|
|
621
|
-
label: 'Disable tools',
|
|
622
|
-
default: options.disabled ?? false,
|
|
623
|
-
},
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
if (options.includeMolecularWeight) {
|
|
627
|
-
doseControls.molecularWeight = {
|
|
628
|
-
type: 'number',
|
|
629
|
-
label: 'Molecular weight',
|
|
630
|
-
default: options.molecularWeight ?? 300,
|
|
631
|
-
min: 0,
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const componentProps: WellPlateDoseControlPropsOptions = {
|
|
636
|
-
...options.componentProps,
|
|
637
|
-
dose: {
|
|
638
|
-
...(options.componentProps?.dose ?? {}),
|
|
639
|
-
...(options.includeMolecularWeight && options.componentProps?.dose?.molecularWeight === undefined
|
|
640
|
-
? { molecularWeight: 'molecularWeight' }
|
|
641
|
-
: {}),
|
|
642
|
-
},
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
return defineControlModel({
|
|
646
|
-
componentBindings: defineWellPlateDoseComponentBindings(componentProps),
|
|
647
|
-
componentPropsById: defineWellPlateDoseControlProps(componentProps),
|
|
648
|
-
views: {
|
|
649
|
-
[viewId]: {
|
|
650
|
-
label: options.viewLabel ?? 'Design',
|
|
651
|
-
sections: {
|
|
652
|
-
[sectionId]: {
|
|
653
|
-
label: options.sectionLabel ?? 'Dose design',
|
|
654
|
-
description: options.sectionDescription ?? 'Well selection and dose calculator controls',
|
|
655
|
-
controls: doseControls,
|
|
656
|
-
},
|
|
657
|
-
},
|
|
658
|
-
},
|
|
659
|
-
},
|
|
660
|
-
})
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
function isControlModelBindingInput<TControls extends ControlSchema>(
|
|
664
|
-
value: TControls | (ControlModelBinding & { controls: TControls }),
|
|
665
|
-
): value is ControlModelBinding & { controls: TControls } {
|
|
666
|
-
return (
|
|
667
|
-
typeof value === 'object'
|
|
668
|
-
&& value !== null
|
|
669
|
-
&& 'controls' in value
|
|
670
|
-
&& 'controlOptions' in value
|
|
671
|
-
)
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
export function mergeControlWorkspaceOptions(
|
|
675
|
-
base?: ControlWorkspaceOptions,
|
|
676
|
-
override?: ControlWorkspaceOptions,
|
|
677
|
-
): ControlWorkspaceOptions {
|
|
678
|
-
return {
|
|
679
|
-
...(base ?? {}),
|
|
680
|
-
...(override ?? {}),
|
|
681
|
-
initialValues: {
|
|
682
|
-
...(base?.initialValues ?? {}),
|
|
683
|
-
...(override?.initialValues ?? {}),
|
|
684
|
-
},
|
|
685
|
-
topBarSettings: {
|
|
686
|
-
...(base?.topBarSettings ?? {}),
|
|
687
|
-
...(override?.topBarSettings ?? {}),
|
|
688
|
-
},
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
/** Convert a compact control schema into a FormBuilder schema. */
|
|
693
|
-
export function controlsToFormSchema(
|
|
694
|
-
controls: ControlSchema,
|
|
695
|
-
options: ControlSchemaOptions = {},
|
|
696
|
-
): ControlFormSchema {
|
|
697
|
-
const normalized = normalizeControls(controls, options)
|
|
698
|
-
const sectionIds = orderedUnique(normalized.map(control => control.sectionId))
|
|
699
|
-
const sections = sectionIds.map((sectionId): FormSectionSchema => {
|
|
700
|
-
const sectionControls = normalized.filter(control => control.sectionId === sectionId)
|
|
701
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
702
|
-
return {
|
|
703
|
-
id: sectionId,
|
|
704
|
-
title: config.title ?? config.label ?? humanize(sectionId),
|
|
705
|
-
description: config.description,
|
|
706
|
-
columns: config.columns ?? options.columns ?? 1,
|
|
707
|
-
defaultOpen: config.defaultOpen,
|
|
708
|
-
condition: config.condition,
|
|
709
|
-
fields: sectionControls.map(controlToFormField),
|
|
710
|
-
}
|
|
711
|
-
})
|
|
712
|
-
|
|
713
|
-
return {
|
|
714
|
-
sections,
|
|
715
|
-
submitLabel: options.submitLabel,
|
|
716
|
-
cancelLabel: options.cancelLabel,
|
|
717
|
-
showCancel: options.showCancel,
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
/** Convert controls into AppSidebar panels grouped by view and section. */
|
|
722
|
-
export function controlsToSidebarPanels(
|
|
723
|
-
controls: ControlSchema,
|
|
724
|
-
options: ControlSchemaOptions = {},
|
|
725
|
-
): Record<string, SidebarToolSection[]> {
|
|
726
|
-
const normalized = normalizeControls(controls, options)
|
|
727
|
-
.filter(control => isSidebarEnabled(control.definition.sidebar))
|
|
728
|
-
const viewIds = orderedUnique(normalized.map(control => control.viewId))
|
|
729
|
-
const panels: Record<string, SidebarToolSection[]> = {}
|
|
730
|
-
|
|
731
|
-
for (const viewId of viewIds) {
|
|
732
|
-
const viewControls = normalized.filter(control => control.viewId === viewId)
|
|
733
|
-
const sectionIds = orderedUnique(viewControls.map(control => control.sectionId))
|
|
734
|
-
panels[viewId] = sectionIds.map((sectionId): SidebarToolSection => {
|
|
735
|
-
const sectionControls = viewControls.filter(control => control.sectionId === sectionId)
|
|
736
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
737
|
-
const sidebarConfig = firstSidebarConfig(sectionControls)
|
|
738
|
-
return {
|
|
739
|
-
id: sectionId,
|
|
740
|
-
label: sidebarConfig?.label ?? config.label ?? config.title ?? humanize(sectionId),
|
|
741
|
-
subtitle: sidebarConfig?.subtitle ?? config.subtitle,
|
|
742
|
-
icon: sidebarConfig?.icon ?? config.icon,
|
|
743
|
-
iconColor: sidebarConfig?.iconColor ?? config.iconColor,
|
|
744
|
-
iconBg: sidebarConfig?.iconBg ?? config.iconBg,
|
|
745
|
-
defaultOpen: sidebarConfig?.defaultOpen ?? config.defaultOpen,
|
|
746
|
-
showToggle: sidebarConfig?.showToggle ?? config.showToggle,
|
|
747
|
-
}
|
|
748
|
-
})
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
return panels
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
/** Convert controls into a SettingsModal schema grouped by the same sections. */
|
|
755
|
-
export function controlsToSettingsSchema(
|
|
756
|
-
controls: ControlSchema,
|
|
757
|
-
options: ControlSchemaOptions = {},
|
|
758
|
-
): SettingsModalSchema {
|
|
759
|
-
const normalized = normalizeControls(controls, options)
|
|
760
|
-
const sectionIds = orderedUnique(normalized.map(control => control.sectionId))
|
|
761
|
-
|
|
762
|
-
return {
|
|
763
|
-
groups: sectionIds.map((sectionId) => {
|
|
764
|
-
const sectionControls = normalized.filter(control => control.sectionId === sectionId)
|
|
765
|
-
const config = sectionConfig(sectionId, sectionControls, options)
|
|
766
|
-
return {
|
|
767
|
-
id: sectionId,
|
|
768
|
-
label: config.label ?? config.title ?? humanize(sectionId),
|
|
769
|
-
description: config.description ?? config.subtitle,
|
|
770
|
-
icon: typeof config.icon === 'string' ? config.icon : undefined,
|
|
771
|
-
fields: sectionControls.map(controlToFormField),
|
|
772
|
-
columns: config.columns ?? options.columns ?? 1,
|
|
773
|
-
condition: config.condition,
|
|
774
|
-
access: config.access,
|
|
775
|
-
visibleFor: config.visibleFor,
|
|
776
|
-
requiresAdmin: config.requiresAdmin,
|
|
777
|
-
permissions: config.permissions,
|
|
778
|
-
anyPermissions: config.anyPermissions,
|
|
779
|
-
}
|
|
780
|
-
}),
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/** Convert controls into an AppTopBar settingsConfig object that passes compact controls through to SettingsModal. */
|
|
785
|
-
export function controlsToTopBarSettingsConfig(
|
|
786
|
-
controls: ControlSchema,
|
|
787
|
-
options: ControlSchemaOptions = {},
|
|
788
|
-
config: Omit<TopBarSettingsConfig, 'schema' | 'controls' | 'controlOptions'> = {},
|
|
789
|
-
): TopBarSettingsConfig {
|
|
790
|
-
return {
|
|
791
|
-
...config,
|
|
792
|
-
controls,
|
|
793
|
-
controlOptions: options,
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
/** Return generated control view IDs that have at least one sidebar panel. */
|
|
798
|
-
export function controlsToViewIds(
|
|
799
|
-
controls: ControlSchema,
|
|
800
|
-
options: ControlSchemaOptions = {},
|
|
801
|
-
): string[] {
|
|
802
|
-
return controlsToViewItems(controls, options).map(item => item.id)
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
/** Return AppTopBar pillNav-compatible view items for switching generated control sidebars. */
|
|
806
|
-
export function controlsToViewItems(
|
|
807
|
-
controls: ControlSchema,
|
|
808
|
-
options: ControlSchemaOptions = {},
|
|
809
|
-
): PillNavItem[] {
|
|
810
|
-
return Object.entries(controlsToSidebarPanels(controls, options))
|
|
811
|
-
.filter(([, sections]) => sections.length > 0)
|
|
812
|
-
.map(([id]) => controlViewItem(id, options))
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
/** Return the first generated sidebar view ID, or an empty string when controls render no sidebar panels. */
|
|
816
|
-
export function getDefaultControlView(
|
|
817
|
-
controls: ControlSchema,
|
|
818
|
-
options: ControlSchemaOptions = {},
|
|
819
|
-
): string {
|
|
820
|
-
return controlsToViewIds(controls, options)[0] ?? ''
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
/** Return a headerless single-section FormBuilder schema for rendering inside an AppSidebar section slot. */
|
|
824
|
-
export function controlsToSectionFormSchema(
|
|
825
|
-
controls: ControlSchema,
|
|
826
|
-
sectionId: string,
|
|
827
|
-
options: ControlSchemaOptions = {},
|
|
828
|
-
): ControlFormSchema {
|
|
829
|
-
const schema = controlsToFormSchema(controls, options)
|
|
830
|
-
return {
|
|
831
|
-
sections: schema.sections
|
|
832
|
-
.filter(section => section.id === sectionId)
|
|
833
|
-
.map(section => ({ ...section, title: '', description: undefined })),
|
|
834
|
-
submitLabel: schema.submitLabel,
|
|
835
|
-
cancelLabel: schema.cancelLabel,
|
|
836
|
-
showCancel: schema.showCancel,
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
/** Return headerless FormBuilder schemas keyed by section ID for AppSidebar auto-rendering. */
|
|
841
|
-
export function controlsToSectionFormSchemas(
|
|
842
|
-
controls: ControlSchema,
|
|
843
|
-
options: ControlSchemaOptions = {},
|
|
844
|
-
): Record<string, ControlFormSchema> {
|
|
845
|
-
const schema = controlsToFormSchema(controls, options)
|
|
846
|
-
const schemas: Record<string, ControlFormSchema> = {}
|
|
847
|
-
for (const section of schema.sections) {
|
|
848
|
-
schemas[section.id] = {
|
|
849
|
-
sections: [{ ...section, title: '', description: undefined }],
|
|
850
|
-
submitLabel: schema.submitLabel,
|
|
851
|
-
cancelLabel: schema.cancelLabel,
|
|
852
|
-
showCancel: schema.showCancel,
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
return schemas
|
|
856
|
-
}
|
|
857
|
-
|
|
858
90
|
/** Prepare FormBuilder, SettingsModal, AppTopBar settings, AppSidebar, and initial values from one compact control model. */
|
|
859
91
|
export function useControlSchema<TControls extends ControlSchema>(
|
|
860
92
|
controls: TControls,
|
|
@@ -901,483 +133,3 @@ export function useControlSchema<TControls extends ControlSchema>(
|
|
|
901
133
|
sectionSchema: (sectionId: string) => controlsToSectionFormSchema(controls, sectionId, options),
|
|
902
134
|
}
|
|
903
135
|
}
|
|
904
|
-
|
|
905
|
-
/** Prepare shared reactive values plus AppTopBar/AppSidebar/FormBuilder bindings from one simple controls data model. */
|
|
906
|
-
export function useControlWorkspace<TControls extends ControlSchema>(
|
|
907
|
-
controlsOrModel: TControls | (ControlModelBinding & { controls: TControls }),
|
|
908
|
-
options: ControlWorkspaceOptions = {},
|
|
909
|
-
): UseControlWorkspaceReturn<TControls> {
|
|
910
|
-
const model = isControlModelBindingInput<TControls>(controlsOrModel) ? controlsOrModel : undefined
|
|
911
|
-
const controls: TControls = model ? model.controls : controlsOrModel as TControls
|
|
912
|
-
const workspaceOptions = model
|
|
913
|
-
? mergeControlWorkspaceOptions(model.controlOptions, options)
|
|
914
|
-
: options
|
|
915
|
-
const { initialValues, topBarSettings, ...schemaOptions } = workspaceOptions
|
|
916
|
-
const schema = useControlSchema(controls, schemaOptions)
|
|
917
|
-
const activeView = ref(schema.defaultView)
|
|
918
|
-
const values = reactive({
|
|
919
|
-
...schema.initialValues,
|
|
920
|
-
...(initialValues ?? {}),
|
|
921
|
-
}) as ControlValues<TControls> & Record<string, unknown>
|
|
922
|
-
|
|
923
|
-
function setActiveView(viewId: string) {
|
|
924
|
-
syncActiveView(viewId)
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
function syncActiveView(viewId: string) {
|
|
928
|
-
if (!schema.viewIds.includes(viewId)) return
|
|
929
|
-
if (activeView.value !== viewId) activeView.value = viewId
|
|
930
|
-
if (sidebar.activeView !== viewId) sidebar.activeView = viewId
|
|
931
|
-
if (pillNav.currentItemId !== viewId) pillNav.currentItemId = viewId
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
function setValues(nextValues: Record<string, unknown>) {
|
|
935
|
-
Object.assign(values, nextValues)
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
function resetValues(nextValues: Record<string, unknown> = {}) {
|
|
939
|
-
replaceRecord(values, {
|
|
940
|
-
...schema.initialValues,
|
|
941
|
-
...nextValues,
|
|
942
|
-
})
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
function getComponentProps(
|
|
946
|
-
mapping?: ControlComponentPropsMap<ControlValues<TControls> & Record<string, unknown>>,
|
|
947
|
-
): Record<string, unknown> {
|
|
948
|
-
return controlValuesToComponentProps(values, mapping)
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
function getComponentPropsById(
|
|
952
|
-
mappings?: ControlComponentPropsByIdMap<ControlValues<TControls> & Record<string, unknown>>,
|
|
953
|
-
): Record<string, Record<string, unknown>> {
|
|
954
|
-
if (mappings === undefined) return {}
|
|
955
|
-
|
|
956
|
-
return Object.fromEntries(
|
|
957
|
-
Object.entries(mappings).map(([id, mapping]) => [
|
|
958
|
-
id,
|
|
959
|
-
controlValuesToComponentProps(values, mapping),
|
|
960
|
-
]),
|
|
961
|
-
)
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
function getComponentBindings(
|
|
965
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,
|
|
966
|
-
): ControlComponentBinding[] {
|
|
967
|
-
return controlValuesToComponentBindings(values, bindings)
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
function getComponentBindingsById(
|
|
971
|
-
bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,
|
|
972
|
-
): ControlComponentBindingsById {
|
|
973
|
-
return controlValuesToComponentBindingsById(values, bindings)
|
|
974
|
-
}
|
|
975
|
-
const componentProps = computed(() => (
|
|
976
|
-
model?.componentProps === undefined ? {} : getComponentProps(model.componentProps)
|
|
977
|
-
))
|
|
978
|
-
const componentPropsById = computed(() => getComponentPropsById(model?.componentPropsById))
|
|
979
|
-
const componentBindings = computed(() => getComponentBindings(model?.componentBindings))
|
|
980
|
-
const componentBindingsById = computed(() => getComponentBindingsById(model?.componentBindings))
|
|
981
|
-
const form = {
|
|
982
|
-
...schema.form,
|
|
983
|
-
modelValue: values,
|
|
984
|
-
'onUpdate:modelValue': setValues,
|
|
985
|
-
} as ControlWorkspaceFormBinding
|
|
986
|
-
|
|
987
|
-
const topBarSettingsConfig: TopBarSettingsConfig = {
|
|
988
|
-
...schema.topBarSettingsConfig,
|
|
989
|
-
...(topBarSettings ?? {}),
|
|
990
|
-
values,
|
|
991
|
-
}
|
|
992
|
-
const sidebar = reactive({
|
|
993
|
-
...schema.sidebar,
|
|
994
|
-
activeView: activeView.value,
|
|
995
|
-
modelValue: values,
|
|
996
|
-
'onUpdate:modelValue': setValues,
|
|
997
|
-
values,
|
|
998
|
-
'onUpdate:values': setValues,
|
|
999
|
-
}) as ControlWorkspaceSidebarBinding
|
|
1000
|
-
const pillNav = reactive({
|
|
1001
|
-
items: schema.viewItems,
|
|
1002
|
-
currentItemId: activeView.value,
|
|
1003
|
-
onSelect: (item: PillNavItem) => setActiveView(item.id),
|
|
1004
|
-
}) as ControlWorkspacePillNavBinding
|
|
1005
|
-
const topBarSettingsBinding = {
|
|
1006
|
-
showSettings: true,
|
|
1007
|
-
settingsConfig: topBarSettingsConfig,
|
|
1008
|
-
onSettingsValuesChange: setValues,
|
|
1009
|
-
} as ControlWorkspaceTopBarSettingsBinding
|
|
1010
|
-
const topBarProps = computed<ControlWorkspaceTopBarBinding>(() => ({
|
|
1011
|
-
pillNav: pillNav.items,
|
|
1012
|
-
currentPillId: pillNav.currentItemId,
|
|
1013
|
-
onPillSelect: pillNav.onSelect,
|
|
1014
|
-
...topBarSettingsBinding,
|
|
1015
|
-
}))
|
|
1016
|
-
const bindings: ControlWorkspaceComponentBindings = {
|
|
1017
|
-
form,
|
|
1018
|
-
sidebar,
|
|
1019
|
-
topBar: topBarProps,
|
|
1020
|
-
topBarSettings: topBarSettingsBinding,
|
|
1021
|
-
pillNav,
|
|
1022
|
-
componentBindings,
|
|
1023
|
-
componentBindingsById,
|
|
1024
|
-
componentProps,
|
|
1025
|
-
componentPropsById,
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
watch(activeView, syncActiveView, { flush: 'sync' })
|
|
1029
|
-
watch(() => sidebar.activeView, syncActiveView, { flush: 'sync' })
|
|
1030
|
-
watch(() => pillNav.currentItemId, syncActiveView, { flush: 'sync' })
|
|
1031
|
-
|
|
1032
|
-
return {
|
|
1033
|
-
...schema,
|
|
1034
|
-
schema,
|
|
1035
|
-
values,
|
|
1036
|
-
activeView,
|
|
1037
|
-
topBarSettingsConfig,
|
|
1038
|
-
form,
|
|
1039
|
-
sidebar,
|
|
1040
|
-
topBar: topBarProps,
|
|
1041
|
-
pillNav,
|
|
1042
|
-
topBarSettings: topBarSettingsBinding,
|
|
1043
|
-
bindings,
|
|
1044
|
-
componentBindings,
|
|
1045
|
-
componentBindingsById,
|
|
1046
|
-
componentProps,
|
|
1047
|
-
componentPropsById,
|
|
1048
|
-
setActiveView,
|
|
1049
|
-
setValues,
|
|
1050
|
-
resetValues,
|
|
1051
|
-
getComponentProps,
|
|
1052
|
-
getComponentPropsById,
|
|
1053
|
-
getComponentBindings,
|
|
1054
|
-
getComponentBindingsById,
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
function normalizeControls(
|
|
1059
|
-
controls: ControlSchema,
|
|
1060
|
-
options: ControlSchemaOptions = {},
|
|
1061
|
-
): NormalizedControl[] {
|
|
1062
|
-
return Object.entries(controls)
|
|
1063
|
-
.map(([name, input], index): NormalizedControl => {
|
|
1064
|
-
const definition = normalizeControlDefinition(input)
|
|
1065
|
-
const type = definition.type ?? inferControlType(definition)
|
|
1066
|
-
return {
|
|
1067
|
-
name,
|
|
1068
|
-
definition,
|
|
1069
|
-
type,
|
|
1070
|
-
sectionId: definition.section ?? options.section ?? 'controls',
|
|
1071
|
-
viewId: definition.view ?? options.view ?? 'default',
|
|
1072
|
-
order: definition.order ?? index,
|
|
1073
|
-
}
|
|
1074
|
-
})
|
|
1075
|
-
.sort((a, b) => a.order - b.order)
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
function normalizeControlDefinition(input: ControlInput): ControlDefinition {
|
|
1079
|
-
if (isControlOptionArray(input)) {
|
|
1080
|
-
if (input.length === 0) return { type: 'tags', default: [] }
|
|
1081
|
-
return {
|
|
1082
|
-
default: optionValue(input[0]),
|
|
1083
|
-
options: input,
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
if (typeof input === 'string' || typeof input === 'number' || typeof input === 'boolean') {
|
|
1088
|
-
return { default: input }
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
return input
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
function appendModelControls(
|
|
1095
|
-
target: ControlSchema,
|
|
1096
|
-
source: ControlSchema,
|
|
1097
|
-
viewId: string,
|
|
1098
|
-
sectionId: string,
|
|
1099
|
-
sidebar?: boolean | ControlSidebarConfig,
|
|
1100
|
-
): void {
|
|
1101
|
-
for (const [name, input] of Object.entries(source)) {
|
|
1102
|
-
if (Object.prototype.hasOwnProperty.call(target, name)) {
|
|
1103
|
-
throw new Error(
|
|
1104
|
-
`Duplicate control "${name}" in defineControlModel(). Control names must be unique across views and sections.`,
|
|
1105
|
-
)
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
const definition = normalizeControlDefinition(input)
|
|
1109
|
-
target[name] = omitUndefined({
|
|
1110
|
-
...definition,
|
|
1111
|
-
view: definition.view ?? viewId,
|
|
1112
|
-
section: definition.section ?? sectionId,
|
|
1113
|
-
sidebar: definition.sidebar ?? sidebar,
|
|
1114
|
-
})
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
function controlModelSectionOptions(section: ControlModelSectionConfig): ControlSectionConfig {
|
|
1119
|
-
const { controls: _controls, sidebar: _sidebar, ...options } = section
|
|
1120
|
-
return omitUndefined(options)
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
function registerSectionOptions(
|
|
1124
|
-
target: Record<string, ControlSectionConfig>,
|
|
1125
|
-
sectionId: string,
|
|
1126
|
-
options: ControlSectionConfig,
|
|
1127
|
-
): void {
|
|
1128
|
-
target[sectionId] = omitUndefined({
|
|
1129
|
-
...(target[sectionId] ?? {}),
|
|
1130
|
-
...options,
|
|
1131
|
-
id: sectionId,
|
|
1132
|
-
})
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
function isControlOptionArray(input: ControlInput): input is readonly ControlOption[] {
|
|
1136
|
-
return Array.isArray(input)
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
function inferControlType(definition: ControlDefinition): FormFieldType {
|
|
1140
|
-
const value = definition.default ?? definition.defaultValue
|
|
1141
|
-
if (definition.options?.length) return Array.isArray(value) ? 'multiselect' : 'select'
|
|
1142
|
-
if (typeof value === 'boolean') return 'toggle'
|
|
1143
|
-
if (typeof value === 'number') return 'number'
|
|
1144
|
-
if (Array.isArray(value)) return 'tags'
|
|
1145
|
-
return 'text'
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
function defaultValueForControl(definition: ControlDefinition, type: FormFieldType): unknown {
|
|
1149
|
-
if (definition.default !== undefined) return definition.default
|
|
1150
|
-
if (definition.defaultValue !== undefined) return definition.defaultValue
|
|
1151
|
-
return getTypeDefault(type)
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
function controlToFormField(control: NormalizedControl): FormFieldSchema {
|
|
1155
|
-
const { name, definition, type } = control
|
|
1156
|
-
const props = fieldProps(definition)
|
|
1157
|
-
return {
|
|
1158
|
-
name,
|
|
1159
|
-
label: definition.label ?? humanize(name),
|
|
1160
|
-
type,
|
|
1161
|
-
defaultValue: defaultValueForControl(definition, type),
|
|
1162
|
-
placeholder: definition.placeholder,
|
|
1163
|
-
hint: definition.hint,
|
|
1164
|
-
size: definition.size,
|
|
1165
|
-
disabled: definition.disabled,
|
|
1166
|
-
readonly: definition.readonly,
|
|
1167
|
-
validation: validationForControl(definition),
|
|
1168
|
-
condition: definition.condition,
|
|
1169
|
-
access: definition.access,
|
|
1170
|
-
visibleFor: definition.visibleFor,
|
|
1171
|
-
requiresAdmin: definition.requiresAdmin,
|
|
1172
|
-
permissions: definition.permissions,
|
|
1173
|
-
anyPermissions: definition.anyPermissions,
|
|
1174
|
-
colSpan: definition.colSpan,
|
|
1175
|
-
props,
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
function fieldProps(definition: ControlDefinition): Record<string, unknown> {
|
|
1180
|
-
const props: Record<string, unknown> = {}
|
|
1181
|
-
if (definition.min !== undefined) props.min = numericValue(definition.min)
|
|
1182
|
-
if (definition.max !== undefined) props.max = numericValue(definition.max)
|
|
1183
|
-
if (definition.options) props.options = definition.options.map(normalizeOption)
|
|
1184
|
-
return { ...props, ...(definition.props ?? {}) }
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
function validationForControl(definition: ControlDefinition): FieldValidation | undefined {
|
|
1188
|
-
const validation: FieldValidation = { ...(definition.validation ?? {}) }
|
|
1189
|
-
if (definition.required !== undefined) validation.required = definition.required
|
|
1190
|
-
if (definition.min !== undefined) validation.min = definition.min
|
|
1191
|
-
if (definition.max !== undefined) validation.max = definition.max
|
|
1192
|
-
if (definition.minLength !== undefined) validation.minLength = definition.minLength
|
|
1193
|
-
if (definition.maxLength !== undefined) validation.maxLength = definition.maxLength
|
|
1194
|
-
if (definition.email !== undefined) validation.email = definition.email
|
|
1195
|
-
if (definition.pattern !== undefined) validation.pattern = definition.pattern
|
|
1196
|
-
return Object.keys(validation).length > 0 ? validation : undefined
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
function sectionConfig(
|
|
1200
|
-
sectionId: string,
|
|
1201
|
-
controls: NormalizedControl[],
|
|
1202
|
-
options: ControlSchemaOptions,
|
|
1203
|
-
): ControlSectionConfig {
|
|
1204
|
-
const configured = options.sections?.[sectionId]
|
|
1205
|
-
const first = controls[0]?.definition
|
|
1206
|
-
return {
|
|
1207
|
-
...configured,
|
|
1208
|
-
id: sectionId,
|
|
1209
|
-
label: configured?.label ?? first?.sectionLabel,
|
|
1210
|
-
title: configured?.title ?? first?.sectionLabel,
|
|
1211
|
-
description: configured?.description ?? first?.sectionDescription,
|
|
1212
|
-
subtitle: configured?.subtitle ?? first?.sectionSubtitle,
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
function firstSidebarConfig(controls: NormalizedControl[]): ControlSidebarConfig | undefined {
|
|
1217
|
-
for (const control of controls) {
|
|
1218
|
-
const sidebar = control.definition.sidebar
|
|
1219
|
-
if (sidebar && typeof sidebar === 'object' && sidebar.enabled !== false) return sidebar
|
|
1220
|
-
}
|
|
1221
|
-
return undefined
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
function isSidebarEnabled(sidebar: ControlDefinition['sidebar']): boolean {
|
|
1225
|
-
if (sidebar === false) return false
|
|
1226
|
-
if (sidebar && typeof sidebar === 'object') return sidebar.enabled !== false
|
|
1227
|
-
return true
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
function normalizeOption(option: ControlOption): SelectOption<unknown> {
|
|
1231
|
-
if (typeof option === 'object' && option !== null && 'label' in option) {
|
|
1232
|
-
return option
|
|
1233
|
-
}
|
|
1234
|
-
return {
|
|
1235
|
-
value: option,
|
|
1236
|
-
label: humanize(String(option)),
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
function optionValue(option: ControlOption): ControlOptionValue | unknown {
|
|
1241
|
-
if (typeof option === 'object' && option !== null && 'value' in option) {
|
|
1242
|
-
return option.value
|
|
1243
|
-
}
|
|
1244
|
-
return option
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
function compactComponentPropsMap<TValues extends Record<string, unknown>>(
|
|
1248
|
-
mapping: Record<string, ControlComponentPropSource<TValues> | undefined>,
|
|
1249
|
-
): ControlComponentPropsMap<TValues> {
|
|
1250
|
-
return Object.fromEntries(
|
|
1251
|
-
Object.entries(mapping).filter((entry): entry is [string, ControlComponentPropSource<TValues>] =>
|
|
1252
|
-
entry[1] !== undefined
|
|
1253
|
-
),
|
|
1254
|
-
)
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
function normalizeControlComponentBindingConfigs<TValues extends Record<string, unknown>>(
|
|
1258
|
-
bindings: ControlComponentBindingsConfig<TValues>,
|
|
1259
|
-
): Array<Required<Pick<ControlComponentBindingConfig<TValues>, 'id' | 'component'>> & Pick<ControlComponentBindingConfig<TValues>, 'props'>> {
|
|
1260
|
-
if (Array.isArray(bindings)) {
|
|
1261
|
-
const usedIds = new Map<string, number>()
|
|
1262
|
-
return bindings.map(binding => ({
|
|
1263
|
-
id: uniqueComponentBindingId(binding.id ?? binding.component, usedIds),
|
|
1264
|
-
component: binding.component,
|
|
1265
|
-
props: binding.props,
|
|
1266
|
-
}))
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
return Object.entries(bindings).map(([id, binding]) => ({
|
|
1270
|
-
id,
|
|
1271
|
-
component: binding.component,
|
|
1272
|
-
props: binding.props,
|
|
1273
|
-
}))
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
function uniqueComponentBindingId(id: string, usedIds: Map<string, number>): string {
|
|
1277
|
-
const count = usedIds.get(id) ?? 0
|
|
1278
|
-
usedIds.set(id, count + 1)
|
|
1279
|
-
return count === 0 ? id : `${id}-${count + 1}`
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
function sourceKey<TValues extends Record<string, unknown>>(key: string): keyof TValues & string {
|
|
1283
|
-
return key as keyof TValues & string
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
function updateControlValueSource<TValues extends Record<string, unknown>>(
|
|
1287
|
-
source: ControlComponentPropSource<TValues>,
|
|
1288
|
-
): ((values: TValues) => (value: string[]) => void) | undefined {
|
|
1289
|
-
if (typeof source !== 'string') return undefined
|
|
1290
|
-
return values => (value: string[]) => {
|
|
1291
|
-
const writableValues = values as Record<string, unknown>
|
|
1292
|
-
writableValues[source] = value
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
function defaultDoseApplyHandler<TValues extends Record<string, unknown>>(
|
|
1297
|
-
wells: ControlComponentPropSource<TValues>,
|
|
1298
|
-
targetWells: ControlComponentPropSource<TValues>,
|
|
1299
|
-
): ((values: TValues) => (results: WellConcentration[]) => void) | undefined {
|
|
1300
|
-
if (wells === targetWells) return undefined
|
|
1301
|
-
return updateWellsFromDoseResults(wells)
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
function updateWellsFromDoseResults<TValues extends Record<string, unknown>>(
|
|
1305
|
-
source: ControlComponentPropSource<TValues>,
|
|
1306
|
-
): ((values: TValues) => (results: WellConcentration[]) => void) | undefined {
|
|
1307
|
-
if (typeof source !== 'string') return undefined
|
|
1308
|
-
return values => (results: WellConcentration[]) => {
|
|
1309
|
-
const writableValues = values as Record<string, unknown>
|
|
1310
|
-
const currentWells = recordValue(writableValues[source])
|
|
1311
|
-
const nextWells: Record<string, Record<string, unknown>> = {}
|
|
1312
|
-
for (const [wellId, well] of Object.entries(currentWells)) {
|
|
1313
|
-
nextWells[wellId] = recordValue(well)
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
for (const result of results) {
|
|
1317
|
-
const existing = recordValue(nextWells[result.wellId])
|
|
1318
|
-
const metadata = recordValue(existing.metadata)
|
|
1319
|
-
nextWells[result.wellId] = {
|
|
1320
|
-
...existing,
|
|
1321
|
-
state: 'filled',
|
|
1322
|
-
value: result.concentration.value,
|
|
1323
|
-
metadata: {
|
|
1324
|
-
...metadata,
|
|
1325
|
-
concentration: result.concentration,
|
|
1326
|
-
...(result.volume === undefined ? {} : { volume: result.volume }),
|
|
1327
|
-
},
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
writableValues[source] = nextWells
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
function recordValue(value: unknown): Record<string, unknown> {
|
|
1336
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
1337
|
-
? value as Record<string, unknown>
|
|
1338
|
-
: {}
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
function numericValue(value: number | { value: number; message: string }): number {
|
|
1342
|
-
return typeof value === 'number' ? value : value.value
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
function orderedUnique(values: string[]): string[] {
|
|
1346
|
-
return [...new Set(values)]
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
function controlViewItem(viewId: string, options: ControlSchemaOptions): PillNavItem {
|
|
1350
|
-
const config = options.views?.[viewId]
|
|
1351
|
-
return {
|
|
1352
|
-
id: viewId,
|
|
1353
|
-
label: config?.label ?? humanize(viewId),
|
|
1354
|
-
...(config?.icon !== undefined ? { icon: config.icon } : {}),
|
|
1355
|
-
...(config?.to !== undefined ? { to: config.to } : {}),
|
|
1356
|
-
...(config?.href !== undefined ? { href: config.href } : {}),
|
|
1357
|
-
...(config?.disabled !== undefined ? { disabled: config.disabled } : {}),
|
|
1358
|
-
...(config?.children !== undefined ? { children: config.children } : {}),
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
function replaceRecord(target: Record<string, unknown>, values: Record<string, unknown>) {
|
|
1363
|
-
for (const key of Object.keys(target)) {
|
|
1364
|
-
delete target[key]
|
|
1365
|
-
}
|
|
1366
|
-
Object.assign(target, values)
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
function omitUndefined<T extends object>(record: T): T {
|
|
1370
|
-
const next: Record<string, unknown> = {}
|
|
1371
|
-
for (const [key, value] of Object.entries(record as Record<string, unknown>)) {
|
|
1372
|
-
if (value !== undefined) next[key] = value
|
|
1373
|
-
}
|
|
1374
|
-
return next as T
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
function humanize(value: string): string {
|
|
1378
|
-
return value
|
|
1379
|
-
.replace(/[_-]+/g, ' ')
|
|
1380
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1381
|
-
.trim()
|
|
1382
|
-
.replace(/\w\S*/g, word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
1383
|
-
}
|