@morscherlab/mint-sdk 1.0.0-beta.7 → 1.0.0-rc.2

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 (163) hide show
  1. package/README.md +9 -1
  2. package/dist/__tests__/components/LcmsSequenceTable.test.d.ts +1 -0
  3. package/dist/__tests__/components/ProgressBar.test.d.ts +1 -0
  4. package/dist/__tests__/components/RackEditor.test.d.ts +1 -0
  5. package/dist/__tests__/components/SequenceProgressBar.test.d.ts +1 -0
  6. package/dist/__tests__/composables/useExperimentSamples.test.d.ts +1 -0
  7. package/dist/__tests__/composables/useProtocolTemplates.test.d.ts +1 -0
  8. package/dist/__tests__/stores/settings.test.d.ts +1 -0
  9. package/dist/__tests__/utils/instrument.test.d.ts +1 -0
  10. package/dist/__tests__/utils/lcms.test.d.ts +1 -0
  11. package/dist/__tests__/utils/permissions.test.d.ts +1 -0
  12. package/dist/__tests__/utils/rack.test.d.ts +1 -0
  13. package/dist/{auth-QQj2kkze.js → auth-B7g4J4ZF.js} +148 -24
  14. package/dist/auth-B7g4J4ZF.js.map +1 -0
  15. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  16. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  17. package/dist/components/BaseToggle.vue.d.ts +2 -2
  18. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
  19. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
  20. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +1 -1
  21. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +1 -1
  22. package/dist/components/FormulaInput.vue.d.ts +1 -1
  23. package/dist/components/InstrumentAlertLog.vue.d.ts +22 -0
  24. package/dist/components/InstrumentStateBadge.vue.d.ts +11 -0
  25. package/dist/components/InstrumentStatusCard.vue.d.ts +13 -0
  26. package/dist/components/LcmsSequenceTable.vue.d.ts +26 -0
  27. package/dist/components/ProgressBar.vue.d.ts +1 -0
  28. package/dist/components/RackEditor.vue.d.ts +41 -3
  29. package/dist/components/ReagentList.vue.d.ts +1 -1
  30. package/dist/components/SampleSelector.vue.d.ts +5 -2
  31. package/dist/components/SegmentedControl.vue.d.ts +2 -0
  32. package/dist/components/SequenceInput.vue.d.ts +1 -1
  33. package/dist/components/SequenceProgressBar.vue.d.ts +15 -0
  34. package/dist/components/SettingsModal.vue.d.ts +8 -1
  35. package/dist/components/TagsInput.vue.d.ts +1 -1
  36. package/dist/components/WellPlate.vue.d.ts +42 -3
  37. package/dist/components/index.d.ts +5 -0
  38. package/dist/components/index.js +3 -3
  39. package/dist/{components-DihbSJjU.js → components-BhK-dW99.js} +2135 -1075
  40. package/dist/components-BhK-dW99.js.map +1 -0
  41. package/dist/composables/experimentDesignData.d.ts +17 -0
  42. package/dist/composables/index.d.ts +2 -0
  43. package/dist/composables/index.js +4 -4
  44. package/dist/composables/useControlSchema.d.ts +11 -0
  45. package/dist/composables/useExperimentData.d.ts +11 -3
  46. package/dist/composables/useExperimentSamples.d.ts +42 -0
  47. package/dist/composables/usePlatformContext.d.ts +54 -0
  48. package/dist/{composables-BcgZ6diz.js → composables-Bg7CFuNz.js} +5 -3
  49. package/dist/composables-Bg7CFuNz.js.map +1 -0
  50. package/dist/index.d.ts +4 -0
  51. package/dist/index.js +168 -6
  52. package/dist/index.js.map +1 -0
  53. package/dist/install.js +2 -2
  54. package/dist/instrument.d.ts +7 -0
  55. package/dist/lcms.d.ts +27 -0
  56. package/dist/permissions.d.ts +46 -0
  57. package/dist/stores/auth.d.ts +74 -2
  58. package/dist/stores/index.js +1 -1
  59. package/dist/styles.css +3186 -1070
  60. package/dist/templates/builders.d.ts +7 -3
  61. package/dist/templates/index.d.ts +2 -2
  62. package/dist/templates/index.js +2 -2
  63. package/dist/templates/presets.d.ts +12 -0
  64. package/dist/templates/types.d.ts +16 -1
  65. package/dist/{templates-Cyt0Suwf.js → templates-BorLR_7p.js} +324 -10
  66. package/dist/templates-BorLR_7p.js.map +1 -0
  67. package/dist/types/auth.d.ts +2 -0
  68. package/dist/types/components.d.ts +32 -3
  69. package/dist/types/form-builder.d.ts +2 -1
  70. package/dist/types/index.d.ts +4 -1
  71. package/dist/types/instrument.d.ts +56 -0
  72. package/dist/types/platform.d.ts +3 -0
  73. package/dist/{useExperimentData-CM6Y0u5L.js → useProtocolTemplates-n6AJqSqv.js} +627 -380
  74. package/dist/useProtocolTemplates-n6AJqSqv.js.map +1 -0
  75. package/dist/utils/rack.d.ts +47 -0
  76. package/package.json +1 -1
  77. package/src/__tests__/components/AppTopBar.test.ts +15 -0
  78. package/src/__tests__/components/BaseTabs.test.ts +15 -0
  79. package/src/__tests__/components/GroupAssigner.test.ts +18 -0
  80. package/src/__tests__/components/LcmsSequenceTable.test.ts +57 -0
  81. package/src/__tests__/components/ProgressBar.test.ts +18 -0
  82. package/src/__tests__/components/RackEditor.test.ts +125 -0
  83. package/src/__tests__/components/SampleSelector.test.ts +25 -0
  84. package/src/__tests__/components/SegmentedControl.test.ts +45 -0
  85. package/src/__tests__/components/SequenceProgressBar.test.ts +39 -0
  86. package/src/__tests__/components/SettingsModal.test.ts +83 -2
  87. package/src/__tests__/composables/useApi.test.ts +45 -0
  88. package/src/__tests__/composables/useAuth.test.ts +20 -0
  89. package/src/__tests__/composables/useControlSchema.test.ts +4 -0
  90. package/src/__tests__/composables/useExperimentData.test.ts +23 -0
  91. package/src/__tests__/composables/useExperimentSamples.test.ts +91 -0
  92. package/src/__tests__/composables/useProtocolTemplates.test.ts +64 -0
  93. package/src/__tests__/stores/settings.test.ts +78 -0
  94. package/src/__tests__/templates/templates.test.ts +86 -0
  95. package/src/__tests__/utils/instrument.test.ts +47 -0
  96. package/src/__tests__/utils/lcms.test.ts +73 -0
  97. package/src/__tests__/utils/permissions.test.ts +50 -0
  98. package/src/__tests__/utils/rack.test.ts +120 -0
  99. package/src/components/AppAvatarMenu.vue +6 -3
  100. package/src/components/AppTopBar.vue +16 -10
  101. package/src/components/AuditTrail.vue +1 -1
  102. package/src/components/BaseTabs.vue +22 -1
  103. package/src/components/Calendar.vue +6 -2
  104. package/src/components/ConcentrationInput.vue +3 -2
  105. package/src/components/GroupAssigner.vue +8 -3
  106. package/src/components/InstrumentAlertLog.vue +191 -0
  107. package/src/components/InstrumentStateBadge.vue +50 -0
  108. package/src/components/InstrumentStatusCard.vue +188 -0
  109. package/src/components/LcmsSequenceTable.vue +191 -0
  110. package/src/components/NumberInput.vue +5 -3
  111. package/src/components/ProgressBar.vue +3 -0
  112. package/src/components/RackEditor.vue +73 -2
  113. package/src/components/SampleHierarchyTree.vue +3 -2
  114. package/src/components/SampleSelector.vue +28 -9
  115. package/src/components/SegmentedControl.story.vue +17 -0
  116. package/src/components/SegmentedControl.vue +14 -3
  117. package/src/components/SequenceProgressBar.vue +71 -0
  118. package/src/components/SettingsModal.vue +49 -2
  119. package/src/components/UnitInput.vue +6 -2
  120. package/src/components/WellPlate.vue +145 -24
  121. package/src/components/index.ts +5 -0
  122. package/src/components/internal/WellEditPopupInternal.vue +1 -0
  123. package/src/composables/experimentDesignData.ts +182 -0
  124. package/src/composables/index.ts +14 -0
  125. package/src/composables/useApi.ts +113 -16
  126. package/src/composables/useAuth.ts +4 -0
  127. package/src/composables/useAutoGroup.ts +18 -9
  128. package/src/composables/useControlSchema.ts +21 -0
  129. package/src/composables/useExperimentData.ts +57 -16
  130. package/src/composables/useExperimentSamples.ts +142 -0
  131. package/src/composables/useProtocolTemplates.ts +13 -1
  132. package/src/composables/useRackEditor.ts +3 -2
  133. package/src/index.ts +27 -0
  134. package/src/instrument.ts +90 -0
  135. package/src/lcms.ts +108 -0
  136. package/src/permissions.ts +143 -0
  137. package/src/stores/auth.ts +79 -26
  138. package/src/stores/settings.ts +10 -0
  139. package/src/styles/components/instrument-monitor.css +478 -0
  140. package/src/styles/components/lcms-sequence-table.css +189 -0
  141. package/src/styles/components/sequence-progress-bar.css +63 -0
  142. package/src/styles/components/settings-modal.css +9 -0
  143. package/src/styles/components/tabs.css +9 -0
  144. package/src/styles/components/well-edit-popup.css +7 -1
  145. package/src/styles/components/well-plate.css +5 -0
  146. package/src/styles/index.css +3 -0
  147. package/src/templates/builders.ts +201 -0
  148. package/src/templates/controlSchemas.ts +68 -0
  149. package/src/templates/index.ts +2 -0
  150. package/src/templates/presets.ts +23 -0
  151. package/src/templates/types.ts +17 -0
  152. package/src/types/auth.ts +3 -0
  153. package/src/types/components.ts +45 -3
  154. package/src/types/form-builder.ts +2 -1
  155. package/src/types/index.ts +35 -0
  156. package/src/types/instrument.ts +61 -0
  157. package/src/types/platform.ts +4 -0
  158. package/src/utils/rack.ts +209 -0
  159. package/dist/auth-QQj2kkze.js.map +0 -1
  160. package/dist/components-DihbSJjU.js.map +0 -1
  161. package/dist/composables-BcgZ6diz.js.map +0 -1
  162. package/dist/templates-Cyt0Suwf.js.map +0 -1
  163. package/dist/useExperimentData-CM6Y0u5L.js.map +0 -1
package/README.md CHANGED
@@ -318,7 +318,7 @@ template presets such as `createWellPlateScreenCollection()`,
318
318
  - `FileUploader` - Drag-and-drop file upload with file/folder mode support
319
319
 
320
320
  ### Sample Management Components
321
- - `SampleSelector` - Hierarchical sample grouping with auto-group and CSV metadata import
321
+ - `SampleSelector` - Hierarchical sample grouping with auto-group, CSV metadata import, and optional experiment `design_data` sample loading
322
322
  - `AutoGroupModal` - Smart sample grouping wizard for names and design metadata
323
323
  - `GroupAssigner` - Drag-and-drop group assignment for comparisons (e.g., Control vs Treatment)
324
324
 
@@ -416,6 +416,14 @@ if (isIntegrated.value) {
416
416
  }
417
417
  ```
418
418
 
419
+ ### `useExperimentSamples(options?)`
420
+ Load experiment `design_data` and derive `SampleSelector`-compatible sample values.
421
+
422
+ ```typescript
423
+ const { samples, sampleOptions, fetch } = useExperimentSamples({ experimentId: 42 })
424
+ await fetch()
425
+ ```
426
+
419
427
  ## Stores
420
428
 
421
429
  ### `useAuthStore`
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,7 @@ import { computed, ref, watch } from "vue";
2
2
  import { defineStore } from "pinia";
3
3
  //#region src/stores/settings.ts
4
4
  var STORAGE_KEY = "mint-settings";
5
+ var LEGACY_STORAGE_KEY = "mld-settings";
5
6
  function getDefaultServerHost() {
6
7
  if (typeof window !== "undefined" && window.location.hostname !== "localhost") return window.location.hostname;
7
8
  return "localhost";
@@ -51,6 +52,17 @@ function loadSettings() {
51
52
  ...parsed
52
53
  };
53
54
  }
55
+ const legacyStored = localStorage.getItem(LEGACY_STORAGE_KEY);
56
+ if (legacyStored) {
57
+ const parsed = JSON.parse(legacyStored);
58
+ const migrated = {
59
+ ...defaultSettings,
60
+ ...parsed
61
+ };
62
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(migrated));
63
+ localStorage.removeItem(LEGACY_STORAGE_KEY);
64
+ return migrated;
65
+ }
54
66
  } catch (e) {
55
67
  console.warn("Failed to load settings from localStorage:", e);
56
68
  }
@@ -187,10 +199,112 @@ var useSettingsStore = defineStore("mint-settings", () => {
187
199
  };
188
200
  });
189
201
  //#endregion
202
+ //#region src/permissions.ts
203
+ var ADMIN_ROLE = "admin";
204
+ var ADMIN_PANEL_PERMISSIONS = [
205
+ "users.view",
206
+ "users.invite",
207
+ "users.manage",
208
+ "platform.configure",
209
+ "platform.view_logs",
210
+ "plugins.configure",
211
+ "plugins.install"
212
+ ];
213
+ function getRoleInfo(user) {
214
+ return user?.roleObj ?? user?.role_obj ?? null;
215
+ }
216
+ function isAdminRole(role) {
217
+ return role === ADMIN_ROLE;
218
+ }
219
+ function isAdminUser(user) {
220
+ return isAdminRole(user?.role) || getRoleInfo(user)?.slug === "admin";
221
+ }
222
+ function getAccessAudience(user) {
223
+ return isAdminUser(user) ? "admin" : "user";
224
+ }
225
+ function getUserPermissions(user) {
226
+ const rolePermissions = getRoleInfo(user)?.permissions;
227
+ if (rolePermissions?.length) return [...rolePermissions];
228
+ return [...user?.permissions ?? []];
229
+ }
230
+ function hasAllPermissions(user, permissions = []) {
231
+ if (permissions.length === 0) return true;
232
+ if (isAdminUser(user)) return true;
233
+ const granted = new Set(getUserPermissions(user));
234
+ return permissions.every((permission) => granted.has(permission));
235
+ }
236
+ function hasAnyPermission(user, permissions = []) {
237
+ if (permissions.length === 0) return true;
238
+ if (isAdminUser(user)) return true;
239
+ const granted = new Set(getUserPermissions(user));
240
+ return permissions.some((permission) => granted.has(permission));
241
+ }
242
+ function canAccessAdmin(user) {
243
+ return isAdminUser(user) || hasAnyPermission(user, ADMIN_PANEL_PERMISSIONS);
244
+ }
245
+ function canAccessPlugin(user, pluginName) {
246
+ if (!pluginName) return true;
247
+ const access = getRoleInfo(user)?.plugin_access;
248
+ if (!access || access === "all") return true;
249
+ return Array.isArray(access) && access.includes(pluginName);
250
+ }
251
+ function normalizeAccessPolicy(rule) {
252
+ if (!rule) return {};
253
+ const { access: nested, ...direct } = rule;
254
+ return {
255
+ ...nested ?? {},
256
+ ...direct,
257
+ ..."visibleFor" in rule && rule.visibleFor !== void 0 ? { visibleFor: rule.visibleFor } : {},
258
+ ..."requiresAdmin" in rule && rule.requiresAdmin !== void 0 ? { requiresAdmin: rule.requiresAdmin } : {},
259
+ ..."permissions" in rule && rule.permissions !== void 0 ? { permissions: rule.permissions } : {},
260
+ ..."anyPermissions" in rule && rule.anyPermissions !== void 0 ? { anyPermissions: rule.anyPermissions } : {}
261
+ };
262
+ }
263
+ function canAccessByPolicy(user, rule, isAuthenticated = user !== null && user !== void 0) {
264
+ const policy = normalizeAccessPolicy(rule);
265
+ if (policy.requiresAuth && !isAuthenticated) return false;
266
+ if (policy.requiresAdmin && !isAdminUser(user)) return false;
267
+ if (!audienceAllowsUser(policy.visibleFor ?? policy.audience, user)) return false;
268
+ if (!hasAllPermissions(user, policy.permissions)) return false;
269
+ if (!hasAnyPermission(user, policy.anyPermissions)) return false;
270
+ if (policy.plugin && !canAccessPlugin(user, policy.plugin)) return false;
271
+ return true;
272
+ }
273
+ function audienceAllowsUser(audience, user) {
274
+ if (audience === void 0) return true;
275
+ const allowed = Array.isArray(audience) ? audience : [audience];
276
+ if (allowed.includes("all")) return true;
277
+ return allowed.includes(getAccessAudience(user));
278
+ }
279
+ //#endregion
190
280
  //#region src/stores/auth.ts
191
281
  var AUTH_TOKEN_KEY = "mint-auth-token";
192
282
  var AUTH_EXPIRES_KEY = "mint-auth-expires";
193
- var hasLocalStorage = typeof localStorage !== "undefined" && typeof localStorage.getItem === "function";
283
+ function getLocalStorage() {
284
+ try {
285
+ const storage = globalThis.localStorage;
286
+ return typeof storage?.getItem === "function" ? storage : null;
287
+ } catch {
288
+ return null;
289
+ }
290
+ }
291
+ function readStoredItem(key) {
292
+ try {
293
+ return getLocalStorage()?.getItem(key) ?? null;
294
+ } catch {
295
+ return null;
296
+ }
297
+ }
298
+ function writeStoredItem(key, value) {
299
+ try {
300
+ getLocalStorage()?.setItem(key, value);
301
+ } catch {}
302
+ }
303
+ function removeStoredItem(key) {
304
+ try {
305
+ getLocalStorage()?.removeItem(key);
306
+ } catch {}
307
+ }
194
308
  var useAuthStore = defineStore("mint-auth", () => {
195
309
  const token = ref(null);
196
310
  const tokenExpires = ref(null);
@@ -215,23 +329,22 @@ var useAuthStore = defineStore("mint-auth", () => {
215
329
  const needsAuth = computed(() => {
216
330
  return authConfig.value.authRequired && !isAuthenticated.value;
217
331
  });
218
- const isAdmin = computed(() => {
219
- return userInfo.value?.role === "admin";
220
- });
332
+ const isAdmin = computed(() => isAdminUser(userInfo.value));
333
+ const userType = computed(() => getAccessAudience(userInfo.value));
334
+ const permissions = computed(() => getUserPermissions(userInfo.value));
335
+ const canAccessAdmin$1 = computed(() => canAccessAdmin(userInfo.value));
221
336
  const canRegister = computed(() => {
222
337
  return authConfig.value.registrationEnabled;
223
338
  });
224
339
  function initialize() {
225
- if (hasLocalStorage) {
226
- const storedToken = localStorage.getItem(AUTH_TOKEN_KEY);
227
- const storedExpires = localStorage.getItem(AUTH_EXPIRES_KEY);
228
- if (storedToken) {
229
- token.value = storedToken;
230
- if (storedExpires) {
231
- const expires = new Date(storedExpires);
232
- if (expires > /* @__PURE__ */ new Date()) tokenExpires.value = expires;
233
- else clearToken();
234
- }
340
+ const storedToken = readStoredItem(AUTH_TOKEN_KEY);
341
+ const storedExpires = readStoredItem(AUTH_EXPIRES_KEY);
342
+ if (storedToken) {
343
+ token.value = storedToken;
344
+ if (storedExpires) {
345
+ const expires = new Date(storedExpires);
346
+ if (expires > /* @__PURE__ */ new Date()) tokenExpires.value = expires;
347
+ else clearToken();
235
348
  }
236
349
  }
237
350
  isInitialized.value = true;
@@ -240,25 +353,30 @@ var useAuthStore = defineStore("mint-auth", () => {
240
353
  token.value = accessToken;
241
354
  const expires = new Date(Date.now() + expiresIn * 1e3);
242
355
  tokenExpires.value = expires;
243
- if (hasLocalStorage) {
244
- localStorage.setItem(AUTH_TOKEN_KEY, accessToken);
245
- localStorage.setItem(AUTH_EXPIRES_KEY, expires.toISOString());
246
- }
356
+ writeStoredItem(AUTH_TOKEN_KEY, accessToken);
357
+ writeStoredItem(AUTH_EXPIRES_KEY, expires.toISOString());
247
358
  }
248
359
  function clearToken() {
249
360
  token.value = null;
250
361
  tokenExpires.value = null;
251
362
  username.value = null;
252
363
  userInfo.value = null;
253
- if (hasLocalStorage) {
254
- localStorage.removeItem(AUTH_TOKEN_KEY);
255
- localStorage.removeItem(AUTH_EXPIRES_KEY);
256
- }
364
+ removeStoredItem(AUTH_TOKEN_KEY);
365
+ removeStoredItem(AUTH_EXPIRES_KEY);
257
366
  }
258
367
  function setUserInfo(info) {
259
368
  userInfo.value = info;
260
369
  username.value = info.username;
261
370
  }
371
+ function hasPermission(...perms) {
372
+ return hasAllPermissions(userInfo.value, perms);
373
+ }
374
+ function hasAnyPermissionForUser(...perms) {
375
+ return hasAnyPermission(userInfo.value, perms);
376
+ }
377
+ function canAccessPlugin$1(pluginName) {
378
+ return canAccessPlugin(userInfo.value, pluginName);
379
+ }
262
380
  function setAuthConfig(config) {
263
381
  authConfig.value = config;
264
382
  }
@@ -286,6 +404,9 @@ var useAuthStore = defineStore("mint-auth", () => {
286
404
  isAuthenticated,
287
405
  needsAuth,
288
406
  isAdmin,
407
+ userType,
408
+ permissions,
409
+ canAccessAdmin: canAccessAdmin$1,
289
410
  canRegister,
290
411
  initialize,
291
412
  setToken,
@@ -295,10 +416,13 @@ var useAuthStore = defineStore("mint-auth", () => {
295
416
  setUserInfo,
296
417
  setError,
297
418
  setLoading,
419
+ hasPermission,
420
+ hasAnyPermission: hasAnyPermissionForUser,
421
+ canAccessPlugin: canAccessPlugin$1,
298
422
  logout
299
423
  };
300
424
  });
301
425
  //#endregion
302
- export { colorPalettes as n, useSettingsStore as r, useAuthStore as t };
426
+ export { canAccessByPolicy as a, getRoleInfo as c, hasAnyPermission as d, isAdminRole as f, useSettingsStore as g, colorPalettes as h, canAccessAdmin as i, getUserPermissions as l, normalizeAccessPolicy as m, ADMIN_PANEL_PERMISSIONS as n, canAccessPlugin as o, isAdminUser as p, ADMIN_ROLE as r, getAccessAudience as s, useAuthStore as t, hasAllPermissions as u };
303
427
 
304
- //# sourceMappingURL=auth-QQj2kkze.js.map
428
+ //# sourceMappingURL=auth-B7g4J4ZF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-B7g4J4ZF.js","names":[],"sources":["../src/stores/settings.ts","../src/permissions.ts","../src/stores/auth.ts"],"sourcesContent":["import { defineStore } from 'pinia'\nimport { ref, watch } from 'vue'\nimport type { ThemeMode, ColorPalette, TableDensity } from '../types'\n\ndeclare global {\n interface ImportMetaEnv {\n readonly VITE_API_PREFIX?: string\n }\n\n interface ImportMeta {\n readonly env: ImportMetaEnv\n }\n}\n\nexport interface SettingsState {\n serverHost: string\n serverPort: number\n requestTimeout: number\n wsAutoReconnect: boolean\n wsReconnectInterval: number\n theme: ThemeMode\n colorPalette: ColorPalette\n tableDensity: TableDensity\n}\n\nconst STORAGE_KEY = 'mint-settings'\nconst LEGACY_STORAGE_KEY = 'mld-settings'\n\nfunction getDefaultServerHost(): string {\n if (typeof window !== 'undefined' && window.location.hostname !== 'localhost') {\n return window.location.hostname\n }\n return 'localhost'\n}\n\nfunction getDefaultServerPort(): number {\n if (typeof window !== 'undefined') {\n if (window.location.port) {\n return parseInt(window.location.port, 10)\n }\n // Standard ports: 443 for HTTPS, 80 for HTTP (browser omits from location.port)\n return window.location.protocol === 'https:' ? 443 : 80\n }\n return 8000\n}\n\nconst defaultSettings: SettingsState = {\n serverHost: getDefaultServerHost(),\n serverPort: getDefaultServerPort(),\n requestTimeout: 120000,\n wsAutoReconnect: true,\n wsReconnectInterval: 5000,\n theme: 'system',\n colorPalette: 'default',\n tableDensity: 'normal',\n}\n\nexport const colorPalettes: Record<ColorPalette, { name: string; hues: [number, number] }> = {\n default: { name: 'Default (Cyan-Pink)', hues: [180, 320] },\n colorblind: { name: 'Colorblind-friendly', hues: [45, 260] },\n viridis: { name: 'Viridis', hues: [280, 80] },\n pastel: { name: 'Pastel', hues: [200, 340] },\n}\n\nfunction loadSettings(): SettingsState {\n try {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored) {\n const parsed = JSON.parse(stored)\n return { ...defaultSettings, ...parsed }\n }\n\n const legacyStored = localStorage.getItem(LEGACY_STORAGE_KEY)\n if (legacyStored) {\n const parsed = JSON.parse(legacyStored)\n const migrated = { ...defaultSettings, ...parsed }\n localStorage.setItem(STORAGE_KEY, JSON.stringify(migrated))\n localStorage.removeItem(LEGACY_STORAGE_KEY)\n return migrated\n }\n } catch (e) {\n console.warn('Failed to load settings from localStorage:', e)\n }\n return { ...defaultSettings }\n}\n\nfunction saveSettings(settings: SettingsState): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(settings))\n } catch (e) {\n console.warn('Failed to save settings to localStorage:', e)\n }\n}\n\nfunction getSystemPrefersDark(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n}\n\nexport const useSettingsStore = defineStore('mint-settings', () => {\n // State\n const serverHost = ref(defaultSettings.serverHost)\n const serverPort = ref(defaultSettings.serverPort)\n const requestTimeout = ref(defaultSettings.requestTimeout)\n const wsAutoReconnect = ref(defaultSettings.wsAutoReconnect)\n const wsReconnectInterval = ref(defaultSettings.wsReconnectInterval)\n const theme = ref<ThemeMode>(defaultSettings.theme)\n const systemPrefersDark = ref(getSystemPrefersDark())\n const colorPalette = ref<ColorPalette>(defaultSettings.colorPalette)\n const tableDensity = ref<TableDensity>(defaultSettings.tableDensity)\n\n // API prefix - can be configured via env variable VITE_API_PREFIX\n const apiPrefix: string = (import.meta.env?.VITE_API_PREFIX as string | undefined) ?? '/api'\n\n function _isSameOrigin(): { same: boolean; currentHost: string; currentPort: string } {\n const currentHost = typeof window !== 'undefined' ? window.location.hostname : 'localhost'\n const currentPort = typeof window !== 'undefined' ? window.location.port : '8000'\n const effectivePort = currentPort || (window.location.protocol === 'https:' ? '443' : '80')\n const same =\n (serverHost.value === currentHost && String(serverPort.value) === effectivePort) ||\n (serverHost.value === 'localhost' && currentHost !== 'localhost')\n return { same, currentHost, currentPort }\n }\n\n function getApiBaseUrl(): string {\n const { same } = _isSameOrigin()\n if (same) return apiPrefix\n return `http://${serverHost.value}:${serverPort.value}${apiPrefix}`\n }\n\n function getWsBaseUrl(): string {\n const { same, currentHost, currentPort } = _isSameOrigin()\n const protocol = typeof window !== 'undefined' && window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n if (same) return `${protocol}//${currentHost}${currentPort ? ':' + currentPort : ''}${apiPrefix}`\n return `ws://${serverHost.value}:${serverPort.value}${apiPrefix}`\n }\n\n let _initialized = false\n\n function initialize() {\n if (_initialized) return\n _initialized = true\n\n const loaded = loadSettings()\n serverHost.value = loaded.serverHost\n serverPort.value = loaded.serverPort\n requestTimeout.value = loaded.requestTimeout\n wsAutoReconnect.value = loaded.wsAutoReconnect\n wsReconnectInterval.value = loaded.wsReconnectInterval\n theme.value = loaded.theme\n colorPalette.value = loaded.colorPalette\n tableDensity.value = loaded.tableDensity\n\n applyTheme()\n }\n\n function applyTheme() {\n if (typeof document === 'undefined') return\n const dark = theme.value === 'system' ? systemPrefersDark.value : theme.value === 'dark'\n document.documentElement.classList.toggle('dark', dark)\n }\n\n watch(theme, () => {\n applyTheme()\n persistSettings()\n })\n\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {\n systemPrefersDark.value = event.matches\n if (theme.value === 'system') {\n applyTheme()\n }\n })\n }\n\n function persistSettings() {\n saveSettings({\n serverHost: serverHost.value,\n serverPort: serverPort.value,\n requestTimeout: requestTimeout.value,\n wsAutoReconnect: wsAutoReconnect.value,\n wsReconnectInterval: wsReconnectInterval.value,\n theme: theme.value,\n colorPalette: colorPalette.value,\n tableDensity: tableDensity.value,\n })\n }\n\n watch([serverHost, serverPort, requestTimeout, wsAutoReconnect, wsReconnectInterval, colorPalette, tableDensity], () => {\n persistSettings()\n })\n\n function resetToDefaults() {\n serverHost.value = defaultSettings.serverHost\n serverPort.value = defaultSettings.serverPort\n requestTimeout.value = defaultSettings.requestTimeout\n wsAutoReconnect.value = defaultSettings.wsAutoReconnect\n wsReconnectInterval.value = defaultSettings.wsReconnectInterval\n theme.value = defaultSettings.theme\n colorPalette.value = defaultSettings.colorPalette\n tableDensity.value = defaultSettings.tableDensity\n }\n\n function getPaletteHues(): [number, number] {\n return colorPalettes[colorPalette.value].hues\n }\n\n function isDark(): boolean {\n return theme.value === 'system' ? systemPrefersDark.value : theme.value === 'dark'\n }\n\n return {\n serverHost,\n serverPort,\n requestTimeout,\n wsAutoReconnect,\n wsReconnectInterval,\n theme,\n systemPrefersDark,\n colorPalette,\n tableDensity,\n initialize,\n applyTheme,\n persistSettings,\n resetToDefaults,\n getPaletteHues,\n isDark,\n getApiBaseUrl,\n getWsBaseUrl,\n }\n})\n","export const ADMIN_ROLE = 'admin'\n\nexport const ADMIN_PANEL_PERMISSIONS = [\n 'users.view',\n 'users.invite',\n 'users.manage',\n 'platform.configure',\n 'platform.view_logs',\n 'plugins.configure',\n 'plugins.install',\n] as const\n\nexport type AccessAudience = 'all' | 'admin' | 'user'\nexport type AccessAudienceInput = AccessAudience | readonly AccessAudience[]\n\nexport interface RoleInfo {\n id?: number\n slug: string\n name?: string\n color?: string\n permissions?: readonly string[] | null\n project_scope?: 'all' | 'assigned' | string\n plugin_access?: readonly string[] | 'all' | null\n}\n\nexport interface PermissionUser {\n role?: string | null\n role_obj?: RoleInfo | null\n roleObj?: RoleInfo | null\n permissions?: readonly string[] | null\n}\n\nexport interface AccessPolicy {\n audience?: AccessAudienceInput\n visibleFor?: AccessAudienceInput\n requiresAuth?: boolean\n requiresAdmin?: boolean\n permissions?: readonly string[]\n anyPermissions?: readonly string[]\n plugin?: string\n}\n\nexport interface AccessControlled {\n access?: AccessPolicy\n visibleFor?: AccessAudienceInput\n requiresAdmin?: boolean\n permissions?: readonly string[]\n anyPermissions?: readonly string[]\n}\n\nexport function getRoleInfo(user: PermissionUser | null | undefined): RoleInfo | null {\n return user?.roleObj ?? user?.role_obj ?? null\n}\n\nexport function isAdminRole(role: string | null | undefined): boolean {\n return role === ADMIN_ROLE\n}\n\nexport function isAdminUser(user: PermissionUser | null | undefined): boolean {\n return isAdminRole(user?.role) || getRoleInfo(user)?.slug === ADMIN_ROLE\n}\n\nexport function getAccessAudience(user: PermissionUser | null | undefined): Exclude<AccessAudience, 'all'> {\n return isAdminUser(user) ? 'admin' : 'user'\n}\n\nexport function getUserPermissions(user: PermissionUser | null | undefined): string[] {\n const rolePermissions = getRoleInfo(user)?.permissions\n if (rolePermissions?.length) return [...rolePermissions]\n return [...(user?.permissions ?? [])]\n}\n\nexport function hasAllPermissions(\n user: PermissionUser | null | undefined,\n permissions: readonly string[] = [],\n): boolean {\n if (permissions.length === 0) return true\n if (isAdminUser(user)) return true\n const granted = new Set(getUserPermissions(user))\n return permissions.every(permission => granted.has(permission))\n}\n\nexport function hasAnyPermission(\n user: PermissionUser | null | undefined,\n permissions: readonly string[] = [],\n): boolean {\n if (permissions.length === 0) return true\n if (isAdminUser(user)) return true\n const granted = new Set(getUserPermissions(user))\n return permissions.some(permission => granted.has(permission))\n}\n\nexport function canAccessAdmin(user: PermissionUser | null | undefined): boolean {\n return isAdminUser(user) || hasAnyPermission(user, ADMIN_PANEL_PERMISSIONS)\n}\n\nexport function canAccessPlugin(\n user: PermissionUser | null | undefined,\n pluginName: string | null | undefined,\n): boolean {\n if (!pluginName) return true\n const access = getRoleInfo(user)?.plugin_access\n if (!access || access === 'all') return true\n return Array.isArray(access) && access.includes(pluginName)\n}\n\nexport function normalizeAccessPolicy(rule: AccessControlled | AccessPolicy | undefined): AccessPolicy {\n if (!rule) return {}\n const { access: nested, ...direct } = rule as AccessPolicy & { access?: AccessPolicy }\n return {\n ...(nested ?? {}),\n ...direct,\n ...('visibleFor' in rule && rule.visibleFor !== undefined ? { visibleFor: rule.visibleFor } : {}),\n ...('requiresAdmin' in rule && rule.requiresAdmin !== undefined ? { requiresAdmin: rule.requiresAdmin } : {}),\n ...('permissions' in rule && rule.permissions !== undefined ? { permissions: rule.permissions } : {}),\n ...('anyPermissions' in rule && rule.anyPermissions !== undefined ? { anyPermissions: rule.anyPermissions } : {}),\n }\n}\n\nexport function canAccessByPolicy(\n user: PermissionUser | null | undefined,\n rule: AccessControlled | AccessPolicy | undefined,\n isAuthenticated = user !== null && user !== undefined,\n): boolean {\n const policy = normalizeAccessPolicy(rule)\n if (policy.requiresAuth && !isAuthenticated) return false\n if (policy.requiresAdmin && !isAdminUser(user)) return false\n if (!audienceAllowsUser(policy.visibleFor ?? policy.audience, user)) return false\n if (!hasAllPermissions(user, policy.permissions)) return false\n if (!hasAnyPermission(user, policy.anyPermissions)) return false\n if (policy.plugin && !canAccessPlugin(user, policy.plugin)) return false\n return true\n}\n\nfunction audienceAllowsUser(\n audience: AccessAudienceInput | undefined,\n user: PermissionUser | null | undefined,\n): boolean {\n if (audience === undefined) return true\n const allowed = Array.isArray(audience) ? audience : [audience]\n if (allowed.includes('all')) return true\n return allowed.includes(getAccessAudience(user))\n}\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport type { AuthConfig, UserInfo } from '../types'\nimport {\n canAccessAdmin as canUserAccessAdmin,\n canAccessPlugin as canUserAccessPlugin,\n getAccessAudience,\n getUserPermissions,\n hasAllPermissions,\n hasAnyPermission,\n isAdminUser,\n} from '../permissions'\n\nconst AUTH_TOKEN_KEY = 'mint-auth-token'\nconst AUTH_EXPIRES_KEY = 'mint-auth-expires'\n\nfunction getLocalStorage(): Storage | null {\n try {\n const storage = globalThis.localStorage\n return typeof storage?.getItem === 'function' ? storage : null\n } catch {\n return null\n }\n}\n\nfunction readStoredItem(key: string): string | null {\n try {\n return getLocalStorage()?.getItem(key) ?? null\n } catch {\n return null\n }\n}\n\nfunction writeStoredItem(key: string, value: string): void {\n try {\n getLocalStorage()?.setItem(key, value)\n } catch {\n // Keep auth usable in-memory when browser storage is blocked.\n }\n}\n\nfunction removeStoredItem(key: string): void {\n try {\n getLocalStorage()?.removeItem(key)\n } catch {\n // Keep auth cleanup usable in-memory when browser storage is blocked.\n }\n}\n\nexport const useAuthStore = defineStore('mint-auth', () => {\n // State\n const token = ref<string | null>(null)\n const tokenExpires = ref<Date | null>(null)\n const username = ref<string | null>(null)\n const userInfo = ref<UserInfo | null>(null)\n const authConfig = ref<AuthConfig>({\n authRequired: true,\n passkeyEnabled: false,\n passkeyRegistered: false,\n registrationEnabled: false,\n databaseMode: 'none',\n })\n const isInitialized = ref(false)\n const isLoading = ref(false)\n const error = ref<string | null>(null)\n\n // Computed\n const isAuthenticated = computed(() => {\n if (!authConfig.value.authRequired) {\n return true\n }\n if (!token.value) {\n return false\n }\n if (tokenExpires.value && tokenExpires.value < new Date()) {\n return false\n }\n return true\n })\n\n const needsAuth = computed(() => {\n return authConfig.value.authRequired && !isAuthenticated.value\n })\n\n const isAdmin = computed(() => isAdminUser(userInfo.value))\n const userType = computed(() => getAccessAudience(userInfo.value))\n const permissions = computed(() => getUserPermissions(userInfo.value))\n const canAccessAdmin = computed(() => canUserAccessAdmin(userInfo.value))\n\n const canRegister = computed(() => {\n return authConfig.value.registrationEnabled\n })\n\n // Actions\n function initialize() {\n const storedToken = readStoredItem(AUTH_TOKEN_KEY)\n const storedExpires = readStoredItem(AUTH_EXPIRES_KEY)\n\n if (storedToken) {\n token.value = storedToken\n\n if (storedExpires) {\n const expires = new Date(storedExpires)\n if (expires > new Date()) {\n tokenExpires.value = expires\n } else {\n clearToken()\n }\n }\n }\n\n isInitialized.value = true\n }\n\n function setToken(accessToken: string, expiresIn: number) {\n token.value = accessToken\n const expires = new Date(Date.now() + expiresIn * 1000)\n tokenExpires.value = expires\n\n writeStoredItem(AUTH_TOKEN_KEY, accessToken)\n writeStoredItem(AUTH_EXPIRES_KEY, expires.toISOString())\n }\n\n function clearToken() {\n token.value = null\n tokenExpires.value = null\n username.value = null\n userInfo.value = null\n\n removeStoredItem(AUTH_TOKEN_KEY)\n removeStoredItem(AUTH_EXPIRES_KEY)\n }\n\n function setUserInfo(info: UserInfo) {\n userInfo.value = info\n username.value = info.username\n }\n\n function hasPermission(...perms: string[]): boolean {\n return hasAllPermissions(userInfo.value, perms)\n }\n\n function hasAnyPermissionForUser(...perms: string[]): boolean {\n return hasAnyPermission(userInfo.value, perms)\n }\n\n function canAccessPlugin(pluginName: string): boolean {\n return canUserAccessPlugin(userInfo.value, pluginName)\n }\n\n function setAuthConfig(config: AuthConfig) {\n authConfig.value = config\n }\n\n function setUsername(name: string) {\n username.value = name\n }\n\n function setError(message: string | null) {\n error.value = message\n }\n\n function setLoading(loading: boolean) {\n isLoading.value = loading\n }\n\n function logout() {\n clearToken()\n }\n\n return {\n // State\n token,\n tokenExpires,\n username,\n userInfo,\n authConfig,\n isInitialized,\n isLoading,\n error,\n\n // Computed\n isAuthenticated,\n needsAuth,\n isAdmin,\n userType,\n permissions,\n canAccessAdmin,\n canRegister,\n\n // Actions\n initialize,\n setToken,\n clearToken,\n setAuthConfig,\n setUsername,\n setUserInfo,\n setError,\n setLoading,\n hasPermission,\n hasAnyPermission: hasAnyPermissionForUser,\n canAccessPlugin,\n logout,\n }\n})\n"],"mappings":"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"}
@@ -16,8 +16,8 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
16
16
  onApply?: ((result: AutoGroupResult) => any) | undefined;
17
17
  }>, {
18
18
  samples: string[];
19
- experimentId: number;
20
19
  designData: Record<string, unknown>;
20
+ experimentId: number;
21
21
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
22
22
  wizardRef: ({
23
23
  $: import('vue').ComponentInternalInstance;
@@ -11,7 +11,7 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
11
11
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
12
12
  }>, {
13
13
  size: "sm" | "md" | "lg";
14
- modelValue: boolean;
15
14
  disabled: boolean;
15
+ modelValue: boolean;
16
16
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLLabelElement>;
17
17
  export default _default;
@@ -11,9 +11,9 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
11
11
  }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
12
12
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
13
13
  }>, {
14
- size: "sm" | "md" | "lg";
15
14
  reverse: boolean;
16
- modelValue: boolean;
15
+ size: "sm" | "md" | "lg";
17
16
  disabled: boolean;
17
+ modelValue: boolean;
18
18
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
19
19
  export default _default;
@@ -96,8 +96,8 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {},
96
96
  error: string | null;
97
97
  message: string;
98
98
  status: TemplateWorkspaceStatus;
99
- loading: boolean;
100
99
  actions: TemplateWorkspaceActions;
100
+ loading: boolean;
101
101
  dense: boolean;
102
102
  currentExperimentId: number;
103
103
  kind: WorkspaceKind;
@@ -69,8 +69,8 @@ declare function __VLS_template(): {
69
69
  };
70
70
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
71
71
  declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
72
- readonly: boolean;
73
72
  label: string;
73
+ readonly: boolean;
74
74
  message: string;
75
75
  status: PackWorkspaceStatus;
76
76
  actions: PackWorkspaceActions;
@@ -63,8 +63,8 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {},
63
63
  "onUpdate:values"?: ((values: BioTemplateControlValues) => any) | undefined;
64
64
  }>, {
65
65
  values: BioTemplateControlValues;
66
- modelValue: BioTemplateControlValues;
67
66
  readonly: boolean;
67
+ modelValue: BioTemplateControlValues;
68
68
  initialValues: BioTemplateControlValues;
69
69
  dense: boolean;
70
70
  sidebarWidth: string;
@@ -133,9 +133,9 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {},
133
133
  sidebarSubtitle: string;
134
134
  sidebarBadge: string | number;
135
135
  sidebarVariant: DoseDesignSidebarVariant;
136
+ plateId: string;
136
137
  workspace: UseControlWorkspaceReturn<ControlSchema>;
137
138
  doseDesignOptions: DoseDesignControlModelOptions;
138
- plateId: string;
139
139
  doseId: string;
140
140
  wellPlateProps: ComponentProps;
141
141
  doseCalculatorProps: ComponentProps;
@@ -15,9 +15,9 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
15
15
  onMw?: ((mw: number | null) => any) | undefined;
16
16
  }>, {
17
17
  size: "sm" | "md" | "lg";
18
- modelValue: string;
19
18
  placeholder: string;
20
19
  disabled: boolean;
20
+ modelValue: string;
21
21
  error: boolean;
22
22
  showPreview: boolean;
23
23
  showMW: boolean;
@@ -0,0 +1,22 @@
1
+ import { InstrumentAlert } from '../types';
2
+ interface Props {
3
+ alerts?: InstrumentAlert[];
4
+ title?: string;
5
+ acknowledgeable?: boolean;
6
+ emptyMessage?: string;
7
+ filteredEmptyMessage?: string;
8
+ locale?: string;
9
+ }
10
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
11
+ acknowledge: (alert: InstrumentAlert) => any;
12
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
13
+ onAcknowledge?: ((alert: InstrumentAlert) => any) | undefined;
14
+ }>, {
15
+ title: string;
16
+ locale: string;
17
+ emptyMessage: string;
18
+ alerts: InstrumentAlert[];
19
+ acknowledgeable: boolean;
20
+ filteredEmptyMessage: string;
21
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
22
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import { InstrumentState } from '../types';
2
+ interface Props {
3
+ state: InstrumentState | string;
4
+ label?: string;
5
+ pulseWhenRunning?: boolean;
6
+ }
7
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
8
+ label: string;
9
+ pulseWhenRunning: boolean;
10
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLSpanElement>;
11
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import { InstrumentStatus } from '../types';
2
+ interface Props {
3
+ status: InstrumentStatus;
4
+ name?: string;
5
+ showPlaceholders?: boolean;
6
+ locale?: string;
7
+ }
8
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
9
+ name: string;
10
+ locale: string;
11
+ showPlaceholders: boolean;
12
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
13
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import { LcmsSequenceItem, LcmsSequenceTableColumn } from '../lcms';
2
+ interface Props {
3
+ items?: LcmsSequenceItem[];
4
+ columns?: LcmsSequenceTableColumn[];
5
+ editable?: boolean;
6
+ maxRows?: number;
7
+ showMoreLabel?: boolean;
8
+ emptyMessage?: string;
9
+ }
10
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
11
+ remove: (index: number) => any;
12
+ reorder: (fromIndex: number, toIndex: number) => any;
13
+ duplicate: (index: number) => any;
14
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
15
+ onRemove?: ((index: number) => any) | undefined;
16
+ onReorder?: ((fromIndex: number, toIndex: number) => any) | undefined;
17
+ onDuplicate?: ((index: number) => any) | undefined;
18
+ }>, {
19
+ items: LcmsSequenceItem[];
20
+ columns: LcmsSequenceTableColumn[];
21
+ editable: boolean;
22
+ emptyMessage: string;
23
+ maxRows: number;
24
+ showMoreLabel: boolean;
25
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
26
+ export default _default;
@@ -8,6 +8,7 @@ interface Props {
8
8
  indeterminate?: boolean;
9
9
  steps?: string[];
10
10
  currentStep?: number;
11
+ ariaLabel?: string;
11
12
  }
12
13
  declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
13
14
  size: "sm" | "md" | "lg";
@@ -1,4 +1,4 @@
1
- import { Rack, WellPlateSize, WellEditData } from '../types';
1
+ import { Rack, WellPlateSize, WellEditData, Well, WellEditField, WellSampleDropData, RackSampleDropMapper } from '../types';
2
2
  interface Props {
3
3
  modelValue?: Rack[];
4
4
  activeRackId?: string;
@@ -10,10 +10,39 @@ interface Props {
10
10
  wellPlateSize?: WellPlateSize;
11
11
  showLegend?: boolean;
12
12
  showBadges?: boolean;
13
+ allowSampleDrop?: boolean;
14
+ sampleDropMapper?: RackSampleDropMapper;
13
15
  }
14
- declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
16
+ interface RackWellEditorSlotProps {
17
+ rack?: Rack;
18
+ rackId: string;
19
+ wellId: string;
20
+ wellData?: Partial<Well>;
21
+ editFields: WellEditField[];
22
+ defaultInjectionVolume: number;
23
+ position: {
24
+ x: number;
25
+ y: number;
26
+ };
27
+ save: (data: WellEditData) => void;
28
+ clear: () => void;
29
+ close: () => void;
30
+ }
31
+ declare function __VLS_template(): {
32
+ attrs: Partial<{}>;
33
+ slots: Readonly<{
34
+ 'well-editor'?: (props: RackWellEditorSlotProps) => unknown;
35
+ }> & {
36
+ 'well-editor'?: (props: RackWellEditorSlotProps) => unknown;
37
+ };
38
+ refs: {};
39
+ rootEl: HTMLDivElement;
40
+ };
41
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
42
+ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
15
43
  "update:modelValue": (racks: Rack[]) => any;
16
44
  "well-edit": (rackId: string, wellId: string, data: WellEditData) => any;
45
+ "sample-drop": (rackId: string, wellId: string, data: WellSampleDropData, event: DragEvent) => any;
17
46
  "update:activeRackId": (rackId: string) => any;
18
47
  "rack-add": (rack: Rack) => any;
19
48
  "rack-remove": (rackId: string) => any;
@@ -21,20 +50,29 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
21
50
  }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
22
51
  "onUpdate:modelValue"?: ((racks: Rack[]) => any) | undefined;
23
52
  "onWell-edit"?: ((rackId: string, wellId: string, data: WellEditData) => any) | undefined;
53
+ "onSample-drop"?: ((rackId: string, wellId: string, data: WellSampleDropData, event: DragEvent) => any) | undefined;
24
54
  "onUpdate:activeRackId"?: ((rackId: string) => any) | undefined;
25
55
  "onRack-add"?: ((rack: Rack) => any) | undefined;
26
56
  "onRack-remove"?: ((rackId: string) => any) | undefined;
27
57
  "onRack-reorder"?: ((rackIds: string[]) => any) | undefined;
28
58
  }>, {
29
- modelValue: Rack[];
30
59
  readonly: boolean;
60
+ modelValue: Rack[];
31
61
  showLegend: boolean;
32
62
  editable: boolean;
33
63
  showBadges: boolean;
64
+ allowSampleDrop: boolean;
34
65
  activeRackId: string;
35
66
  maxRacks: number;
36
67
  minRacks: number;
37
68
  allowReorder: boolean;
38
69
  wellPlateSize: WellPlateSize;
70
+ sampleDropMapper: RackSampleDropMapper;
39
71
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
72
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
40
73
  export default _default;
74
+ type __VLS_WithTemplateSlots<T, S> = T & {
75
+ new (): {
76
+ $slots: S;
77
+ };
78
+ };
@@ -21,8 +21,8 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
21
21
  onEdit?: ((reagent: Reagent) => any) | undefined;
22
22
  onReorder?: ((reagentId: string, fromIndex: number, toIndex: number) => any) | undefined;
23
23
  }>, {
24
- modelValue: Reagent[];
25
24
  readonly: boolean;
25
+ modelValue: Reagent[];
26
26
  columns: ReagentColumn[];
27
27
  sortable: boolean;
28
28
  searchable: boolean;