@morscherlab/mint-sdk 1.2.0-beta.1 → 1.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -5
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-Dphh3RrI.js} +5 -8
- package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
- package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
- package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
- package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/AutoGroupModal.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -0
- package/dist/components/DropdownButton.vue.d.ts +2 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
- package/dist/components/ExperimentPopover.vue.d.ts +1 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
- package/dist/components/FitPanel.vue.d.ts +1 -1
- package/dist/components/JobsStatusTray.vue.d.ts +9 -2
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
- package/dist/components/ReagentList.vue.d.ts +29 -1
- package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
- package/dist/components/SampleLegend.vue.d.ts +1 -1
- package/dist/components/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +35 -2
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +28 -0
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/TimePicker.vue.d.ts +1 -0
- package/dist/components/WellPlate.geometry.d.ts +15 -0
- package/dist/components/WellPlate.interaction.d.ts +13 -0
- package/dist/components/WellPlate.vue.d.ts +29 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
- package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
- package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
- package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
- package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
- package/dist/{components-DkHddRMl.js → components-CgAUzF8F.js} +2497 -2235
- package/dist/components-CgAUzF8F.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +9 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useAsync.d.ts +5 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
- package/dist/composables/useCommandHistory.d.ts +5 -1
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +9 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
- package/dist/composables/useJobsStatusTray.d.ts +25 -1
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +29 -0
- package/dist/composables/useOptimisticMutation.d.ts +5 -1
- package/dist/composables/usePluginClient.d.ts +2 -0
- package/dist/composables/usePluginConfig.d.ts +27 -0
- package/dist/composables/usePluginWorkspace.d.ts +51 -0
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useResourceCrud.d.ts +5 -1
- package/dist/composables/useRovingFocus.d.ts +24 -0
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/composables/useWellPainting.d.ts +5 -1
- package/dist/composables/useWellPlateAdapter.d.ts +5 -1
- package/dist/composables/useWellPlateValidation.d.ts +5 -1
- package/dist/composables/workspaceRecipes.d.ts +188 -0
- package/dist/{composables-C_i90sGS.js → composables-B_pia3hO.js} +209 -82
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-J6zFkHmn.js → errors-_W0-LbA6.js} +103 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Cq145oEW.js → experiment-Cwl9AYxw.js} +3 -8
- package/dist/experiment-Cwl9AYxw.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
- package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -7
- package/dist/install.js.map +1 -1
- package/dist/permissions.d.ts +42 -1
- package/dist/permissions.js +20 -10
- package/dist/permissions.js.map +1 -1
- package/dist/stores/auth.d.ts +6 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -3
- package/dist/stores/settings.d.ts +31 -1
- package/dist/styles.css +11247 -29501
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-DsP51i-S.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/auth.d.ts +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-aMZlb4Sc.js} +462 -1130
- package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
- package/dist/useDropdownState-DitCtrTT.js.map +1 -0
- package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-CS_SQl6U.js → useProtocolTemplates-BmX_iVBR.js} +766 -212
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/pluginSecrets.d.ts +53 -0
- package/dist/utils/records.d.ts +4 -0
- package/package.json +1 -1
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
- package/src/__tests__/components/BaseTabs.test.ts +67 -0
- package/src/__tests__/components/DataFrame.test.ts +183 -11
- package/src/__tests__/components/DataStates.test.ts +176 -0
- package/src/__tests__/components/DatePicker.test.ts +76 -0
- package/src/__tests__/components/DateTimePicker.test.ts +36 -0
- package/src/__tests__/components/DropdownButton.test.ts +134 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
- package/src/__tests__/components/RackEditor.test.ts +35 -0
- package/src/__tests__/components/ReagentList.test.ts +64 -2
- package/src/__tests__/components/RetiredStyles.test.ts +31 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
- package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
- package/src/__tests__/components/SecretInput.test.ts +87 -0
- package/src/__tests__/components/SegmentedControl.test.ts +88 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/composables/useAuth.test.ts +2 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +140 -0
- package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
- package/src/__tests__/stores/settings.test.ts +71 -1
- package/src/__tests__/styles/cssTokens.test.ts +131 -0
- package/src/__tests__/utils/permissions.test.ts +68 -0
- package/src/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +26 -7
- package/src/components/AppLayout.vue +0 -4
- package/src/components/AppPluginSwitcher.story.vue +87 -0
- package/src/components/AppPluginSwitcher.vue +2 -5
- package/src/components/AppSidebar.vue +0 -4
- package/src/components/AppToastContainer.vue +6 -8
- package/src/components/AppTopBar.vue +0 -4
- package/src/components/ArtifactSaveDialog.vue +0 -4
- package/src/components/ArtifactSelectorModal.vue +0 -4
- package/src/components/AuditTrail.story.vue +18 -0
- package/src/components/AuditTrail.vue +27 -7
- package/src/components/AutoGroupModal.vue +0 -4
- package/src/components/Avatar.vue +0 -4
- package/src/components/BaseButton.vue +0 -4
- package/src/components/BaseCheckbox.vue +0 -4
- package/src/components/BaseInput.vue +0 -4
- package/src/components/BaseModal.vue +8 -60
- package/src/components/BasePill.vue +0 -4
- package/src/components/BaseRadioGroup.vue +0 -4
- package/src/components/BaseSelect.vue +0 -4
- package/src/components/BaseSlider.vue +0 -4
- package/src/components/BaseTabs.vue +26 -5
- package/src/components/BaseTextarea.vue +0 -4
- package/src/components/BaseToggle.vue +0 -4
- package/src/components/BatchProgressList.story.vue +18 -0
- package/src/components/BatchProgressList.vue +32 -4
- package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
- package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
- package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
- package/src/components/Breadcrumb.vue +0 -4
- package/src/components/Calendar.vue +0 -4
- package/src/components/ChartContainer.story.vue +1 -1
- package/src/components/ChartContainer.vue +0 -4
- package/src/components/ChemicalFormula.vue +0 -4
- package/src/components/CollapsibleCard.vue +0 -4
- package/src/components/ColorSlider.vue +0 -4
- package/src/components/ComponentBindingRenderer.vue +1 -3
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/ControlWorkspaceView.vue +11 -22
- package/src/components/DataFrame.story.vue +14 -0
- package/src/components/DataFrame.vue +97 -23
- package/src/components/DatePicker.vue +73 -27
- package/src/components/DateTimePicker.vue +45 -17
- package/src/components/Divider.vue +0 -4
- package/src/components/DoseCalculator.vue +0 -4
- package/src/components/DoseDesignWorkspaceView.vue +6 -25
- package/src/components/DropdownButton.vue +24 -6
- package/src/components/EmptyState.vue +0 -4
- package/src/components/ExperimentCodeBadge.vue +0 -4
- package/src/components/ExperimentDataViewer.story.vue +3 -0
- package/src/components/ExperimentDataViewer.vue +33 -13
- package/src/components/ExperimentPopover.vue +2 -5
- package/src/components/ExperimentSelectorModal.vue +0 -4
- package/src/components/ExperimentTimeline.story.vue +18 -0
- package/src/components/ExperimentTimeline.vue +81 -75
- package/src/components/FileUploader.vue +0 -4
- package/src/components/FitPanel.vue +0 -4
- package/src/components/FormActions.story.vue +96 -0
- package/src/components/FormActions.vue +0 -4
- package/src/components/FormBuilder.vue +0 -4
- package/src/components/FormField.vue +0 -4
- package/src/components/FormulaInput.vue +0 -4
- package/src/components/GeneratedPathInput.story.vue +68 -0
- package/src/components/GeneratedPlotlyResult.story.vue +96 -0
- package/src/components/GeneratedPlotlyResult.vue +3 -3
- package/src/components/GeneratedPluginView.story.vue +145 -0
- package/src/components/GeneratedPluginView.vue +10 -10
- package/src/components/GeneratedResultRenderer.story.vue +117 -0
- package/src/components/GeneratedResultRenderer.vue +4 -4
- package/src/components/GroupAssigner.vue +67 -5
- package/src/components/IconButton.vue +0 -4
- package/src/components/InstrumentAlertLog.vue +0 -4
- package/src/components/InstrumentStateBadge.vue +0 -4
- package/src/components/InstrumentStatusCard.vue +0 -4
- package/src/components/JobsStatusTray.vue +16 -5
- package/src/components/LcmsSequenceTable.vue +81 -50
- package/src/components/LoadingSpinner.vue +0 -4
- package/src/components/MobileSupportGate.vue +0 -4
- package/src/components/MoleculeInput.vue +0 -4
- package/src/components/MultiSelect.vue +0 -4
- package/src/components/NumberInput.vue +0 -4
- package/src/components/PlateMapEditor.vue +3 -14
- package/src/components/PluginIcon.vue +0 -4
- package/src/components/PluginWorkspaceView.props.ts +38 -0
- package/src/components/PluginWorkspaceView.vue +53 -224
- package/src/components/ProgressBar.vue +0 -4
- package/src/components/ProtocolStepEditor.vue +2 -4
- package/src/components/RackEditor.vue +51 -70
- package/src/components/ReagentEditor.vue +0 -4
- package/src/components/ReagentList.story.vue +18 -0
- package/src/components/ReagentList.vue +127 -82
- package/src/components/ResourceCard.vue +0 -4
- package/src/components/RuntimeUpdateNotice.story.vue +49 -0
- package/src/components/RuntimeUpdateNotice.vue +4 -4
- package/src/components/SampleHierarchyTree.story.vue +18 -0
- package/src/components/SampleHierarchyTree.vue +32 -9
- package/src/components/SampleLegend.vue +2 -8
- package/src/components/SampleSelector.drag.ts +51 -0
- package/src/components/SampleSelector.story.vue +6 -0
- package/src/components/SampleSelector.tree.ts +2 -0
- package/src/components/SampleSelector.vue +49 -10
- package/src/components/SampleSelectorGroupNode.vue +19 -0
- package/src/components/ScheduleCalendar.story.vue +6 -0
- package/src/components/ScheduleCalendar.vue +82 -7
- package/src/components/ScientificNumber.vue +0 -4
- package/src/components/SecretInput.story.vue +79 -0
- package/src/components/SecretInput.vue +150 -0
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +48 -5
- package/src/components/SequenceInput.vue +0 -4
- package/src/components/SequenceProgressBar.story.vue +110 -0
- package/src/components/SequenceProgressBar.vue +0 -4
- package/src/components/SettingsModal.vue +0 -4
- package/src/components/Skeleton.vue +0 -4
- package/src/components/SmartGroupFieldRecipe.vue +8 -6
- package/src/components/SmartGroupManual.vue +0 -4
- package/src/components/StatusIndicator.vue +0 -4
- package/src/components/StepWizard.vue +0 -4
- package/src/components/TagsInput.vue +4 -6
- package/src/components/ThemeToggle.vue +0 -4
- package/src/components/TimePicker.vue +36 -7
- package/src/components/TimeRangeInput.vue +0 -4
- package/src/components/Tooltip.story.vue +3 -3
- package/src/components/Tooltip.vue +0 -4
- package/src/components/UnitInput.vue +0 -4
- package/src/components/WellPlate.geometry.ts +60 -1
- package/src/components/WellPlate.interaction.ts +44 -0
- package/src/components/WellPlate.story.vue +8 -0
- package/src/components/WellPlate.vue +53 -7
- package/src/components/index.ts +9 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
- package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
- package/src/components/internal/DataStateInternal.vue +74 -0
- package/src/components/internal/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +20 -5
- package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
- package/src/components/internal/WorkspaceShellInternal.vue +125 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/experimentDesignData.ts +1 -3
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +43 -0
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useAsync.ts +5 -1
- package/src/composables/useAuth.ts +3 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
- package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
- package/src/composables/useBioTemplateWorkspace.ts +18 -43
- package/src/composables/useCommandHistory.ts +5 -1
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +14 -2
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +22 -10
- package/src/composables/useJobsStatusTray.ts +184 -17
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +90 -0
- package/src/composables/useOptimisticMutation.ts +6 -16
- package/src/composables/usePluginClient.ts +47 -4
- package/src/composables/usePluginConfig.ts +252 -0
- package/src/composables/usePluginWorkspace.ts +208 -0
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +6 -16
- package/src/composables/useRovingFocus.ts +66 -0
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +10 -30
- package/src/composables/useWellPlateAdapter.ts +5 -1
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/composables/useWellPlateValidation.ts +5 -1
- package/src/composables/workspaceRecipes.ts +267 -0
- package/src/index.ts +16 -0
- package/src/permissions.ts +48 -9
- package/src/stores/auth.ts +1 -0
- package/src/stores/experiment.ts +2 -7
- package/src/stores/index.ts +9 -1
- package/src/stores/settings.ts +93 -1
- package/src/styles/components/audit-trail.css +5 -5
- package/src/styles/components/batch-progress-list.css +7 -0
- package/src/styles/components/color-slider.css +2 -2
- package/src/styles/components/data-state.css +30 -0
- package/src/styles/components/dataframe.css +29 -35
- package/src/styles/components/experiment-data-viewer.css +4 -4
- package/src/styles/components/experiment-timeline.css +3 -30
- package/src/styles/components/form-builder.css +5 -5
- package/src/styles/components/lcms-sequence-table.css +16 -1
- package/src/styles/components/multi-select.css +1 -1
- package/src/styles/components/reagent-list.css +38 -31
- package/src/styles/components/sample-hierarchy-tree.css +5 -19
- package/src/styles/components/sample-selector.css +9 -2
- package/src/styles/components/schedule-calendar.css +8 -0
- package/src/styles/components/scientific-number.css +1 -1
- package/src/styles/components/secret-input.css +60 -0
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +9 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/builderReadUtils.ts +1 -3
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/componentTargetResolvers.ts +1 -3
- package/src/templates/controlSchemaTargets.ts +1 -3
- package/src/templates/doseResponseAdapters.ts +2 -13
- package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
- package/src/templates/plateMapBuilder.ts +2 -2
- package/src/templates/qpcrPlateBuilder.ts +1 -1
- package/src/templates/templateValidators.ts +1 -1
- package/src/templates/timeCourseBuilder.ts +2 -2
- package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
- package/src/types/auth.ts +1 -0
- package/src/types/form-builder.ts +1 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/src/utils/formModelSync.ts +1 -3
- package/src/utils/pluginIcon.ts +1 -3
- package/src/utils/pluginSecrets.ts +102 -0
- package/src/utils/records.ts +9 -0
- package/dist/EmptyState-p90quq8Z.js.map +0 -1
- package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
- package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
- package/dist/SettingsModal-BgKY93zh.js.map +0 -1
- package/dist/components-DkHddRMl.js.map +0 -1
- package/dist/composables/autoGroupConstants.d.ts +0 -1
- package/dist/composables/autoGroupGrouping.d.ts +0 -3
- package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
- package/dist/composables-C_i90sGS.js.map +0 -1
- package/dist/experiment-Cq145oEW.js.map +0 -1
- package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-DsP51i-S.js.map +0 -1
- package/dist/useApi-J6zFkHmn.js.map +0 -1
- package/dist/useControlSchema-BDx2Olha.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
- package/src/composables/autoGroupConstants.ts +0 -4
- package/src/composables/autoGroupGrouping.ts +0 -148
- package/src/composables/useAutoGroupInputSources.ts +0 -147
- package/src/templates/builderDefaults.ts +0 -11
- package/src/templates/plateGeometry.ts +0 -62
- /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* SecretInput — plugin secret settings field with a set / not set / environment badge. */
|
|
2
|
+
|
|
3
|
+
.mint-secret-input {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.mint-secret-input__status {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
gap: 0.5rem;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.mint-secret-input__badge {
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
border-radius: 999px;
|
|
20
|
+
padding: 0.125rem 0.5rem;
|
|
21
|
+
font-size: 0.75rem;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
line-height: 1.4;
|
|
24
|
+
border: 1px solid transparent;
|
|
25
|
+
background-color: var(--bg-tertiary);
|
|
26
|
+
color: var(--text-secondary);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.mint-secret-input__badge--set {
|
|
30
|
+
background-color: color-mix(in srgb, var(--mint-success) 12%, transparent);
|
|
31
|
+
border-color: color-mix(in srgb, var(--mint-success) 35%, transparent);
|
|
32
|
+
color: var(--mint-success);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.mint-secret-input__badge--environment {
|
|
36
|
+
background-color: color-mix(in srgb, var(--mint-info) 12%, transparent);
|
|
37
|
+
border-color: color-mix(in srgb, var(--mint-info) 35%, transparent);
|
|
38
|
+
color: var(--mint-info);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.mint-secret-input__badge--pending {
|
|
42
|
+
background-color: color-mix(in srgb, var(--mint-warning) 12%, transparent);
|
|
43
|
+
border-color: color-mix(in srgb, var(--mint-warning) 35%, transparent);
|
|
44
|
+
color: var(--mint-warning);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.mint-secret-input__hint {
|
|
48
|
+
font-size: 0.75rem;
|
|
49
|
+
color: var(--text-muted);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.mint-secret-input__actions {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 0.5rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.mint-secret-input--error .mint-secret-input__badge {
|
|
59
|
+
border-color: color-mix(in srgb, var(--mint-error) 45%, transparent);
|
|
60
|
+
}
|
|
@@ -284,3 +284,11 @@
|
|
|
284
284
|
font-size: 0.75rem;
|
|
285
285
|
color: var(--text-muted);
|
|
286
286
|
}
|
|
287
|
+
|
|
288
|
+
/* Empty / loading / error placeholder host (content comes from EmptyState) */
|
|
289
|
+
.mint-well-plate__state {
|
|
290
|
+
display: flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: center;
|
|
293
|
+
min-height: 12rem;
|
|
294
|
+
}
|
package/src/styles/index.css
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
@import './components/radio-group.css';
|
|
31
31
|
@import './components/sample-legend.css';
|
|
32
32
|
@import './components/section-card.css';
|
|
33
|
+
@import './components/secret-input.css';
|
|
33
34
|
@import './components/select.css';
|
|
34
35
|
@import './components/skeleton.css';
|
|
35
36
|
@import './components/slider.css';
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
@import './components/dropdown-button.css';
|
|
57
58
|
@import './components/calendar.css';
|
|
58
59
|
@import './components/dataframe.css';
|
|
60
|
+
@import './components/data-state.css';
|
|
59
61
|
@import './components/well-edit-popup.css';
|
|
60
62
|
@import './components/rack-editor.css';
|
|
61
63
|
@import './components/loading-spinner.css';
|
|
@@ -91,3 +93,10 @@
|
|
|
91
93
|
@import './components/artifact-save-dialog.css';
|
|
92
94
|
@import './components/experiment-popover.css';
|
|
93
95
|
@import './components/fit-panel.css';
|
|
96
|
+
@import './components/app-avatar-menu.css';
|
|
97
|
+
@import './components/app-page-selector.css';
|
|
98
|
+
@import './components/app-pill-nav.css';
|
|
99
|
+
@import './components/app-plugin-switcher.css';
|
|
100
|
+
@import './components/mobile-support-gate.css';
|
|
101
|
+
@import './components/plugin-icon.css';
|
|
102
|
+
@import './components/reagent-editor.css';
|
package/src/styles/variables.css
CHANGED
|
@@ -66,6 +66,32 @@
|
|
|
66
66
|
/* The MINT 1.1 card system uses exactly one shadow for every card. */
|
|
67
67
|
--card-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.04), 0 1px 3px 0 rgb(0 0 0 / 0.06);
|
|
68
68
|
|
|
69
|
+
/* Categorical sample scale — mirrored by SAMPLE_COLOR_SCALE in
|
|
70
|
+
src/utils/color.ts. The JS constant carries the same hexes as a
|
|
71
|
+
canvas/SVG/persistence-safe fallback; change both together. */
|
|
72
|
+
--mint-sample-1: #3B82F6;
|
|
73
|
+
--mint-sample-2: #10B981;
|
|
74
|
+
--mint-sample-3: #EF4444;
|
|
75
|
+
--mint-sample-4: #F59E0B;
|
|
76
|
+
--mint-sample-5: #8B5CF6;
|
|
77
|
+
--mint-sample-6: #F97316;
|
|
78
|
+
--mint-sample-7: #06B6D4;
|
|
79
|
+
--mint-sample-8: #14B8A6;
|
|
80
|
+
--mint-sample-9: #6B7280;
|
|
81
|
+
|
|
82
|
+
/* Rack / plate slot positions — mirrored by SLOT_COLORS in
|
|
83
|
+
src/utils/color.ts. */
|
|
84
|
+
--mint-slot-r: #ef4444;
|
|
85
|
+
--mint-slot-g: #22c55e;
|
|
86
|
+
--mint-slot-b: #3b82f6;
|
|
87
|
+
--mint-slot-y: #eab308;
|
|
88
|
+
|
|
89
|
+
/* Motion — the SDK's standard easing curve. */
|
|
90
|
+
--mint-ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
|
|
91
|
+
|
|
92
|
+
/* Typography — Fira Code for data, code and routes. */
|
|
93
|
+
--font-mono: 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
94
|
+
|
|
69
95
|
/* Border radius */
|
|
70
96
|
--radius-sm: 0.25rem;
|
|
71
97
|
--radius: 0.375rem;
|
|
@@ -90,6 +116,8 @@
|
|
|
90
116
|
--mint-warning-hover: #D97706;
|
|
91
117
|
--mint-warning-bg: rgba(245, 158, 11, 0.1);
|
|
92
118
|
--mint-warning-border: rgba(245, 158, 11, 0.3);
|
|
119
|
+
/* Readable warning label on --mint-warning-bg (amber-700, 5.9:1). */
|
|
120
|
+
--mint-warning-text: #B45309;
|
|
93
121
|
--mint-info: #3B82F6;
|
|
94
122
|
--mint-info-bg: rgba(59, 130, 246, 0.1);
|
|
95
123
|
--mint-info-border: rgba(59, 130, 246, 0.3);
|
|
@@ -178,6 +206,7 @@ html.dark {
|
|
|
178
206
|
--mint-success-bg: rgba(16, 185, 129, 0.15);
|
|
179
207
|
--mint-error-bg: rgba(239, 68, 68, 0.15);
|
|
180
208
|
--mint-warning-bg: rgba(245, 158, 11, 0.15);
|
|
209
|
+
--mint-warning-text: #FCD34D;
|
|
181
210
|
--mint-info-bg: rgba(59, 130, 246, 0.15);
|
|
182
211
|
|
|
183
212
|
/* Focus ring - dark mode offset uses bg-primary instead of white */
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
readString,
|
|
8
8
|
readStringList,
|
|
9
9
|
} from './builderReadUtils'
|
|
10
|
-
import { readPlateFormat } from '
|
|
10
|
+
import { readPlateFormat } from '../components/WellPlate.geometry'
|
|
11
11
|
import { getBioTemplatePresetInfo } from './presets'
|
|
12
12
|
import type {
|
|
13
13
|
CreateElisaAssayCollectionOptions,
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
3
|
-
}
|
|
1
|
+
export { isRecord } from '../utils/records'
|
|
4
2
|
|
|
5
3
|
export function readStringList(value: unknown, fallback: string[]): string[] {
|
|
6
4
|
if (Array.isArray(value)) {
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
PlateMapEditorState,
|
|
3
3
|
WellLegendItem,
|
|
4
4
|
} from '../types'
|
|
5
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
5
6
|
|
|
6
7
|
export function activePlateFromState(state: PlateMapEditorState) {
|
|
7
8
|
return state.plates.find(plate => plate.id === state.activePlateId) ?? state.plates[0]
|
|
@@ -24,6 +25,7 @@ export function legendItemsFromPlateState(state: PlateMapEditorState): WellLegen
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export function colorForIndex(index: number): string {
|
|
27
|
-
|
|
28
|
+
// The gray tail of the scale is reserved for "other"; component plates cycle the eight hues.
|
|
29
|
+
const colors = SAMPLE_COLOR_SCALE.slice(0, 8)
|
|
28
30
|
return colors[index % colors.length]
|
|
29
31
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObjectLike as isRecord } from '../utils/records'
|
|
1
2
|
import { extractTemplateCollection } from './templateEnvelopes'
|
|
2
3
|
import { getBioTemplateInfo } from './catalog'
|
|
3
4
|
import { getBioTemplatePackInfo } from './packs'
|
|
@@ -64,6 +65,3 @@ function collectionPackName(value: unknown): string | undefined {
|
|
|
64
65
|
return typeof value.metadata.pack === 'string' ? value.metadata.pack : undefined
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
68
|
-
return typeof value === 'object' && value !== null
|
|
69
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObjectLike as isRecord } from '../utils/records'
|
|
1
2
|
import {
|
|
2
3
|
getBioTemplateInfo,
|
|
3
4
|
} from './catalog'
|
|
@@ -82,6 +83,3 @@ function collectionPackName(value: unknown): string | undefined {
|
|
|
82
83
|
return typeof value.metadata.pack === 'string' ? value.metadata.pack : undefined
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
86
|
-
return typeof value === 'object' && value !== null
|
|
87
|
-
}
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
PlateCondition,
|
|
3
3
|
PlateMapEditorState,
|
|
4
4
|
} from '../types'
|
|
5
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
5
6
|
import { toPlateMapEditorState } from './plateMapAdapters'
|
|
6
7
|
import { getTemplateData } from './templateEnvelopes'
|
|
7
8
|
import { validateDoseResponseData } from './templateValidators'
|
|
@@ -11,18 +12,6 @@ import type {
|
|
|
11
12
|
DoseResponseTemplateData,
|
|
12
13
|
} from './types'
|
|
13
14
|
|
|
14
|
-
const CONDITION_COLORS = [
|
|
15
|
-
'#3B82F6',
|
|
16
|
-
'#10B981',
|
|
17
|
-
'#EF4444',
|
|
18
|
-
'#F59E0B',
|
|
19
|
-
'#8B5CF6',
|
|
20
|
-
'#F97316',
|
|
21
|
-
'#06B6D4',
|
|
22
|
-
'#14B8A6',
|
|
23
|
-
'#6B7280',
|
|
24
|
-
]
|
|
25
|
-
|
|
26
15
|
export function toDoseConditions(
|
|
27
16
|
template: DoseResponseTemplate | DoseResponseTemplateData
|
|
28
17
|
): DoseConditionsAdapterResult {
|
|
@@ -30,7 +19,7 @@ export function toDoseConditions(
|
|
|
30
19
|
validateDoseResponseData(data)
|
|
31
20
|
return data.compounds.map((compound, index): PlateCondition => ({
|
|
32
21
|
label: compound.name,
|
|
33
|
-
color: String(compound.metadata?.color ??
|
|
22
|
+
color: String(compound.metadata?.color ?? SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length]),
|
|
34
23
|
concentrations: compound.concentrations,
|
|
35
24
|
unit: data.unit,
|
|
36
25
|
}))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAssayMatrixTemplate } from './assayMatrixBuilder'
|
|
2
|
-
import {
|
|
2
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
3
3
|
import { idFromName } from './builderIdUtils'
|
|
4
4
|
import { createCalibrationCurveTemplate } from './calibrationCurveBuilder'
|
|
5
5
|
import { createPlateMapTemplate } from './plateMapBuilder'
|
|
@@ -27,7 +27,7 @@ export function createElisaAssayCollection(
|
|
|
27
27
|
...sampleRecords.map((sample, index) => ({
|
|
28
28
|
id: sample.sampleId,
|
|
29
29
|
name: sample.name ?? sample.sampleId,
|
|
30
|
-
color:
|
|
30
|
+
color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
|
|
31
31
|
})),
|
|
32
32
|
],
|
|
33
33
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
2
2
|
import { sampleIdFromName } from './builderIdUtils'
|
|
3
3
|
import { createTemplateEnvelope } from './templateEnvelopes'
|
|
4
4
|
import type {
|
|
@@ -23,7 +23,7 @@ export function createPlateMapTemplate(
|
|
|
23
23
|
return {
|
|
24
24
|
id: sampleIdFromName(sample, index),
|
|
25
25
|
name: sample,
|
|
26
|
-
color:
|
|
26
|
+
color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
|
|
27
27
|
}
|
|
28
28
|
})
|
|
29
29
|
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
SampleSheetTemplateData,
|
|
13
13
|
TimeCourseTemplateData,
|
|
14
14
|
} from './types'
|
|
15
|
-
import { assertWellInFormat } from '
|
|
15
|
+
import { assertWellInFormat } from '../components/WellPlate.geometry'
|
|
16
16
|
|
|
17
17
|
export function validatePlateMapData(data: PlateMapTemplateData): void {
|
|
18
18
|
if (!Array.isArray(data.plates) || data.plates.length === 0) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
2
2
|
import {
|
|
3
3
|
idFromName,
|
|
4
4
|
timepointId,
|
|
@@ -36,7 +36,7 @@ export function createTimeCourseTemplate(
|
|
|
36
36
|
return {
|
|
37
37
|
id: idFromName(condition, `condition-${index + 1}`),
|
|
38
38
|
name: condition,
|
|
39
|
-
color:
|
|
39
|
+
color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
|
|
40
40
|
metadata: {},
|
|
41
41
|
}
|
|
42
42
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SAMPLE_COLOR_SCALE } from '../utils/color'
|
|
2
2
|
import { createDoseResponseTemplate } from './doseResponseBuilder'
|
|
3
3
|
import { createPlateMapTemplate } from './plateMapBuilder'
|
|
4
4
|
import { createSampleSheetTemplate } from './sampleSheetBuilder'
|
|
@@ -19,7 +19,7 @@ export function createWellPlateScreenCollection(
|
|
|
19
19
|
samples: sampleRecords.map((sample, index) => ({
|
|
20
20
|
id: sample.sampleId,
|
|
21
21
|
name: sample.name ?? sample.sampleId,
|
|
22
|
-
color:
|
|
22
|
+
color: SAMPLE_COLOR_SCALE[index % SAMPLE_COLOR_SCALE.length],
|
|
23
23
|
})),
|
|
24
24
|
})
|
|
25
25
|
const sampleSheet = createSampleSheetTemplate({ samples: sampleRecords })
|
package/src/types/auth.ts
CHANGED
package/src/utils/color.ts
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared color scales and color math for the MINT SDK.
|
|
3
|
+
*
|
|
4
|
+
* ## Why the exported values are hex, not `var(--…)`
|
|
5
|
+
*
|
|
6
|
+
* Every scale below is mirrored by a CSS custom property in
|
|
7
|
+
* `styles/variables.css` (`--mint-sample-1…9`, `--mint-slot-r/g/b/y`), so
|
|
8
|
+
* stylesheets and `:style` bindings can stay theme-aware by referencing the
|
|
9
|
+
* token. The JavaScript constants deliberately carry the plain hex **fallback**
|
|
10
|
+
* for the same slot, because these values are also
|
|
11
|
+
*
|
|
12
|
+
* - persisted into experiment design data (`SampleType.color`), where a
|
|
13
|
+
* `var(--…)` string would be meaningless outside the browser, and
|
|
14
|
+
* - handed to canvas / SVG / export code paths, which cannot resolve CSS
|
|
15
|
+
* custom properties.
|
|
16
|
+
*
|
|
17
|
+
* Keep the two in sync: a change here must be mirrored in `variables.css`.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { SlotPosition } from '../types/componentLabTypes'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Canonical categorical scale for sample types, plate maps, dose-response
|
|
24
|
+
* series and legends. Mirrors `--mint-sample-1` … `--mint-sample-9`.
|
|
25
|
+
*/
|
|
26
|
+
export const SAMPLE_COLOR_SCALE: readonly string[] = [
|
|
27
|
+
'#3B82F6', // blue
|
|
28
|
+
'#10B981', // green
|
|
29
|
+
'#EF4444', // red
|
|
30
|
+
'#F59E0B', // amber
|
|
31
|
+
'#8B5CF6', // purple
|
|
32
|
+
'#F97316', // orange
|
|
33
|
+
'#06B6D4', // cyan
|
|
34
|
+
'#14B8A6', // teal
|
|
35
|
+
'#6B7280', // gray
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Slot-position colors shared by `PlateMapEditor` and `RackEditor`.
|
|
40
|
+
* Mirrors `--mint-slot-r`, `--mint-slot-g`, `--mint-slot-b`, `--mint-slot-y`.
|
|
41
|
+
*/
|
|
42
|
+
export const SLOT_COLORS: Record<SlotPosition, string> = {
|
|
43
|
+
R: '#ef4444', // red
|
|
44
|
+
G: '#22c55e', // green
|
|
45
|
+
B: '#3b82f6', // blue
|
|
46
|
+
Y: '#eab308', // yellow
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Slot positions in their canonical display order. */
|
|
50
|
+
export const SLOT_ORDER: readonly SlotPosition[] = ['R', 'G', 'B', 'Y']
|
|
51
|
+
|
|
1
52
|
/**
|
|
2
53
|
* Color utilities for deriving same-hue-family shades.
|
|
3
54
|
*
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a thrown value is turned into a developer-facing message.
|
|
3
|
+
*
|
|
4
|
+
* Five copies of this logic drifted apart across the composables and stores
|
|
5
|
+
* (some checked a bare `{ message }` object, some did not); this export is the
|
|
6
|
+
* union of what they all accepted, so every caller now reads the same message
|
|
7
|
+
* from the same value.
|
|
8
|
+
*/
|
|
9
|
+
export function readErrorMessage(value: unknown, fallback = 'Request failed.'): string {
|
|
10
|
+
if (value instanceof Error && value.message) {
|
|
11
|
+
return value.message
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (typeof value === 'string' && value.trim()) {
|
|
15
|
+
return value
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
typeof value === 'object'
|
|
20
|
+
&& value !== null
|
|
21
|
+
&& 'message' in value
|
|
22
|
+
&& typeof (value as { message?: unknown }).message === 'string'
|
|
23
|
+
&& (value as { message: string }).message.trim()
|
|
24
|
+
) {
|
|
25
|
+
return (value as { message: string }).message
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return fallback
|
|
29
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FormSchema } from '../types/form-builder'
|
|
2
|
+
import { isRecord } from './records'
|
|
2
3
|
|
|
3
4
|
export function recordValuesEqualForKeys(
|
|
4
5
|
left: Record<string, unknown>,
|
|
@@ -47,6 +48,3 @@ function valuesEqual(left: unknown, right: unknown): boolean {
|
|
|
47
48
|
return false
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
51
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
52
|
-
}
|
package/src/utils/pluginIcon.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from './records'
|
|
1
2
|
export type PluginIconFormat = 'path' | 'data-url' | 'asset-url' | 'structured' | 'fallback'
|
|
2
3
|
|
|
3
4
|
export interface StructuredPluginIconStop {
|
|
@@ -177,9 +178,6 @@ function parseOffset(value: unknown): string | undefined {
|
|
|
177
178
|
return undefined
|
|
178
179
|
}
|
|
179
180
|
|
|
180
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
181
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
182
|
-
}
|
|
183
181
|
|
|
184
182
|
function isSafeColor(value: unknown): value is string {
|
|
185
183
|
return typeof value === 'string' && COLOR_REGEX.test(value)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable references for plugin secret settings.
|
|
3
|
+
*
|
|
4
|
+
* A settings response never carries a secret's value. Every secret leaf is a
|
|
5
|
+
* marker instead:
|
|
6
|
+
*
|
|
7
|
+
* - `{ "$secret": "sec_…", "set": true }` — a stored secret, referenced by a
|
|
8
|
+
* stable opaque id. Send the marker back unchanged to keep the stored value.
|
|
9
|
+
* - `null` — nothing stored at that position.
|
|
10
|
+
* - `{ "$secret": null, "locked": true }` — the effective value comes from the
|
|
11
|
+
* environment and is never written back.
|
|
12
|
+
*
|
|
13
|
+
* On save each secret leaf accepts the reference, a plain string (a new value),
|
|
14
|
+
* or `null` (clear). Payloads carry `secret_format: "ref"` so a `null` reads as
|
|
15
|
+
* a deliberate clear rather than the deprecated "unchanged" placeholder.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** Reserved marker key that references a stored secret. */
|
|
19
|
+
export const PLUGIN_SECRET_REF_KEY = '$secret'
|
|
20
|
+
|
|
21
|
+
/** Reserved payload key declaring which secret wire format a client speaks. */
|
|
22
|
+
export const PLUGIN_SECRET_FORMAT_KEY = 'secret_format'
|
|
23
|
+
|
|
24
|
+
/** Wire format published and understood by this SDK. */
|
|
25
|
+
export const PLUGIN_SECRET_FORMAT_REF = 'ref'
|
|
26
|
+
|
|
27
|
+
/** One `$secret` marker as published by a settings response. */
|
|
28
|
+
export interface PluginSecretRef {
|
|
29
|
+
$secret: string | null
|
|
30
|
+
set?: boolean
|
|
31
|
+
locked?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** What a settings form should tell the user about one secret field. */
|
|
35
|
+
export type PluginSecretState = 'set' | 'unset' | 'environment'
|
|
36
|
+
|
|
37
|
+
const MARKER_KEYS = new Set([PLUGIN_SECRET_REF_KEY, 'set', 'locked'])
|
|
38
|
+
|
|
39
|
+
/** Return whether one settings value is a `$secret` reference marker. */
|
|
40
|
+
export function isPluginSecretRef(value: unknown): value is PluginSecretRef {
|
|
41
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false
|
|
42
|
+
const record = value as Record<string, unknown>
|
|
43
|
+
if (!(PLUGIN_SECRET_REF_KEY in record)) return false
|
|
44
|
+
return Object.keys(record).every(key => MARKER_KEYS.has(key))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Return the stored secret id behind a marker, or `null` when nothing is stored. */
|
|
48
|
+
export function pluginSecretId(value: unknown): string | null {
|
|
49
|
+
if (!isPluginSecretRef(value)) return null
|
|
50
|
+
return typeof value.$secret === 'string' ? value.$secret : null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Classify one secret field for display: stored, unset, or environment-provided. */
|
|
54
|
+
export function pluginSecretState(value: unknown): PluginSecretState {
|
|
55
|
+
if (isPluginSecretRef(value)) {
|
|
56
|
+
if (value.locked) return 'environment'
|
|
57
|
+
return typeof value.$secret === 'string' ? 'set' : 'unset'
|
|
58
|
+
}
|
|
59
|
+
return typeof value === 'string' && value.length > 0 ? 'set' : 'unset'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Human label for one secret field's state. */
|
|
63
|
+
export function pluginSecretLabel(value: unknown): string {
|
|
64
|
+
const state = pluginSecretState(value)
|
|
65
|
+
if (state === 'environment') return 'Provided by environment'
|
|
66
|
+
return state === 'set' ? 'Set' : 'Not set'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Whether a secret field is read-only because the environment supplies it. */
|
|
70
|
+
export function isPluginSecretLocked(value: unknown): boolean {
|
|
71
|
+
return isPluginSecretRef(value) && value.locked === true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Value to submit for an untouched secret field: the reference, unchanged.
|
|
76
|
+
*
|
|
77
|
+
* A locked marker round-trips too, which is how the platform keeps a stored
|
|
78
|
+
* value that an environment variable currently hides.
|
|
79
|
+
*/
|
|
80
|
+
export function keepPluginSecret(current: unknown): PluginSecretRef | null {
|
|
81
|
+
if (isPluginSecretRef(current)) return { ...current }
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Value to submit when the user typed a new secret. */
|
|
86
|
+
export function setPluginSecret(value: string): string {
|
|
87
|
+
return value
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Value to submit when the user cleared a secret. */
|
|
91
|
+
export function clearPluginSecret(): null {
|
|
92
|
+
return null
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Whether a settings response declares the `$secret` reference wire format. */
|
|
96
|
+
export function usesPluginSecretReferences(response: unknown): boolean {
|
|
97
|
+
if (!response || typeof response !== 'object') return false
|
|
98
|
+
return (
|
|
99
|
+
(response as Record<string, unknown>)[PLUGIN_SECRET_FORMAT_KEY]
|
|
100
|
+
=== PLUGIN_SECRET_FORMAT_REF
|
|
101
|
+
)
|
|
102
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Narrow an unknown value to a plain object (arrays and null excluded). */
|
|
2
|
+
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
3
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Narrow an unknown value to any non-null object, arrays included. */
|
|
7
|
+
export function isObjectLike(value: unknown): value is Record<string, unknown> {
|
|
8
|
+
return typeof value === 'object' && value !== null
|
|
9
|
+
}
|