@morscherlab/mint-sdk 1.0.0-rc.2 → 1.0.0-rc.4

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.
Files changed (178) hide show
  1. package/dist/components/AppSidebar.vue.d.ts +3 -3
  2. package/dist/components/ControlWorkspaceView.vue.d.ts +3 -3
  3. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +1 -1
  4. package/dist/components/PluginWorkspaceView.vue.d.ts +3 -3
  5. package/dist/components/index.js +2 -2
  6. package/dist/{components-BhK-dW99.js → components-DafPc4rM.js} +3 -3
  7. package/dist/{components-BhK-dW99.js.map → components-DafPc4rM.js.map} +1 -1
  8. package/dist/composables/controlComponentBindings.d.ts +7 -0
  9. package/dist/composables/controlSchemaAdapters.d.ts +20 -0
  10. package/dist/composables/controlSchemaFormFields.d.ts +3 -0
  11. package/dist/composables/controlSchemaLayout.d.ts +7 -0
  12. package/dist/composables/controlSchemaNormalize.d.ts +15 -0
  13. package/dist/composables/controlSchemaUtils.d.ts +9 -0
  14. package/dist/composables/controlWorkspaceOptions.d.ts +2 -0
  15. package/dist/composables/index.js +3 -3
  16. package/dist/composables/useControlSchema.d.ts +4 -30
  17. package/dist/composables/useControlWorkspace.d.ts +5 -0
  18. package/dist/{composables-Bg7CFuNz.js → composables-BMkPQhVK.js} +2 -2
  19. package/dist/{composables-Bg7CFuNz.js.map → composables-BMkPQhVK.js.map} +1 -1
  20. package/dist/index.js +4 -4
  21. package/dist/install.js +2 -2
  22. package/dist/templates/adapters.d.ts +14 -47
  23. package/dist/templates/assayLookups.d.ts +3 -0
  24. package/dist/templates/assayMatrixAdapters.d.ts +6 -0
  25. package/dist/templates/assayMatrixBuilder.d.ts +2 -0
  26. package/dist/templates/assayNormalizers.d.ts +4 -0
  27. package/dist/templates/builderDefaults.d.ts +1 -0
  28. package/dist/templates/builderIdUtils.d.ts +4 -0
  29. package/dist/templates/builderPresetControls.d.ts +10 -0
  30. package/dist/templates/builderReadUtils.d.ts +8 -0
  31. package/dist/templates/builders.d.ts +26 -67
  32. package/dist/templates/calibrationCurveAdapters.d.ts +4 -0
  33. package/dist/templates/calibrationCurveBuilder.d.ts +2 -0
  34. package/dist/templates/calibrationNormalizers.d.ts +5 -0
  35. package/dist/templates/componentBindingCatalog.d.ts +25 -0
  36. package/dist/templates/componentBindingHelpers.d.ts +17 -0
  37. package/dist/templates/componentDoseResponseProps.d.ts +3 -0
  38. package/dist/templates/componentGenericProps.d.ts +8 -0
  39. package/dist/templates/componentPlateHelpers.d.ts +5 -0
  40. package/dist/templates/componentPlateMapProps.d.ts +3 -0
  41. package/dist/templates/componentPropsFactory.d.ts +3 -0
  42. package/dist/templates/componentQpcrPlateProps.d.ts +3 -0
  43. package/dist/templates/componentTargetResolvers.d.ts +5 -0
  44. package/dist/templates/componentTemplateProps.d.ts +3 -0
  45. package/dist/templates/controlSchemaClone.d.ts +4 -0
  46. package/dist/templates/controlSchemaConstants.d.ts +10 -0
  47. package/dist/templates/controlSchemaMerge.d.ts +3 -0
  48. package/dist/templates/controlSchemaTargets.d.ts +17 -0
  49. package/dist/templates/controlSchemaTypes.d.ts +4 -0
  50. package/dist/templates/controlSchemas.d.ts +4 -4
  51. package/dist/templates/defaultBioTemplateBuilder.d.ts +2 -0
  52. package/dist/templates/doseResponseAdapters.d.ts +4 -0
  53. package/dist/templates/doseResponseBuilder.d.ts +2 -0
  54. package/dist/templates/elisaAssayCollectionBuilder.d.ts +2 -0
  55. package/dist/templates/flowCytometryAssayCollectionBuilder.d.ts +2 -0
  56. package/dist/templates/flowCytometryPanelBuilder.d.ts +2 -0
  57. package/dist/templates/flowNormalizers.d.ts +8 -0
  58. package/dist/templates/flowPanelAdapters.d.ts +4 -0
  59. package/dist/templates/index.js +1 -1
  60. package/dist/templates/instrumentRunAdapterHelpers.d.ts +8 -0
  61. package/dist/templates/instrumentRunAdapters.d.ts +8 -0
  62. package/dist/templates/instrumentRunBuilder.d.ts +2 -0
  63. package/dist/templates/lcmsBatchCollectionBuilder.d.ts +2 -0
  64. package/dist/templates/plateGeometry.d.ts +4 -0
  65. package/dist/templates/plateMapAdapters.d.ts +3 -0
  66. package/dist/templates/plateMapBuilder.d.ts +2 -0
  67. package/dist/templates/presetControlSchemas.d.ts +534 -0
  68. package/dist/templates/protocolAdapters.d.ts +5 -0
  69. package/dist/templates/protocolNormalizers.d.ts +6 -0
  70. package/dist/templates/protocolStepsBuilder.d.ts +2 -0
  71. package/dist/templates/qpcrAdapters.d.ts +5 -0
  72. package/dist/templates/qpcrExpressionCollectionBuilder.d.ts +2 -0
  73. package/dist/templates/qpcrPlateBuilder.d.ts +2 -0
  74. package/dist/templates/reagentAdapters.d.ts +5 -0
  75. package/dist/templates/reagentListBuilder.d.ts +2 -0
  76. package/dist/templates/runNormalizers.d.ts +10 -0
  77. package/dist/templates/sampleNormalizers.d.ts +4 -0
  78. package/dist/templates/samplePrepAdapters.d.ts +4 -0
  79. package/dist/templates/samplePrepBuilder.d.ts +2 -0
  80. package/dist/templates/sampleSheetAdapters.d.ts +5 -0
  81. package/dist/templates/sampleSheetBuilder.d.ts +2 -0
  82. package/dist/templates/targetedMetabolomicsCollectionBuilder.d.ts +2 -0
  83. package/dist/templates/targetedMetabolomicsHelpers.d.ts +5 -0
  84. package/dist/templates/templateControlSchemas.d.ts +400 -0
  85. package/dist/templates/templateEnvelopes.d.ts +9 -0
  86. package/dist/templates/templatePackCollectionBuilder.d.ts +2 -0
  87. package/dist/templates/templatePresetCollectionBuilder.d.ts +18 -0
  88. package/dist/templates/templateValidators.d.ts +13 -0
  89. package/dist/templates/timeCourseAdapters.d.ts +5 -0
  90. package/dist/templates/timeCourseBuilder.d.ts +2 -0
  91. package/dist/templates/wellPlateScreenCollectionBuilder.d.ts +2 -0
  92. package/dist/templates/westernBlotAssayCollectionBuilder.d.ts +2 -0
  93. package/dist/{templates-BorLR_7p.js → templates-bUAWMn5L.js} +3574 -3428
  94. package/dist/templates-bUAWMn5L.js.map +1 -0
  95. package/dist/{useProtocolTemplates-n6AJqSqv.js → useProtocolTemplates-QZtHFFH2.js} +2 -2
  96. package/dist/{useProtocolTemplates-n6AJqSqv.js.map → useProtocolTemplates-QZtHFFH2.js.map} +1 -1
  97. package/package.json +1 -1
  98. package/src/composables/controlComponentBindings.ts +80 -0
  99. package/src/composables/controlSchemaAdapters.ts +196 -0
  100. package/src/composables/controlSchemaFormFields.ts +61 -0
  101. package/src/composables/controlSchemaLayout.ts +59 -0
  102. package/src/composables/controlSchemaNormalize.ts +101 -0
  103. package/src/composables/controlSchemaUtils.ts +36 -0
  104. package/src/composables/controlWorkspaceOptions.ts +21 -0
  105. package/src/composables/useControlSchema.ts +51 -628
  106. package/src/composables/useControlWorkspace.ts +207 -0
  107. package/src/templates/adapters.ts +89 -930
  108. package/src/templates/assayLookups.ts +33 -0
  109. package/src/templates/assayMatrixAdapters.ts +78 -0
  110. package/src/templates/assayMatrixBuilder.ts +59 -0
  111. package/src/templates/assayNormalizers.ts +34 -0
  112. package/src/templates/builderDefaults.ts +11 -0
  113. package/src/templates/builderIdUtils.ts +20 -0
  114. package/src/templates/builderPresetControls.ts +165 -0
  115. package/src/templates/builderReadUtils.ts +57 -0
  116. package/src/templates/builders.ts +122 -2350
  117. package/src/templates/calibrationCurveAdapters.ts +59 -0
  118. package/src/templates/calibrationCurveBuilder.ts +99 -0
  119. package/src/templates/calibrationNormalizers.ts +60 -0
  120. package/src/templates/componentBindingCatalog.ts +90 -0
  121. package/src/templates/componentBindingHelpers.ts +93 -0
  122. package/src/templates/componentBindings.ts +12 -461
  123. package/src/templates/componentDoseResponseProps.ts +42 -0
  124. package/src/templates/componentGenericProps.ts +77 -0
  125. package/src/templates/componentPlateHelpers.ts +29 -0
  126. package/src/templates/componentPlateMapProps.ts +32 -0
  127. package/src/templates/componentPropsFactory.ts +21 -0
  128. package/src/templates/componentQpcrPlateProps.ts +28 -0
  129. package/src/templates/componentTargetResolvers.ts +69 -0
  130. package/src/templates/componentTemplateProps.ts +78 -0
  131. package/src/templates/controlSchemaClone.ts +32 -0
  132. package/src/templates/controlSchemaConstants.ts +11 -0
  133. package/src/templates/controlSchemaMerge.ts +40 -0
  134. package/src/templates/controlSchemaTargets.ts +87 -0
  135. package/src/templates/controlSchemaTypes.ts +20 -0
  136. package/src/templates/controlSchemas.ts +22 -704
  137. package/src/templates/defaultBioTemplateBuilder.ts +124 -0
  138. package/src/templates/doseResponseAdapters.ts +45 -0
  139. package/src/templates/doseResponseBuilder.ts +44 -0
  140. package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
  141. package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
  142. package/src/templates/flowCytometryPanelBuilder.ts +53 -0
  143. package/src/templates/flowNormalizers.ts +58 -0
  144. package/src/templates/flowPanelAdapters.ts +58 -0
  145. package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
  146. package/src/templates/instrumentRunAdapters.ts +163 -0
  147. package/src/templates/instrumentRunBuilder.ts +97 -0
  148. package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
  149. package/src/templates/plateGeometry.ts +62 -0
  150. package/src/templates/plateMapAdapters.ts +36 -0
  151. package/src/templates/plateMapBuilder.ts +43 -0
  152. package/src/templates/presetControlSchemas.ts +258 -0
  153. package/src/templates/protocolAdapters.ts +69 -0
  154. package/src/templates/protocolNormalizers.ts +37 -0
  155. package/src/templates/protocolStepsBuilder.ts +36 -0
  156. package/src/templates/qpcrAdapters.ts +104 -0
  157. package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
  158. package/src/templates/qpcrPlateBuilder.ts +96 -0
  159. package/src/templates/reagentAdapters.ts +77 -0
  160. package/src/templates/reagentListBuilder.ts +30 -0
  161. package/src/templates/runNormalizers.ts +63 -0
  162. package/src/templates/sampleNormalizers.ts +58 -0
  163. package/src/templates/samplePrepAdapters.ts +63 -0
  164. package/src/templates/samplePrepBuilder.ts +51 -0
  165. package/src/templates/sampleSheetAdapters.ts +75 -0
  166. package/src/templates/sampleSheetBuilder.ts +23 -0
  167. package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
  168. package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
  169. package/src/templates/templateControlSchemas.ts +320 -0
  170. package/src/templates/templateEnvelopes.ts +137 -0
  171. package/src/templates/templatePackCollectionBuilder.ts +23 -0
  172. package/src/templates/templatePresetCollectionBuilder.ts +139 -0
  173. package/src/templates/templateValidators.ts +414 -0
  174. package/src/templates/timeCourseAdapters.ts +73 -0
  175. package/src/templates/timeCourseBuilder.ts +64 -0
  176. package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
  177. package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
  178. package/dist/templates-BorLR_7p.js.map +0 -1
@@ -1,48 +1,23 @@
1
- import type { WellLegendItem } from '../types'
1
+ import { extractTemplateCollection } from './templateEnvelopes'
2
2
  import {
3
- extractTemplateCollection,
4
- getTemplateData,
5
- } from './builders'
3
+ isTemplateEnvelope,
4
+ resolveComponentTemplateIds,
5
+ } from './componentTargetResolvers'
6
6
  import {
7
- toAssayMatrixSampleOptions,
8
- toDoseConditions,
9
- toDoseLayoutState,
10
- toInstrumentRunScheduleEvents,
11
- toInstrumentRunSteps,
12
- toPlateMapEditorState,
13
- toProtocolSteps,
14
- toQpcrWellPlateWells,
15
- toReagentListItems,
16
- toSampleOptions,
17
- toTemplateDataFrame,
18
- toTimeCourseSteps,
19
- toWellPlateWells,
20
- } from './adapters'
21
- import {
22
- getBioTemplateInfo,
23
- } from './catalog'
24
- import {
25
- getBioTemplatePresetInfo,
26
- } from './presets'
27
- import {
28
- getBioTemplatePackInfo,
29
- } from './packs'
7
+ cloneBinding,
8
+ cloneBindingMap,
9
+ cloneBindings,
10
+ toVueSfc,
11
+ uniquePropsName,
12
+ } from './componentBindingHelpers'
13
+ import { templateComponentBindings } from './componentBindingCatalog'
14
+ import { propsForTemplate } from './componentTemplateProps'
30
15
  import type {
31
16
  BioTemplateEnvelope,
32
- AssayMatrixTemplate,
33
- DataFrameTemplate,
34
- DoseResponseTemplate,
35
- InstrumentRunTemplate,
36
- PlateMapTemplate,
37
- QpcrPlateTemplate,
38
- ReagentListTemplate,
39
- SampleSheetTemplate,
40
17
  TemplateCollectionEnvelope,
41
18
  TemplateId,
42
19
  TemplatePackId,
43
20
  TemplatePresetId,
44
- TimeCourseTemplate,
45
- ProtocolStepsTemplate,
46
21
  } from './types'
47
22
 
48
23
  export type BioTemplateComponentTarget =
@@ -116,67 +91,6 @@ export interface BioTemplateComponentUsage {
116
91
  sfc: string
117
92
  }
118
93
 
119
- const templateComponentBindings = {
120
- 'plate-map': [
121
- binding('plate-map', 'PlateMapEditor', ['toPlateMapEditorState'], ['modelValue', 'format', 'samples'], 'Edit plate layouts from plate-map template data.'),
122
- binding('plate-map', 'WellPlate', ['toWellPlateWells'], ['format', 'wells', 'sampleColors', 'legendItems'], 'Render the active plate as a well grid.'),
123
- ],
124
- 'sample-sheet': [
125
- binding('sample-sheet', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render sample metadata as a sortable table.'),
126
- binding('sample-sheet', 'SampleSelector', ['toSampleOptions'], ['samples', 'modelValue'], 'Select samples from sample-sheet records.'),
127
- ],
128
- 'sample-prep': [
129
- binding('sample-prep', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render preparation steps as a table.'),
130
- ],
131
- 'dose-response': [
132
- binding('dose-response', 'DoseCalculator', ['toDoseConditions'], ['mode', 'targetWells'], 'Configure serial dilution and apply concentrations to wells.'),
133
- binding('dose-response', 'WellPlate', ['toDoseLayoutState'], ['format', 'wells', 'sampleColors', 'legendItems'], 'Render the optional dose-response plate layout.'),
134
- ],
135
- 'calibration-curve': [
136
- binding('calibration-curve', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render standards, QC, blanks, and response values.'),
137
- ],
138
- 'time-course': [
139
- binding('time-course', 'ExperimentTimeline', ['toTimeCourseSteps'], ['modelValue', 'orientation'], 'Render time points as an ordered timeline.'),
140
- binding('time-course', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render longitudinal samples as a table.'),
141
- ],
142
- 'protocol-steps': [
143
- binding('protocol-steps', 'ExperimentTimeline', ['toProtocolSteps'], ['modelValue', 'orientation', 'editable'], 'Render protocol steps as an editable timeline.'),
144
- binding('protocol-steps', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render protocol steps as a table.'),
145
- ],
146
- 'assay-matrix': [
147
- binding('assay-matrix', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render sample-by-feature measurements.'),
148
- binding('assay-matrix', 'SampleSelector', ['toAssayMatrixSampleOptions'], ['samples', 'modelValue'], 'Select samples from assay-matrix records.'),
149
- ],
150
- 'reagent-list': [
151
- binding('reagent-list', 'ReagentList', ['toReagentListItems'], ['modelValue'], 'Render reagents with lot, storage, and stock metadata.'),
152
- binding('reagent-list', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render reagents as a table.'),
153
- ],
154
- 'flow-cytometry-panel': [
155
- binding('flow-cytometry-panel', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render markers, fluorophores, detectors, and controls.'),
156
- ],
157
- 'instrument-run': [
158
- binding('instrument-run', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render acquisition queues, methods, QC, and run status.'),
159
- binding(
160
- 'instrument-run',
161
- 'ScheduleCalendar',
162
- ['toInstrumentRunScheduleEvents'],
163
- ['modelValue', 'events', 'view', 'readonly', 'showNavigation', 'showViewToggle'],
164
- 'Render acquisition queues as a scheduled run calendar.',
165
- ),
166
- binding(
167
- 'instrument-run',
168
- 'ExperimentTimeline',
169
- ['toInstrumentRunSteps'],
170
- ['modelValue', 'orientation', 'showDuration', 'editable'],
171
- 'Render acquisition queues as an ordered run timeline.',
172
- ),
173
- ],
174
- 'qpcr-plate': [
175
- binding('qpcr-plate', 'WellPlate', ['toQpcrWellPlateWells'], ['format', 'wells', 'sampleColors', 'legendItems'], 'Render qPCR reactions on a well plate.'),
176
- binding('qpcr-plate', 'DataFrame', ['toTemplateDataFrame'], ['data', 'columns', 'rowKey'], 'Render qPCR reactions, targets, controls, and Cq values.'),
177
- ],
178
- } satisfies Record<TemplateId, readonly BioTemplateComponentBinding[]>
179
-
180
94
  export function listBioTemplateComponentBindings(): Record<TemplateId, BioTemplateComponentBinding[]> {
181
95
  return cloneBindingMap(templateComponentBindings)
182
96
  }
@@ -337,366 +251,3 @@ export function toBioTemplateComponentUsage(
337
251
  sfc: toVueSfc(imports, setupLines, template, usesGeneratedTargetProp),
338
252
  }
339
253
  }
340
-
341
- function propsForTemplate(template: BioTemplateEnvelope<unknown>): BioTemplateComponentPropsBinding[] {
342
- switch (template.template_id) {
343
- case 'plate-map':
344
- return plateMapProps(template as PlateMapTemplate)
345
- case 'sample-sheet':
346
- return [
347
- dataFrameProps(template as DataFrameTemplate),
348
- sampleSelectorProps(template as SampleSheetTemplate),
349
- ]
350
- case 'sample-prep':
351
- case 'calibration-curve':
352
- case 'flow-cytometry-panel':
353
- return [dataFrameProps(template as DataFrameTemplate)]
354
- case 'assay-matrix':
355
- return [
356
- dataFrameProps(template as DataFrameTemplate),
357
- assayMatrixSampleSelectorProps(template as AssayMatrixTemplate),
358
- ]
359
- case 'instrument-run':
360
- return [
361
- dataFrameProps(template as DataFrameTemplate),
362
- scheduleCalendarProps(template as InstrumentRunTemplate),
363
- timelineProps(template as InstrumentRunTemplate, toInstrumentRunSteps(template as InstrumentRunTemplate)),
364
- ]
365
- case 'dose-response':
366
- return doseResponseProps(template as DoseResponseTemplate)
367
- case 'time-course':
368
- return [
369
- timelineProps(template as TimeCourseTemplate, toTimeCourseSteps(template as TimeCourseTemplate)),
370
- dataFrameProps(template as DataFrameTemplate),
371
- ]
372
- case 'protocol-steps':
373
- return [
374
- timelineProps(template as ProtocolStepsTemplate, toProtocolSteps(template as ProtocolStepsTemplate), true),
375
- dataFrameProps(template as DataFrameTemplate),
376
- ]
377
- case 'reagent-list':
378
- return [
379
- reagentListProps(template as ReagentListTemplate),
380
- dataFrameProps(template as DataFrameTemplate),
381
- ]
382
- case 'qpcr-plate':
383
- return qpcrPlateProps(template as QpcrPlateTemplate)
384
- default:
385
- return []
386
- }
387
- }
388
-
389
- function plateMapProps(template: PlateMapTemplate): BioTemplateComponentPropsBinding[] {
390
- const state = toPlateMapEditorState(template)
391
- const plate = activePlateFromState(state)
392
- return [
393
- propsBinding('plate-map', 'PlateMapEditor', {
394
- modelValue: state,
395
- format: plate.format,
396
- samples: state.samples,
397
- }),
398
- propsBinding('plate-map', 'WellPlate', {
399
- format: plate.format,
400
- wells: toWellPlateWells(template),
401
- sampleColors: sampleColorsFromPlateState(state),
402
- legendItems: legendItemsFromPlateState(state),
403
- showLegend: true,
404
- showSampleTypeIndicator: true,
405
- }),
406
- ]
407
- }
408
-
409
- function doseResponseProps(template: DoseResponseTemplate): BioTemplateComponentPropsBinding[] {
410
- const conditions = toDoseConditions(template)
411
- const layout = toDoseLayoutState(template)
412
- const targetWells = layout ? Object.keys(activePlateFromState(layout).wells) : []
413
- const props = [
414
- propsBinding('dose-response', 'DoseCalculator', {
415
- mode: 'serial',
416
- targetWells,
417
- disabled: conditions.length === 0,
418
- }),
419
- ]
420
-
421
- if (layout) {
422
- const plate = activePlateFromState(layout)
423
- props.push(propsBinding('dose-response', 'WellPlate', {
424
- format: plate.format,
425
- wells: plate.wells,
426
- sampleColors: sampleColorsFromPlateState(layout),
427
- legendItems: conditions.map(condition => ({
428
- type: condition.label,
429
- label: condition.label,
430
- color: condition.color,
431
- })),
432
- showLegend: true,
433
- showSampleTypeIndicator: true,
434
- }))
435
- }
436
-
437
- return props
438
- }
439
-
440
- function qpcrPlateProps(template: QpcrPlateTemplate): BioTemplateComponentPropsBinding[] {
441
- const data = getTemplateData(template, 'qpcr-plate')
442
- const frame = dataFrameProps(template)
443
- return [
444
- propsBinding('qpcr-plate', 'WellPlate', {
445
- format: data.format,
446
- wells: toQpcrWellPlateWells(template),
447
- sampleColors: Object.fromEntries(data.samples.map((sample, index) => [sample.sampleId, colorForIndex(index)])),
448
- legendItems: data.samples.map((sample, index): WellLegendItem => ({
449
- type: sample.sampleId,
450
- label: sample.name ?? sample.sampleId,
451
- color: colorForIndex(index),
452
- })),
453
- showLegend: true,
454
- showSampleTypeIndicator: true,
455
- }),
456
- frame,
457
- ]
458
- }
459
-
460
- function dataFrameProps(template: DataFrameTemplate): BioTemplateComponentPropsBinding {
461
- const frame = toTemplateDataFrame(template)
462
- return propsBinding(template.template_id as TemplateId, 'DataFrame', {
463
- ...frame,
464
- searchable: true,
465
- sortable: true,
466
- size: 'sm',
467
- })
468
- }
469
-
470
- function sampleSelectorProps(template: SampleSheetTemplate): BioTemplateComponentPropsBinding {
471
- const options = toSampleOptions(template)
472
- return propsBinding('sample-sheet', 'SampleSelector', {
473
- samples: options.map(option => option.label),
474
- modelValue: [],
475
- })
476
- }
477
-
478
- function assayMatrixSampleSelectorProps(template: AssayMatrixTemplate): BioTemplateComponentPropsBinding {
479
- const options = toAssayMatrixSampleOptions(template)
480
- return propsBinding('assay-matrix', 'SampleSelector', {
481
- samples: options.map(option => option.label),
482
- modelValue: [],
483
- })
484
- }
485
-
486
- function timelineProps(
487
- template: TimeCourseTemplate | ProtocolStepsTemplate | InstrumentRunTemplate,
488
- steps: unknown[],
489
- editable = false
490
- ): BioTemplateComponentPropsBinding {
491
- return propsBinding(template.template_id as TemplateId, 'ExperimentTimeline', {
492
- modelValue: steps,
493
- orientation: 'vertical',
494
- editable,
495
- })
496
- }
497
-
498
- function scheduleCalendarProps(template: InstrumentRunTemplate): BioTemplateComponentPropsBinding {
499
- const events = toInstrumentRunScheduleEvents(template)
500
- return propsBinding('instrument-run', 'ScheduleCalendar', {
501
- modelValue: events[0]?.start,
502
- events,
503
- view: 'day',
504
- readonly: true,
505
- showNavigation: false,
506
- showViewToggle: false,
507
- })
508
- }
509
-
510
- function reagentListProps(template: ReagentListTemplate): BioTemplateComponentPropsBinding {
511
- return propsBinding('reagent-list', 'ReagentList', {
512
- modelValue: toReagentListItems(template),
513
- searchable: true,
514
- sortable: true,
515
- })
516
- }
517
-
518
- function propsBinding(
519
- templateId: TemplateId,
520
- component: string,
521
- propsObject: Record<string, unknown>
522
- ): BioTemplateComponentPropsBinding {
523
- const matched = templateComponentBindings[templateId].find(binding => binding.component === component)
524
- if (!matched) {
525
- throw new Error(`No component binding registered for '${templateId}' and '${component}'.`)
526
- }
527
- return {
528
- ...cloneBinding(matched),
529
- propsObject,
530
- }
531
- }
532
-
533
- function resolveComponentTemplateIds(target: BioTemplateComponentTarget): TemplateId[] {
534
- if (typeof target === 'string') {
535
- const preset = getBioTemplatePresetInfo(target)
536
- if (preset) return [...preset.templates]
537
- const pack = getBioTemplatePackInfo(target)
538
- if (pack) return [...pack.templates]
539
- const template = getBioTemplateInfo(target)
540
- return template ? [template.template_id] : []
541
- }
542
-
543
- if (isTemplateEnvelope(target)) {
544
- const template = getBioTemplateInfo(target.template_id)
545
- return template ? [template.template_id] : []
546
- }
547
-
548
- const presetName = collectionPresetName(target)
549
- if (presetName) {
550
- const preset = getBioTemplatePresetInfo(presetName)
551
- if (preset) return [...preset.templates]
552
- }
553
-
554
- const packName = collectionPackName(target)
555
- if (packName) {
556
- const pack = getBioTemplatePackInfo(packName)
557
- if (pack) return [...pack.templates]
558
- }
559
-
560
- return Object.keys(extractTemplateCollection(target))
561
- .map(templateId => getBioTemplateInfo(templateId)?.template_id)
562
- .filter((templateId): templateId is TemplateId => templateId !== undefined)
563
- }
564
-
565
- function binding(
566
- templateId: TemplateId,
567
- component: string,
568
- adapters: readonly string[],
569
- props: readonly string[],
570
- description: string
571
- ): BioTemplateComponentBinding {
572
- return {
573
- id: `${templateId}:${component}`,
574
- template_id: templateId,
575
- component,
576
- adapters,
577
- props,
578
- description,
579
- importPath: '@morscherlab/mint-sdk',
580
- }
581
- }
582
-
583
- function activePlateFromState(state: ReturnType<typeof toPlateMapEditorState>) {
584
- return state.plates.find(plate => plate.id === state.activePlateId) ?? state.plates[0]
585
- }
586
-
587
- function sampleColorsFromPlateState(state: ReturnType<typeof toPlateMapEditorState>): Record<string, string> {
588
- return Object.fromEntries(
589
- state.samples
590
- .filter(sample => sample.color)
591
- .map(sample => [sample.id, sample.color as string])
592
- )
593
- }
594
-
595
- function legendItemsFromPlateState(state: ReturnType<typeof toPlateMapEditorState>): WellLegendItem[] {
596
- return state.samples.map((sample, index) => ({
597
- type: sample.id,
598
- label: sample.name,
599
- color: sample.color ?? colorForIndex(index),
600
- }))
601
- }
602
-
603
- function colorForIndex(index: number): string {
604
- const colors = ['#3B82F6', '#10B981', '#EF4444', '#F59E0B', '#8B5CF6', '#F97316', '#06B6D4', '#14B8A6']
605
- return colors[index % colors.length]
606
- }
607
-
608
- function cloneBindingMap<TName extends string>(
609
- bindings: Record<TName, readonly BioTemplateComponentBinding[]>
610
- ): Record<TName, BioTemplateComponentBinding[]> {
611
- const result = {} as Record<TName, BioTemplateComponentBinding[]>
612
- for (const name of Object.keys(bindings) as TName[]) {
613
- result[name] = cloneBindings(bindings[name])
614
- }
615
- return result
616
- }
617
-
618
- function cloneBindings(bindings: readonly BioTemplateComponentBinding[]): BioTemplateComponentBinding[] {
619
- return bindings.map(cloneBinding)
620
- }
621
-
622
- function cloneBinding(binding: BioTemplateComponentBinding): BioTemplateComponentBinding {
623
- return {
624
- ...binding,
625
- adapters: [...binding.adapters],
626
- props: [...binding.props],
627
- }
628
- }
629
-
630
- function uniquePropsName(
631
- binding: BioTemplateComponentBinding,
632
- usedNames: Map<string, number>
633
- ): string {
634
- const base = toCamelIdentifier(`${binding.template_id} ${binding.component} props`)
635
- const count = usedNames.get(base) ?? 0
636
- usedNames.set(base, count + 1)
637
- return count === 0 ? base : `${base}${count + 1}`
638
- }
639
-
640
- function toCamelIdentifier(value: string): string {
641
- const words = value
642
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
643
- .split(/[^A-Za-z0-9]+/)
644
- .filter(Boolean)
645
-
646
- if (words.length === 0) return 'componentProps'
647
-
648
- return words
649
- .map((word, index) => {
650
- const lower = word.toLowerCase()
651
- return index === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1)
652
- })
653
- .join('')
654
- }
655
-
656
- function toVueSfc(
657
- imports: BioTemplateComponentImport[],
658
- setupLines: string[],
659
- template: string,
660
- includeTargetTypeImport: boolean
661
- ): string {
662
- const importLines = [
663
- ...imports.map(item => item.statement),
664
- "import { toBioTemplateComponentProps } from '@morscherlab/mint-sdk/templates'",
665
- ...(includeTargetTypeImport
666
- ? ["import type { BioTemplateEnvelope, TemplateCollectionEnvelope } from '@morscherlab/mint-sdk/templates'"]
667
- : []),
668
- ]
669
- const templateLines = template
670
- ? template.split('\n').map(line => ` ${line}`).join('\n')
671
- : ''
672
-
673
- return [
674
- '<script setup lang="ts">',
675
- ...importLines,
676
- '',
677
- ...setupLines,
678
- '</script>',
679
- '',
680
- '<template>',
681
- templateLines,
682
- '</template>',
683
- ].join('\n')
684
- }
685
-
686
- function isTemplateEnvelope(value: unknown): value is BioTemplateEnvelope<unknown> {
687
- return isRecord(value) && typeof value.template_id === 'string' && 'data' in value
688
- }
689
-
690
- function collectionPresetName(value: unknown): string | undefined {
691
- if (!isRecord(value) || !isRecord(value.metadata)) return undefined
692
- return typeof value.metadata.preset === 'string' ? value.metadata.preset : undefined
693
- }
694
-
695
- function collectionPackName(value: unknown): string | undefined {
696
- if (!isRecord(value) || !isRecord(value.metadata)) return undefined
697
- return typeof value.metadata.pack === 'string' ? value.metadata.pack : undefined
698
- }
699
-
700
- function isRecord(value: unknown): value is Record<string, unknown> {
701
- return typeof value === 'object' && value !== null
702
- }
@@ -0,0 +1,42 @@
1
+ import {
2
+ toDoseConditions,
3
+ toDoseLayoutState,
4
+ } from './adapters'
5
+ import {
6
+ activePlateFromState,
7
+ sampleColorsFromPlateState,
8
+ } from './componentPlateHelpers'
9
+ import { propsBinding } from './componentPropsFactory'
10
+ import type { BioTemplateComponentPropsBinding } from './componentBindings'
11
+ import type { DoseResponseTemplate } from './types'
12
+
13
+ export function doseResponseProps(template: DoseResponseTemplate): BioTemplateComponentPropsBinding[] {
14
+ const conditions = toDoseConditions(template)
15
+ const layout = toDoseLayoutState(template)
16
+ const targetWells = layout ? Object.keys(activePlateFromState(layout).wells) : []
17
+ const props = [
18
+ propsBinding('dose-response', 'DoseCalculator', {
19
+ mode: 'serial',
20
+ targetWells,
21
+ disabled: conditions.length === 0,
22
+ }),
23
+ ]
24
+
25
+ if (layout) {
26
+ const plate = activePlateFromState(layout)
27
+ props.push(propsBinding('dose-response', 'WellPlate', {
28
+ format: plate.format,
29
+ wells: plate.wells,
30
+ sampleColors: sampleColorsFromPlateState(layout),
31
+ legendItems: conditions.map(condition => ({
32
+ type: condition.label,
33
+ label: condition.label,
34
+ color: condition.color,
35
+ })),
36
+ showLegend: true,
37
+ showSampleTypeIndicator: true,
38
+ }))
39
+ }
40
+
41
+ return props
42
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ toAssayMatrixSampleOptions,
3
+ toInstrumentRunScheduleEvents,
4
+ toReagentListItems,
5
+ toSampleOptions,
6
+ toTemplateDataFrame,
7
+ } from './adapters'
8
+ import { propsBinding } from './componentPropsFactory'
9
+ import type { BioTemplateComponentPropsBinding } from './componentBindings'
10
+ import type {
11
+ AssayMatrixTemplate,
12
+ DataFrameTemplate,
13
+ InstrumentRunTemplate,
14
+ ProtocolStepsTemplate,
15
+ ReagentListTemplate,
16
+ SampleSheetTemplate,
17
+ TemplateId,
18
+ TimeCourseTemplate,
19
+ } from './types'
20
+
21
+ export function dataFrameProps(template: DataFrameTemplate): BioTemplateComponentPropsBinding {
22
+ const frame = toTemplateDataFrame(template)
23
+ return propsBinding(template.template_id as TemplateId, 'DataFrame', {
24
+ ...frame,
25
+ searchable: true,
26
+ sortable: true,
27
+ size: 'sm',
28
+ })
29
+ }
30
+
31
+ export function sampleSelectorProps(template: SampleSheetTemplate): BioTemplateComponentPropsBinding {
32
+ const options = toSampleOptions(template)
33
+ return propsBinding('sample-sheet', 'SampleSelector', {
34
+ samples: options.map(option => option.label),
35
+ modelValue: [],
36
+ })
37
+ }
38
+
39
+ export function assayMatrixSampleSelectorProps(template: AssayMatrixTemplate): BioTemplateComponentPropsBinding {
40
+ const options = toAssayMatrixSampleOptions(template)
41
+ return propsBinding('assay-matrix', 'SampleSelector', {
42
+ samples: options.map(option => option.label),
43
+ modelValue: [],
44
+ })
45
+ }
46
+
47
+ export function timelineProps(
48
+ template: TimeCourseTemplate | ProtocolStepsTemplate | InstrumentRunTemplate,
49
+ steps: unknown[],
50
+ editable = false
51
+ ): BioTemplateComponentPropsBinding {
52
+ return propsBinding(template.template_id as TemplateId, 'ExperimentTimeline', {
53
+ modelValue: steps,
54
+ orientation: 'vertical',
55
+ editable,
56
+ })
57
+ }
58
+
59
+ export function scheduleCalendarProps(template: InstrumentRunTemplate): BioTemplateComponentPropsBinding {
60
+ const events = toInstrumentRunScheduleEvents(template)
61
+ return propsBinding('instrument-run', 'ScheduleCalendar', {
62
+ modelValue: events[0]?.start,
63
+ events,
64
+ view: 'day',
65
+ readonly: true,
66
+ showNavigation: false,
67
+ showViewToggle: false,
68
+ })
69
+ }
70
+
71
+ export function reagentListProps(template: ReagentListTemplate): BioTemplateComponentPropsBinding {
72
+ return propsBinding('reagent-list', 'ReagentList', {
73
+ modelValue: toReagentListItems(template),
74
+ searchable: true,
75
+ sortable: true,
76
+ })
77
+ }
@@ -0,0 +1,29 @@
1
+ import type {
2
+ PlateMapEditorState,
3
+ WellLegendItem,
4
+ } from '../types'
5
+
6
+ export function activePlateFromState(state: PlateMapEditorState) {
7
+ return state.plates.find(plate => plate.id === state.activePlateId) ?? state.plates[0]
8
+ }
9
+
10
+ export function sampleColorsFromPlateState(state: PlateMapEditorState): Record<string, string> {
11
+ return Object.fromEntries(
12
+ state.samples
13
+ .filter(sample => sample.color)
14
+ .map(sample => [sample.id, sample.color as string])
15
+ )
16
+ }
17
+
18
+ export function legendItemsFromPlateState(state: PlateMapEditorState): WellLegendItem[] {
19
+ return state.samples.map((sample, index) => ({
20
+ type: sample.id,
21
+ label: sample.name,
22
+ color: sample.color ?? colorForIndex(index),
23
+ }))
24
+ }
25
+
26
+ export function colorForIndex(index: number): string {
27
+ const colors = ['#3B82F6', '#10B981', '#EF4444', '#F59E0B', '#8B5CF6', '#F97316', '#06B6D4', '#14B8A6']
28
+ return colors[index % colors.length]
29
+ }
@@ -0,0 +1,32 @@
1
+ import {
2
+ toPlateMapEditorState,
3
+ toWellPlateWells,
4
+ } from './adapters'
5
+ import {
6
+ activePlateFromState,
7
+ legendItemsFromPlateState,
8
+ sampleColorsFromPlateState,
9
+ } from './componentPlateHelpers'
10
+ import { propsBinding } from './componentPropsFactory'
11
+ import type { BioTemplateComponentPropsBinding } from './componentBindings'
12
+ import type { PlateMapTemplate } from './types'
13
+
14
+ export function plateMapProps(template: PlateMapTemplate): BioTemplateComponentPropsBinding[] {
15
+ const state = toPlateMapEditorState(template)
16
+ const plate = activePlateFromState(state)
17
+ return [
18
+ propsBinding('plate-map', 'PlateMapEditor', {
19
+ modelValue: state,
20
+ format: plate.format,
21
+ samples: state.samples,
22
+ }),
23
+ propsBinding('plate-map', 'WellPlate', {
24
+ format: plate.format,
25
+ wells: toWellPlateWells(template),
26
+ sampleColors: sampleColorsFromPlateState(state),
27
+ legendItems: legendItemsFromPlateState(state),
28
+ showLegend: true,
29
+ showSampleTypeIndicator: true,
30
+ }),
31
+ ]
32
+ }