@morscherlab/mint-sdk 1.0.0-beta.3 → 1.0.0-beta.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.
Files changed (181) hide show
  1. package/README.md +9 -2
  2. package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
  3. package/dist/__tests__/composables/useApi.test.d.ts +1 -0
  4. package/dist/components/AppContainer.vue.d.ts +1 -1
  5. package/dist/components/AppLayout.vue.d.ts +20 -1
  6. package/dist/components/AppSidebar.vue.d.ts +57 -5
  7. package/dist/components/AppTopBar.vue.d.ts +7 -25
  8. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +3 -1
  9. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -0
  10. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +5 -0
  11. package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
  12. package/dist/components/ControlWorkspaceView.vue.d.ts +24 -7
  13. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
  14. package/dist/components/ExperimentTimeline.vue.d.ts +1 -1
  15. package/dist/components/FormBuilder.vue.d.ts +9 -9
  16. package/dist/components/PlateMapEditor.vue.d.ts +1 -1
  17. package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
  18. package/dist/components/SettingsModal.vue.d.ts +1 -1
  19. package/dist/components/WellPlate.vue.d.ts +2 -2
  20. package/dist/components/index.d.ts +3 -12
  21. package/dist/components/index.js +3 -3
  22. package/dist/components/{AppPageSelector.vue.d.ts → internal/AppTopBarPageSelectorInternal.vue.d.ts} +1 -1
  23. package/dist/components/{AppPillNav.vue.d.ts → internal/AppTopBarPillNavInternal.vue.d.ts} +3 -1
  24. package/dist/components/{CalendarGridPanel.vue.d.ts → internal/CalendarGridPanelInternal.vue.d.ts} +1 -1
  25. package/dist/components/internal/FormSectionRenderer.vue.d.ts +4 -4
  26. package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
  27. package/dist/{components-D_Sr0adg.js → components-DihbSJjU.js} +5932 -5408
  28. package/dist/components-DihbSJjU.js.map +1 -0
  29. package/dist/composables/experiment-utils.d.ts +8 -0
  30. package/dist/composables/index.d.ts +5 -7
  31. package/dist/composables/index.js +4 -4
  32. package/dist/composables/useAppExperiment.d.ts +31 -2
  33. package/dist/composables/useBioTemplateComponents.d.ts +5 -3
  34. package/dist/composables/useBioTemplatePackWorkspace.d.ts +3 -2
  35. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +6 -5
  36. package/dist/composables/useBioTemplateWorkspace.d.ts +5 -4
  37. package/dist/composables/useControlSchema.d.ts +43 -21
  38. package/dist/composables/usePluginClient.d.ts +5 -2
  39. package/dist/{composables-C3dpXQN5.js → composables-BcgZ6diz.js} +40 -28
  40. package/dist/composables-BcgZ6diz.js.map +1 -0
  41. package/dist/index.d.ts +5 -12
  42. package/dist/index.js +5 -5
  43. package/dist/install.js +2 -2
  44. package/dist/styles.css +5637 -5663
  45. package/dist/templates/adapters.d.ts +7 -1
  46. package/dist/templates/catalog.d.ts +5 -5
  47. package/dist/templates/componentBindings.d.ts +13 -0
  48. package/dist/templates/index.d.ts +5 -5
  49. package/dist/templates/index.js +2 -2
  50. package/dist/templates/presets.d.ts +4 -4
  51. package/dist/templates/types.d.ts +4 -1
  52. package/dist/{templates-50NPjaxL.js → templates-Cyt0Suwf.js} +322 -73
  53. package/dist/templates-Cyt0Suwf.js.map +1 -0
  54. package/dist/types/components.d.ts +6 -25
  55. package/dist/types/index.d.ts +1 -1
  56. package/dist/{useScheduleDrag-D4oWdh41.js → useExperimentData-CM6Y0u5L.js} +400 -357
  57. package/dist/useExperimentData-CM6Y0u5L.js.map +1 -0
  58. package/package.json +1 -1
  59. package/src/__tests__/components/ActionItem.test.ts +6 -6
  60. package/src/__tests__/components/AppLayout.test.ts +44 -0
  61. package/src/__tests__/components/AppSidebar.test.ts +130 -2
  62. package/src/__tests__/components/AppToastContainer.test.ts +0 -11
  63. package/src/__tests__/components/AppTopBar.test.ts +189 -120
  64. package/src/__tests__/components/{AppPageSelector.test.ts → AppTopBarPageSelector.test.ts} +8 -8
  65. package/src/__tests__/components/{AppPillNav.test.ts → AppTopBarPillNav.test.ts} +53 -6
  66. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +7 -1
  67. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +32 -1
  68. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +48 -1
  69. package/src/__tests__/components/BioTemplateRenderer.test.ts +25 -0
  70. package/src/__tests__/components/CalendarGridPanel.test.ts +3 -3
  71. package/src/__tests__/components/ComponentBindingRenderer.test.ts +278 -0
  72. package/src/__tests__/components/ControlWorkspaceView.test.ts +134 -63
  73. package/src/__tests__/components/DateTimePicker.test.ts +2 -2
  74. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
  75. package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
  76. package/src/__tests__/composables/experiment-utils.test.ts +30 -0
  77. package/src/__tests__/composables/useApi.test.ts +30 -0
  78. package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
  79. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +7 -4
  80. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +7 -7
  81. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +6 -1
  82. package/src/__tests__/composables/useControlSchema.test.ts +151 -37
  83. package/src/__tests__/composables/usePluginClient.test.ts +99 -2
  84. package/src/__tests__/docs/frontendDocsCatalog.test.ts +120 -25
  85. package/src/__tests__/templates/templates.test.ts +56 -0
  86. package/src/components/AppAvatarMenu.vue +3 -3
  87. package/src/components/AppLayout.story.vue +39 -0
  88. package/src/components/AppLayout.vue +83 -2
  89. package/src/components/AppPluginSwitcher.vue +5 -5
  90. package/src/components/AppSidebar.story.vue +113 -5
  91. package/src/components/AppSidebar.vue +147 -27
  92. package/src/components/AppTopBar.story.vue +2 -5
  93. package/src/components/AppTopBar.vue +35 -425
  94. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +2 -2
  95. package/src/components/BioTemplateExperimentWorkspaceView.vue +6 -0
  96. package/src/components/BioTemplatePackWorkspaceView.story.vue +4 -4
  97. package/src/components/BioTemplatePackWorkspaceView.vue +1 -0
  98. package/src/components/BioTemplatePresetWorkspaceView.story.vue +14 -2
  99. package/src/components/BioTemplatePresetWorkspaceView.vue +12 -3
  100. package/src/components/BioTemplateRenderer.story.vue +2 -2
  101. package/src/components/BioTemplateRenderer.vue +15 -227
  102. package/src/components/ComponentBindingRenderer.story.vue +87 -0
  103. package/src/components/ComponentBindingRenderer.vue +317 -0
  104. package/src/components/ControlWorkspaceView.story.vue +20 -9
  105. package/src/components/ControlWorkspaceView.vue +43 -12
  106. package/src/components/DatePicker.vue +2 -2
  107. package/src/components/DateTimePicker.vue +2 -2
  108. package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
  109. package/src/components/DoseDesignWorkspaceView.vue +255 -0
  110. package/src/components/ExperimentPopover.story.vue +2 -2
  111. package/src/components/ExperimentPopover.vue +2 -6
  112. package/src/components/ExperimentSelectorModal.vue +6 -5
  113. package/src/components/FormBuilder.story.vue +190 -0
  114. package/src/components/PluginWorkspaceView.story.vue +334 -0
  115. package/src/components/PluginWorkspaceView.vue +708 -0
  116. package/src/components/SettingsModal.story.vue +87 -0
  117. package/src/components/WellPlate.vue +2 -2
  118. package/src/components/index.ts +3 -12
  119. package/src/components/{AppPageSelector.vue → internal/AppTopBarPageSelectorInternal.vue} +9 -9
  120. package/src/components/internal/AppTopBarPillNavInternal.vue +194 -0
  121. package/src/components/{CalendarGridPanel.vue → internal/CalendarGridPanelInternal.vue} +1 -1
  122. package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +3 -3
  123. package/src/composables/experiment-utils.ts +26 -0
  124. package/src/composables/index.ts +21 -7
  125. package/src/composables/useApi.ts +9 -2
  126. package/src/composables/useAppExperiment.ts +85 -13
  127. package/src/composables/useBioTemplateComponents.ts +12 -0
  128. package/src/composables/useBioTemplatePackWorkspace.ts +6 -2
  129. package/src/composables/useBioTemplatePresetWorkspace.ts +10 -21
  130. package/src/composables/useBioTemplateWorkspace.ts +6 -4
  131. package/src/composables/useControlSchema.ts +157 -69
  132. package/src/composables/usePluginClient.ts +50 -9
  133. package/src/index.ts +6 -563
  134. package/src/styles/components/app-layout.css +82 -0
  135. package/src/styles/components/app-page-selector.css +1 -1
  136. package/src/styles/components/app-pill-nav.css +71 -1
  137. package/src/styles/components/app-sidebar.css +119 -0
  138. package/src/styles/components/app-top-bar.css +0 -235
  139. package/src/styles/components/experiment-popover.css +2 -2
  140. package/src/styles/index.css +0 -1
  141. package/src/templates/adapters.ts +193 -0
  142. package/src/templates/catalog.ts +5 -5
  143. package/src/templates/componentBindings.ts +90 -3
  144. package/src/templates/index.ts +10 -0
  145. package/src/templates/packs.ts +10 -1
  146. package/src/templates/presets.ts +14 -4
  147. package/src/templates/types.ts +4 -0
  148. package/src/types/components.ts +6 -31
  149. package/src/types/index.ts +2 -6
  150. package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
  151. package/dist/components/FormFieldRenderer.vue.d.ts +0 -28
  152. package/dist/components/FormSection.vue.d.ts +0 -30
  153. package/dist/components/GroupingModal.vue.d.ts +0 -12
  154. package/dist/components/SettingsButton.vue.d.ts +0 -30
  155. package/dist/components/ToastNotification.vue.d.ts +0 -2
  156. package/dist/components-D_Sr0adg.js.map +0 -1
  157. package/dist/composables/usePluginApi.d.ts +0 -22
  158. package/dist/composables-C3dpXQN5.js.map +0 -1
  159. package/dist/templates-50NPjaxL.js.map +0 -1
  160. package/dist/useScheduleDrag-D4oWdh41.js.map +0 -1
  161. package/src/__tests__/components/FormCompatibility.test.ts +0 -94
  162. package/src/__tests__/components/GroupingModal.test.ts +0 -73
  163. package/src/__tests__/components/SettingsButton.test.ts +0 -44
  164. package/src/__tests__/composables/usePluginApi.test.ts +0 -81
  165. package/src/components/AppPillNav.vue +0 -71
  166. package/src/components/FormFieldRenderer.vue +0 -35
  167. package/src/components/FormSection.vue +0 -37
  168. package/src/components/GroupingModal.story.vue +0 -52
  169. package/src/components/GroupingModal.vue +0 -61
  170. package/src/components/SettingsButton.story.vue +0 -58
  171. package/src/components/SettingsButton.vue +0 -64
  172. package/src/components/ToastNotification.vue +0 -9
  173. package/src/composables/usePluginApi.ts +0 -32
  174. package/src/styles/components/settings-button.css +0 -31
  175. /package/dist/__tests__/components/{AppPageSelector.test.d.ts → AppTopBarPageSelector.test.d.ts} +0 -0
  176. /package/dist/__tests__/components/{AppPillNav.test.d.ts → AppTopBarPillNav.test.d.ts} +0 -0
  177. /package/dist/__tests__/components/{FormCompatibility.test.d.ts → ComponentBindingRenderer.test.d.ts} +0 -0
  178. /package/dist/__tests__/components/{GroupingModal.test.d.ts → DoseDesignWorkspaceView.test.d.ts} +0 -0
  179. /package/dist/__tests__/components/{SettingsButton.test.d.ts → PluginWorkspaceView.test.d.ts} +0 -0
  180. /package/dist/components/{ActionItem.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +0 -0
  181. /package/src/components/{ActionItem.vue → internal/ActionItemInternal.vue} +0 -0
@@ -4,14 +4,28 @@ import {
4
4
  readonly,
5
5
  provide,
6
6
  toValue,
7
+ watch,
7
8
  onScopeDispose,
8
9
  type Ref,
9
10
  type ComputedRef,
10
11
  type InjectionKey,
11
12
  } from 'vue'
12
13
  import type { ExperimentSummary, ExperimentStatus } from '../types'
14
+ import { resolveExperimentCode } from './experiment-utils'
15
+
16
+ export type AppExperimentRecord = Pick<ExperimentSummary, 'id' | 'name' | 'status' | 'experiment_code'>
17
+
18
+ export type AppExperimentSource =
19
+ | AppExperimentRecord
20
+ | null
21
+ | undefined
22
+ | Ref<AppExperimentRecord | null | undefined>
23
+ | ComputedRef<AppExperimentRecord | null | undefined>
24
+ | (() => AppExperimentRecord | null | undefined)
13
25
 
14
26
  export interface UseAppExperimentOptions {
27
+ /** Current experiment source to mirror into the app shell. Accepts a value, ref, computed, or getter. */
28
+ experiment?: AppExperimentSource
15
29
  onSelect?: (experiment: ExperimentSummary) => void | Promise<void>
16
30
  onSave?: () => string | null | Promise<string | null>
17
31
  onDetach?: () => void
@@ -19,12 +33,37 @@ export interface UseAppExperimentOptions {
19
33
  saveDisabledMessage?: string | Ref<string | undefined> | ComputedRef<string | undefined>
20
34
  }
21
35
 
36
+ export interface AppExperimentPopoverBinding {
37
+ experimentName?: string
38
+ experimentCode?: string
39
+ experimentStatus?: ExperimentStatus
40
+ showSave: boolean
41
+ showDetach: boolean
42
+ saveDisabled: boolean
43
+ saveDisabledMessage?: string
44
+ saveLoading: boolean
45
+ saveSuccessMessage?: string
46
+ }
47
+
48
+ export interface AppExperimentSelectorModalBinding {
49
+ modelValue: boolean
50
+ currentExperimentId: number | null
51
+ }
52
+
22
53
  export interface UseAppExperimentReturn {
23
- set: (experiment: Pick<ExperimentSummary, 'id' | 'name' | 'status' | 'experiment_code'>) => void
54
+ set: (experiment: AppExperimentRecord) => void
24
55
  clear: () => void
25
56
  experimentName: Readonly<Ref<string | undefined>>
26
57
  experimentCode: Readonly<Ref<string | undefined>>
58
+ experimentStatus: Readonly<Ref<ExperimentStatus | undefined>>
27
59
  experimentId: Readonly<Ref<number | null>>
60
+ popover: ComputedRef<AppExperimentPopoverBinding>
61
+ selectorModal: ComputedRef<AppExperimentSelectorModalBinding>
62
+ openModal: () => void
63
+ closeModal: () => void
64
+ handleSelect: (experiment: ExperimentSummary) => void
65
+ handleSave: () => Promise<void>
66
+ handleDetach: () => void
28
67
  }
29
68
 
30
69
  export interface AppExperimentState {
@@ -40,6 +79,8 @@ export interface AppExperimentState {
40
79
  closeModal: () => void
41
80
  saveDisabled: ComputedRef<boolean>
42
81
  saveDisabledMessage: ComputedRef<string | undefined>
82
+ popover: ComputedRef<AppExperimentPopoverBinding>
83
+ selectorModal: ComputedRef<AppExperimentSelectorModalBinding>
43
84
  openModal: () => void
44
85
  handleSelect: (experiment: ExperimentSummary) => void
45
86
  handleSave: () => Promise<void>
@@ -48,7 +89,7 @@ export interface AppExperimentState {
48
89
 
49
90
  export const APP_EXPERIMENT_KEY: InjectionKey<AppExperimentState> = Symbol('app-experiment')
50
91
 
51
- /** Manages the active experiment selection, save flow, and detach action for a plugin's app shell. */
92
+ /** Manages the current experiment selection, save flow, and detach action for a plugin's AppTopBar app shell. */
52
93
  export function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppExperimentReturn {
53
94
  const experimentName = ref<string | undefined>()
54
95
  const experimentCode = ref<string | undefined>()
@@ -64,19 +105,26 @@ export function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppE
64
105
  const showDetach = computed(() => experimentId.value !== null)
65
106
  const saveDisabled = computed(() => toValue(options.saveDisabled) ?? false)
66
107
  const saveDisabledMessage = computed(() => toValue(options.saveDisabledMessage))
67
-
68
- function set(experiment: Pick<ExperimentSummary, 'id' | 'name' | 'status' | 'experiment_code'>) {
108
+ const popover = computed<AppExperimentPopoverBinding>(() => ({
109
+ experimentName: experimentName.value,
110
+ experimentCode: experimentCode.value,
111
+ experimentStatus: experimentStatus.value,
112
+ showSave: showSave.value,
113
+ showDetach: showDetach.value,
114
+ saveDisabled: saveDisabled.value,
115
+ saveDisabledMessage: saveDisabledMessage.value,
116
+ saveLoading: saveLoading.value,
117
+ saveSuccessMessage: saveSuccessMessage.value,
118
+ }))
119
+ const selectorModal = computed<AppExperimentSelectorModalBinding>(() => ({
120
+ modelValue: showModal.value,
121
+ currentExperimentId: experimentId.value,
122
+ }))
123
+
124
+ function set(experiment: AppExperimentRecord) {
69
125
  experimentId.value = experiment.id
70
126
  experimentName.value = experiment.name
71
- // Fallback: if no explicit experiment_code, derive `EXP-${id}` so the
72
- // topbar always has a compact identifier to show instead of the long
73
- // name. Matches the `EXP-${id}` format used elsewhere (e.g., queue
74
- // cards in mint-ms-planner). Callers with the real code should pass it
75
- // via `experiment_code` to keep the topbar chip in sync with the
76
- // formal code shown in the popover panel.
77
- experimentCode.value = experiment.experiment_code ?? (
78
- experiment.id != null ? `EXP-${experiment.id}` : undefined
79
- )
127
+ experimentCode.value = resolveExperimentCode(experiment)
80
128
  experimentStatus.value = experiment.status
81
129
  }
82
130
 
@@ -87,6 +135,20 @@ export function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppE
87
135
  experimentStatus.value = undefined
88
136
  }
89
137
 
138
+ if (options.experiment !== undefined) {
139
+ watch(
140
+ () => toValue(options.experiment),
141
+ (experiment) => {
142
+ if (experiment) {
143
+ set(experiment)
144
+ } else {
145
+ clear()
146
+ }
147
+ },
148
+ { immediate: true },
149
+ )
150
+ }
151
+
90
152
  function openModal() {
91
153
  showModal.value = true
92
154
  }
@@ -140,6 +202,8 @@ export function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppE
140
202
  showDetach,
141
203
  saveDisabled,
142
204
  saveDisabledMessage,
205
+ popover,
206
+ selectorModal,
143
207
  openModal,
144
208
  closeModal,
145
209
  handleSelect,
@@ -154,6 +218,14 @@ export function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppE
154
218
  clear,
155
219
  experimentName: readonly(experimentName),
156
220
  experimentCode: readonly(experimentCode),
221
+ experimentStatus: readonly(experimentStatus),
157
222
  experimentId: readonly(experimentId),
223
+ popover,
224
+ selectorModal,
225
+ openModal,
226
+ closeModal,
227
+ handleSelect,
228
+ handleSave,
229
+ handleDetach,
158
230
  }
159
231
  }
@@ -2,17 +2,21 @@ import {
2
2
  getBioTemplateComponentBindings,
3
3
  getBioTemplateComponentProps as getTemplateComponentProps,
4
4
  toBioTemplateComponentImports,
5
+ toBioTemplateComponentBindings,
6
+ toBioTemplateComponentBindingsById,
5
7
  toBioTemplateComponentProps,
6
8
  toBioTemplateComponentPropsByComponent as toTemplateComponentPropsByComponent,
7
9
  toBioTemplateComponentPropsById,
8
10
  toBioTemplateComponentSnippets,
9
11
  toBioTemplateComponentUsage,
10
12
  type BioTemplateComponentBinding,
13
+ type BioTemplateComponentBindingsById,
11
14
  type BioTemplateComponentImport,
12
15
  type BioTemplateComponentPropsByComponent,
13
16
  type BioTemplateComponentPropsBinding,
14
17
  type BioTemplateComponentPropsById,
15
18
  type BioTemplateComponentPropsLookupOptions,
19
+ type BioTemplateResolvedComponentBinding,
16
20
  type BioTemplateComponentSnippet,
17
21
  type BioTemplateComponentTarget,
18
22
  type BioTemplateComponentUsage,
@@ -24,6 +28,8 @@ import type {
24
28
 
25
29
  export {
26
30
  getBioTemplateComponentBindings,
31
+ toBioTemplateComponentBindings,
32
+ toBioTemplateComponentBindingsById,
27
33
  toBioTemplateComponentImports,
28
34
  toBioTemplateComponentProps,
29
35
  toBioTemplateComponentPropsById,
@@ -33,11 +39,13 @@ export {
33
39
 
34
40
  export type {
35
41
  BioTemplateComponentBinding,
42
+ BioTemplateComponentBindingsById,
36
43
  BioTemplateComponentImport,
37
44
  BioTemplateComponentPropsByComponent,
38
45
  BioTemplateComponentPropsBinding,
39
46
  BioTemplateComponentPropsById,
40
47
  BioTemplateComponentPropsLookupOptions,
48
+ BioTemplateResolvedComponentBinding,
41
49
  BioTemplateComponentSnippet,
42
50
  BioTemplateComponentTarget,
43
51
  BioTemplateComponentUsage,
@@ -46,6 +54,8 @@ export type {
46
54
  export interface UseBioTemplateComponentsReturn {
47
55
  bindings: BioTemplateComponentBinding[]
48
56
  imports: BioTemplateComponentImport[]
57
+ componentBindings: BioTemplateResolvedComponentBinding[]
58
+ componentBindingsById: BioTemplateComponentBindingsById
49
59
  componentProps: BioTemplateComponentPropsBinding[]
50
60
  componentPropsById: BioTemplateComponentPropsById
51
61
  componentPropsByComponent: BioTemplateComponentPropsByComponent
@@ -80,6 +90,8 @@ export function useBioTemplateComponents(
80
90
  return {
81
91
  bindings: getBioTemplateComponentBindings(target),
82
92
  imports: toBioTemplateComponentImports(target),
93
+ componentBindings: typeof target === 'string' ? [] : toBioTemplateComponentBindings(target),
94
+ componentBindingsById: typeof target === 'string' ? {} : toBioTemplateComponentBindingsById(target),
83
95
  componentProps: typeof target === 'string' ? [] : toBioTemplateComponentProps(target),
84
96
  componentPropsById: typeof target === 'string' ? {} : toBioTemplateComponentPropsById(target),
85
97
  componentPropsByComponent: typeof target === 'string' ? {} : toBioTemplateComponentPropsByComponent(target),
@@ -29,6 +29,7 @@ import {
29
29
  } from './useBioTemplateWorkspace'
30
30
  import type {
31
31
  BioTemplateComponentBinding,
32
+ BioTemplateComponentBindingsById,
32
33
  BioTemplateComponentImport,
33
34
  BioTemplateComponentPropsByComponent,
34
35
  BioTemplateComponentPropsBinding,
@@ -56,11 +57,12 @@ export interface UseBioTemplatePackWorkspaceReturn {
56
57
  workspace: ComputedRef<UseBioTemplateWorkspaceReturn>
57
58
  form: ComputedRef<UseBioTemplateWorkspaceReturn['form']>
58
59
  sidebar: ComputedRef<UseBioTemplateWorkspaceReturn['sidebar']>
59
- topBar: ComputedRef<UseBioTemplateWorkspaceReturn['topBar']>
60
+ topBar: ComputedRef<UseBioTemplateWorkspaceReturn['topBar']['value']>
60
61
  pillNav: ComputedRef<UseBioTemplateWorkspaceReturn['pillNav']>
61
62
  topBarSettings: ComputedRef<UseBioTemplateWorkspaceReturn['topBarSettings']>
62
63
  bindings: ComputedRef<BioTemplateWorkspaceBindings>
63
64
  componentBindings: ComputedRef<BioTemplateComponentBinding[]>
65
+ componentBindingsById: ComputedRef<BioTemplateComponentBindingsById>
64
66
  componentImports: ComputedRef<BioTemplateComponentImport[]>
65
67
  componentProps: ComputedRef<BioTemplateComponentPropsBinding[]>
66
68
  componentPropsById: ComputedRef<BioTemplateComponentPropsById>
@@ -106,11 +108,12 @@ export function useBioTemplatePackWorkspace(
106
108
  const renderer = computed<BioTemplateRendererBinding>(() => ({ target: collection.value }))
107
109
  const form = computed(() => workspace.value.form)
108
110
  const sidebar = computed(() => workspace.value.sidebar)
109
- const topBar = computed(() => workspace.value.topBar)
111
+ const topBar = computed(() => workspace.value.topBar.value)
110
112
  const pillNav = computed(() => workspace.value.pillNav)
111
113
  const topBarSettings = computed(() => workspace.value.topBarSettings)
112
114
  const bindings = computed(() => workspace.value.bindings)
113
115
  const componentBindings = computed(() => workspace.value.componentBindings)
116
+ const componentBindingsById = computed(() => workspace.value.componentBindingsById)
114
117
  const componentImports = computed(() => workspace.value.componentImports)
115
118
  const componentProps = computed(() => workspace.value.componentProps)
116
119
  const componentPropsById = computed(() => workspace.value.componentPropsById)
@@ -163,6 +166,7 @@ export function useBioTemplatePackWorkspace(
163
166
  topBarSettings,
164
167
  bindings,
165
168
  componentBindings,
169
+ componentBindingsById,
166
170
  componentImports,
167
171
  componentProps,
168
172
  componentPropsById,
@@ -16,8 +16,6 @@ import {
16
16
  type TemplatePresetId,
17
17
  } from '../templates'
18
18
  import type {
19
- ControlWorkspaceAppTopBarPillBinding,
20
- ControlWorkspaceAppTopBarTabsBinding,
21
19
  ControlWorkspaceOptions,
22
20
  ControlWorkspaceFormBinding,
23
21
  ControlWorkspacePillNavBinding,
@@ -38,6 +36,7 @@ import {
38
36
  } from './useBioTemplateWorkspace'
39
37
  import type {
40
38
  BioTemplateComponentBinding,
39
+ BioTemplateComponentBindingsById,
41
40
  BioTemplateComponentImport,
42
41
  BioTemplateComponentPropsByComponent,
43
42
  BioTemplateComponentPropsBinding,
@@ -76,13 +75,14 @@ export interface UseBioTemplatePresetWorkspaceReturn {
76
75
  activeControlView: Ref<string>
77
76
  form: ControlWorkspaceFormBinding
78
77
  sidebar: ControlWorkspaceSidebarBinding
79
- topBar: ControlWorkspaceTopBarBinding
78
+ topBar: ComputedRef<ControlWorkspaceTopBarBinding>
80
79
  pillNav: ControlWorkspacePillNavBinding
81
80
  topBarSettings: ControlWorkspaceTopBarSettingsBinding
82
81
  bindings: BioTemplatePresetWorkspaceBindings
83
82
  renderer: ComputedRef<BioTemplateRendererBinding>
84
83
  workspace: ComputedRef<UseBioTemplateWorkspaceReturn>
85
84
  componentBindings: ComputedRef<BioTemplateComponentBinding[]>
85
+ componentBindingsById: ComputedRef<BioTemplateComponentBindingsById>
86
86
  componentImports: ComputedRef<BioTemplateComponentImport[]>
87
87
  componentProps: ComputedRef<BioTemplateComponentPropsBinding[]>
88
88
  componentPropsById: ComputedRef<BioTemplateComponentPropsById>
@@ -103,11 +103,11 @@ export interface BioTemplatePresetWorkspaceBindings {
103
103
  renderer: ComputedRef<BioTemplateRendererBinding>
104
104
  form: ControlWorkspaceFormBinding
105
105
  sidebar: ControlWorkspaceSidebarBinding
106
- topBar: ComputedRef<ControlWorkspaceAppTopBarPillBinding>
107
- topBarTabs: ComputedRef<ControlWorkspaceAppTopBarTabsBinding>
106
+ topBar: ComputedRef<ControlWorkspaceTopBarBinding>
108
107
  topBarSettings: ControlWorkspaceTopBarSettingsBinding
109
108
  pillNav: ControlWorkspacePillNavBinding
110
109
  componentBindings: ComputedRef<BioTemplateComponentBinding[]>
110
+ componentBindingsById: ComputedRef<BioTemplateComponentBindingsById>
111
111
  componentProps: ComputedRef<BioTemplateComponentPropsBinding[]>
112
112
  componentPropsById: ComputedRef<BioTemplateComponentPropsById>
113
113
  componentPropsByComponent: ComputedRef<BioTemplateComponentPropsByComponent>
@@ -139,6 +139,7 @@ export function useBioTemplatePresetWorkspace(
139
139
  const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions))
140
140
  const renderer = computed<BioTemplateRendererBinding>(() => ({ target: collection.value }))
141
141
  const componentBindings = computed(() => workspace.value.componentBindings)
142
+ const componentBindingsById = computed(() => workspace.value.componentBindingsById)
142
143
  const componentImports = computed(() => workspace.value.componentImports)
143
144
  const componentProps = computed(() => workspace.value.componentProps)
144
145
  const componentPropsById = computed(() => workspace.value.componentPropsById)
@@ -158,11 +159,6 @@ export function useBioTemplatePresetWorkspace(
158
159
  values: controlValues.value,
159
160
  'onUpdate:values': setControlValues,
160
161
  }) as ControlWorkspaceSidebarBinding
161
- const topBar = reactive({
162
- tabs: controls.topBarTabs,
163
- currentTabId: activeControlView.value,
164
- onTabSelect: (tab: { id: string }) => setActiveControlView(tab.id),
165
- }) as ControlWorkspaceTopBarBinding
166
162
  const pillNav = reactive({
167
163
  items: controls.viewItems,
168
164
  currentItemId: activeControlView.value,
@@ -176,18 +172,12 @@ export function useBioTemplatePresetWorkspace(
176
172
  },
177
173
  onSettingsValuesChange: setControlValues,
178
174
  }) as ControlWorkspaceTopBarSettingsBinding
179
- const topBarProps = computed<ControlWorkspaceAppTopBarPillBinding>(() => ({
175
+ const topBarProps = computed<ControlWorkspaceTopBarBinding>(() => ({
180
176
  pillNav: pillNav.items,
181
177
  currentPillId: pillNav.currentItemId,
182
178
  onPillSelect: pillNav.onSelect,
183
179
  ...topBarSettings,
184
180
  }))
185
- const topBarTabsProps = computed<ControlWorkspaceAppTopBarTabsBinding>(() => ({
186
- tabs: topBar.tabs,
187
- currentTabId: topBar.currentTabId,
188
- onTabSelect: topBar.onTabSelect,
189
- ...topBarSettings,
190
- }))
191
181
 
192
182
  function getComponentProps(
193
183
  component: string,
@@ -201,10 +191,10 @@ export function useBioTemplatePresetWorkspace(
201
191
  form,
202
192
  sidebar,
203
193
  topBar: topBarProps,
204
- topBarTabs: topBarTabsProps,
205
194
  topBarSettings,
206
195
  pillNav,
207
196
  componentBindings,
197
+ componentBindingsById,
208
198
  componentProps,
209
199
  componentPropsById,
210
200
  componentPropsByComponent,
@@ -228,11 +218,9 @@ export function useBioTemplatePresetWorkspace(
228
218
 
229
219
  watch(activeControlView, (viewId) => {
230
220
  sidebar.activeView = viewId
231
- topBar.currentTabId = viewId
232
221
  pillNav.currentItemId = viewId
233
222
  }, { flush: 'sync' })
234
223
  watch(() => sidebar.activeView, setActiveControlView, { flush: 'sync' })
235
- watch(() => topBar.currentTabId, setActiveControlView, { flush: 'sync' })
236
224
  watch(() => pillNav.currentItemId, setActiveControlView, { flush: 'sync' })
237
225
 
238
226
  function applyCollection(value: TemplateCollectionEnvelope): TemplateCollectionEnvelope {
@@ -292,13 +280,14 @@ export function useBioTemplatePresetWorkspace(
292
280
  activeControlView,
293
281
  form,
294
282
  sidebar,
295
- topBar,
283
+ topBar: topBarProps,
296
284
  pillNav,
297
285
  topBarSettings,
298
286
  bindings,
299
287
  renderer,
300
288
  workspace,
301
289
  componentBindings,
290
+ componentBindingsById,
302
291
  componentImports,
303
292
  componentProps,
304
293
  componentPropsById,
@@ -7,7 +7,6 @@ import type {
7
7
  ControlWorkspaceOptions,
8
8
  ControlWorkspacePillNavBinding,
9
9
  ControlWorkspaceSidebarBinding,
10
- ControlWorkspaceTopBarBinding,
11
10
  ControlWorkspaceTopBarSettingsBinding,
12
11
  UseControlSchemaReturn,
13
12
  UseControlWorkspaceReturn,
@@ -23,6 +22,7 @@ import {
23
22
  import {
24
23
  useBioTemplateComponents,
25
24
  type BioTemplateComponentBinding,
25
+ type BioTemplateComponentBindingsById,
26
26
  type BioTemplateComponentImport,
27
27
  type BioTemplateComponentPropsByComponent,
28
28
  type BioTemplateComponentPropsBinding,
@@ -43,10 +43,10 @@ export interface BioTemplateWorkspaceBindings {
43
43
  form: ControlWorkspaceFormBinding
44
44
  sidebar: ControlWorkspaceSidebarBinding
45
45
  topBar: UseControlWorkspaceReturn<BioTemplateControlSchema>['bindings']['topBar']
46
- topBarTabs: UseControlWorkspaceReturn<BioTemplateControlSchema>['bindings']['topBarTabs']
47
46
  topBarSettings: ControlWorkspaceTopBarSettingsBinding
48
47
  pillNav: ControlWorkspacePillNavBinding
49
48
  componentBindings: BioTemplateComponentBinding[]
49
+ componentBindingsById: BioTemplateComponentBindingsById
50
50
  componentProps: BioTemplateComponentPropsBinding[]
51
51
  componentPropsById: BioTemplateComponentPropsById
52
52
  componentPropsByComponent: BioTemplateComponentPropsByComponent
@@ -65,12 +65,13 @@ export interface UseBioTemplateWorkspaceReturn {
65
65
  activeView: UseControlWorkspaceReturn<BioTemplateControlSchema>['activeView']
66
66
  form: ControlWorkspaceFormBinding
67
67
  sidebar: ControlWorkspaceSidebarBinding
68
- topBar: ControlWorkspaceTopBarBinding
68
+ topBar: UseControlWorkspaceReturn<BioTemplateControlSchema>['topBar']
69
69
  pillNav: ControlWorkspacePillNavBinding
70
70
  topBarSettings: ControlWorkspaceTopBarSettingsBinding
71
71
  bindings: BioTemplateWorkspaceBindings
72
72
  renderer: BioTemplateRendererBinding | null
73
73
  componentBindings: BioTemplateComponentBinding[]
74
+ componentBindingsById: BioTemplateComponentBindingsById
74
75
  componentImports: BioTemplateComponentImport[]
75
76
  componentProps: BioTemplateComponentPropsBinding[]
76
77
  componentPropsById: BioTemplateComponentPropsById
@@ -94,10 +95,10 @@ export function useBioTemplateWorkspace(
94
95
  form: workspace.bindings.form,
95
96
  sidebar: workspace.bindings.sidebar,
96
97
  topBar: workspace.bindings.topBar,
97
- topBarTabs: workspace.bindings.topBarTabs,
98
98
  topBarSettings: workspace.bindings.topBarSettings,
99
99
  pillNav: workspace.bindings.pillNav,
100
100
  componentBindings: components.bindings,
101
+ componentBindingsById: components.componentBindingsById,
101
102
  componentProps: components.componentProps,
102
103
  componentPropsById: components.componentPropsById,
103
104
  componentPropsByComponent: components.componentPropsByComponent,
@@ -122,6 +123,7 @@ export function useBioTemplateWorkspace(
122
123
  bindings,
123
124
  renderer,
124
125
  componentBindings: components.bindings,
126
+ componentBindingsById: components.componentBindingsById,
125
127
  componentImports: components.imports,
126
128
  componentProps: components.componentProps,
127
129
  componentPropsById: components.componentPropsById,