@morscherlab/mint-sdk 1.5.0-beta.6 → 1.5.0-beta.8

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 (106) hide show
  1. package/dist/{AlertBox-CexONPhA.js → AlertBox-Cai0w7gF.js} +3 -3
  2. package/dist/{AlertBox-CexONPhA.js.map → AlertBox-Cai0w7gF.js.map} +1 -1
  3. package/dist/{AppSidebar-FxlF5_dI.js → AppSidebar-C1DT4nsZ.js} +351 -90
  4. package/dist/AppSidebar-C1DT4nsZ.js.map +1 -0
  5. package/dist/{ConfirmDialog-D9QXFpsy.js → ConfirmDialog-BjFsOpBe.js} +2 -2
  6. package/dist/{ConfirmDialog-D9QXFpsy.js.map → ConfirmDialog-BjFsOpBe.js.map} +1 -1
  7. package/dist/{ExperimentPopover-Bbd6RaoH.js → ExperimentPopover-DYy_s0kI.js} +25 -37
  8. package/dist/ExperimentPopover-DYy_s0kI.js.map +1 -0
  9. package/dist/{ExperimentSelectorModal-CUkKmgfr.js → ExperimentSelectorModal-Bfh5bdkv.js} +5 -5
  10. package/dist/{ExperimentSelectorModal-CUkKmgfr.js.map → ExperimentSelectorModal-Bfh5bdkv.js.map} +1 -1
  11. package/dist/{SegmentedControl-C-sckoJZ.js → SegmentedControl-B8KgyOjd.js} +2 -2
  12. package/dist/{SegmentedControl-C-sckoJZ.js.map → SegmentedControl-B8KgyOjd.js.map} +1 -1
  13. package/dist/{SettingsModal-BIC0dAYc.js → SettingsModal-DPNblTe9.js} +7 -7
  14. package/dist/{SettingsModal-BIC0dAYc.js.map → SettingsModal-DPNblTe9.js.map} +1 -1
  15. package/dist/__tests__/components/AppTopBarCompact.test.d.ts +1 -0
  16. package/dist/__tests__/components/AppTopBarCompactReset.test.d.ts +1 -0
  17. package/dist/__tests__/components/AutoGroupModal.experimentLoad.test.d.ts +1 -0
  18. package/dist/components/AppTopBar.compact.d.ts +5 -0
  19. package/dist/components/AppTopBar.vue.d.ts +17 -17
  20. package/dist/components/PluginWorkspaceView.vue.d.ts +4 -0
  21. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -2
  22. package/dist/components/internal/LucideIconInternal.vue.d.ts +17 -0
  23. package/dist/composables/appLayoutSidebar.d.ts +9 -0
  24. package/dist/composables/useVersionedSave.d.ts +5 -2
  25. package/dist/{controlSchemaModel-C_XqpkgE.js → controlSchemaModel-BtFNZj8t.js} +2 -2
  26. package/dist/{controlSchemaModel-C_XqpkgE.js.map → controlSchemaModel-BtFNZj8t.js.map} +1 -1
  27. package/dist/{data-CfY7o8QC.js → data-CJztFns8.js} +31 -15
  28. package/dist/{data-CfY7o8QC.js.map → data-CJztFns8.js.map} +1 -1
  29. package/dist/data.js +8 -8
  30. package/dist/{experimentStatus-DCn2QKG7.js → experimentStatus-Deokk7Br.js} +2 -2
  31. package/dist/{experimentStatus-DCn2QKG7.js.map → experimentStatus-Deokk7Br.js.map} +1 -1
  32. package/dist/index.js +14 -14
  33. package/dist/{install-QF3Sh82O.js → install-9FkKs0iW.js} +14 -15
  34. package/dist/{install-QF3Sh82O.js.map → install-9FkKs0iW.js.map} +1 -1
  35. package/dist/install.js +1 -1
  36. package/dist/{lab-BcX5JBSY.js → lab-BYhb_cJI.js} +22 -14
  37. package/dist/lab-BYhb_cJI.js.map +1 -0
  38. package/dist/lab.js +4 -4
  39. package/dist/{records-BAymyHAn.js → records-GtiVMlTQ.js} +198 -62
  40. package/dist/records-GtiVMlTQ.js.map +1 -0
  41. package/dist/{runtime-DngeJtdq.js → runtime-DcMsvlaS.js} +29 -12
  42. package/dist/runtime-DcMsvlaS.js.map +1 -0
  43. package/dist/runtime.js +6 -6
  44. package/dist/{shell-CWZi97nW.js → shell-XZYkAZS_.js} +5 -5
  45. package/dist/{shell-CWZi97nW.js.map → shell-XZYkAZS_.js.map} +1 -1
  46. package/dist/shell.js +5 -5
  47. package/dist/styles.css +136 -12
  48. package/dist/types/components.d.ts +22 -2
  49. package/dist/types/index.d.ts +1 -1
  50. package/dist/{useDropdownState-uFIz6Yv8.js → useDropdownState-CcBzUYZ6.js} +14 -5
  51. package/dist/useDropdownState-CcBzUYZ6.js.map +1 -0
  52. package/dist/{useExperimentSamples-DEDAKa2E.js → useExperimentSamples-CpNXvpUn.js} +3 -3
  53. package/dist/{useExperimentSamples-DEDAKa2E.js.map → useExperimentSamples-CpNXvpUn.js.map} +1 -1
  54. package/dist/{useListReorder-W1bzK_bo.js → useListReorder-Bp4EAI2w.js} +3 -3
  55. package/dist/{useListReorder-W1bzK_bo.js.map → useListReorder-Bp4EAI2w.js.map} +1 -1
  56. package/dist/{useRackEditor-Bmtuo0aj.js → useRackEditor-i2bdPUFf.js} +8 -8
  57. package/dist/{useRackEditor-Bmtuo0aj.js.map → useRackEditor-i2bdPUFf.js.map} +1 -1
  58. package/dist/{useRealtime-jOetF2mM.js → useRealtime-BLQEjbuq.js} +3 -3
  59. package/dist/{useRealtime-jOetF2mM.js.map → useRealtime-BLQEjbuq.js.map} +1 -1
  60. package/dist/useRequest-CXyPw3eh.js +76 -0
  61. package/dist/useRequest-CXyPw3eh.js.map +1 -0
  62. package/dist/utils/deprecation.d.ts +2 -0
  63. package/dist/utils/lucideIcon.d.ts +4 -0
  64. package/package.json +1 -1
  65. package/src/__tests__/components/AppTopBar.test.ts +102 -20
  66. package/src/__tests__/components/AppTopBarCompact.test.ts +65 -0
  67. package/src/__tests__/components/AppTopBarCompactReset.test.ts +24 -0
  68. package/src/__tests__/components/AutoGroupModal.experimentLoad.test.ts +58 -0
  69. package/src/__tests__/components/BaseModal.test.ts +33 -2
  70. package/src/__tests__/components/ExperimentPopover.test.ts +32 -0
  71. package/src/__tests__/components/PluginWorkspaceView.test.ts +1 -1
  72. package/src/__tests__/composables/useJobCenter.test.ts +35 -0
  73. package/src/__tests__/composables/useVersionedSave.test.ts +71 -6
  74. package/src/__tests__/styles/menusShellRefresh.test.ts +5 -0
  75. package/src/components/AppLayout.story.vue +5 -5
  76. package/src/components/AppLayout.vue +13 -1
  77. package/src/components/AppTopBar.compact.ts +60 -0
  78. package/src/components/AppTopBar.story.vue +39 -14
  79. package/src/components/AppTopBar.vue +222 -89
  80. package/src/components/BaseModal.vue +16 -5
  81. package/src/components/ExperimentPopover.story.vue +2 -2
  82. package/src/components/ExperimentPopover.vue +6 -22
  83. package/src/components/GeneratedPluginView.vue +0 -1
  84. package/src/components/PluginWorkspaceView.vue +8 -0
  85. package/src/components/internal/AppTopBarPageSelectorInternal.vue +12 -0
  86. package/src/components/internal/AutoGroupModalInternal.vue +14 -3
  87. package/src/components/internal/LucideIconInternal.vue +23 -0
  88. package/src/composables/appLayoutSidebar.ts +11 -0
  89. package/src/composables/useJobCenter.ts +21 -1
  90. package/src/composables/usePluginWorkspace.ts +1 -1
  91. package/src/composables/useVersionedSave.ts +32 -7
  92. package/src/styles/components/app-layout.css +5 -0
  93. package/src/styles/components/app-top-bar.css +128 -8
  94. package/src/types/components.ts +23 -2
  95. package/src/types/index.ts +1 -0
  96. package/src/utils/deprecation.ts +8 -0
  97. package/src/utils/lucideIcon.ts +25 -0
  98. package/src/utils/lucideIconIndex.d.ts +2 -0
  99. package/dist/AppSidebar-FxlF5_dI.js.map +0 -1
  100. package/dist/ExperimentPopover-Bbd6RaoH.js.map +0 -1
  101. package/dist/lab-BcX5JBSY.js.map +0 -1
  102. package/dist/records-BAymyHAn.js.map +0 -1
  103. package/dist/runtime-DngeJtdq.js.map +0 -1
  104. package/dist/useDropdownState-uFIz6Yv8.js.map +0 -1
  105. package/dist/useRequest-D9-3BS-3.js +0 -215
  106. package/dist/useRequest-D9-3BS-3.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ import { ComputedRef, InjectionKey } from 'vue';
2
+ /** The responsive sidebar drawer of an AppLayout; its AppTopBar renders the drawer button. */
3
+ export interface AppLayoutSidebarDrawer {
4
+ open: ComputedRef<boolean>;
5
+ toggle: () => void;
6
+ openLabel: ComputedRef<string>;
7
+ closeLabel: ComputedRef<string>;
8
+ }
9
+ export declare const APP_LAYOUT_SIDEBAR_KEY: InjectionKey<AppLayoutSidebarDrawer>;
@@ -21,8 +21,11 @@ export interface UseVersionedSaveOptions<T> {
21
21
  /**
22
22
  * Refetch the entity and reset the form to it. The user's edits are discarded.
23
23
  * Reject when no fresh record arrives: the form then keeps the edits and the conflict.
24
+ * `auto` is true for the refetch after another user's write on a clean form: when
25
+ * the form holds edits by the time the record arrives, skip the reset (the stale
26
+ * banner then shows the write).
24
27
  */
25
- reload: () => unknown;
28
+ reload: (auto?: boolean) => unknown;
26
29
  /**
27
30
  * The realtime topic of the open entity (`experiment:42`). `null` turns the
28
31
  * stale banner off: pass it while the form is closed or the platform's
@@ -37,7 +40,7 @@ export interface UseVersionedSaveOptions<T> {
37
40
  fieldLabel?: (field: string) => string;
38
41
  }
39
42
  export interface UseVersionedSaveReturn<T> {
40
- /** Save with `If-Match`. Resolves `undefined` on a 412: `conflict` is then set. Other errors reject. */
43
+ /** Save with `If-Match`. Resolves `undefined` on a 412 (`conflict` set, `stale` cleared) and, unsent, while a save runs. Other errors reject. */
41
44
  save: () => Promise<T | undefined>;
42
45
  /** Save again on top of the version the 412 reported. Resolves `undefined` on another 412. */
43
46
  overwrite: () => Promise<T | undefined>;
@@ -1,4 +1,4 @@
1
- import { f as omitUndefined, s as normalizeControlDefinition } from "./useListReorder-W1bzK_bo.js";
1
+ import { f as omitUndefined, s as normalizeControlDefinition } from "./useListReorder-Bp4EAI2w.js";
2
2
  //#region src/composables/controlSchemaModel.ts
3
3
  function isControlModelBinding(model) {
4
4
  return typeof model === "object" && model !== null && "controls" in model && "controlOptions" in model;
@@ -92,4 +92,4 @@ function registerSectionOptions(target, sectionId, options) {
92
92
  //#endregion
93
93
  export { isControlModelBinding as n, defineControlModel as t };
94
94
 
95
- //# sourceMappingURL=controlSchemaModel-C_XqpkgE.js.map
95
+ //# sourceMappingURL=controlSchemaModel-BtFNZj8t.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"controlSchemaModel-C_XqpkgE.js","names":[],"sources":["../src/composables/controlSchemaModel.ts"],"sourcesContent":["import type {\n ControlModel,\n ControlModelBinding,\n ControlModelSectionConfig,\n ControlSchema,\n ControlSectionConfig,\n ControlSidebarConfig,\n ControlViewConfig,\n ControlWorkspaceOptions,\n} from './controlSchemaTypes'\nimport {\n normalizeControlDefinition,\n} from './controlSchemaNormalize'\nimport {\n omitUndefined,\n} from './controlSchemaUtils'\n\nexport function isControlModelBinding<TBinding extends ControlModelBinding = ControlModelBinding>(\n model: unknown,\n): model is TBinding {\n return (\n typeof model === 'object'\n && model !== null\n && 'controls' in model\n && 'controlOptions' in model\n )\n}\n\nexport function resolveControlModel(\n model: ControlModel | ControlModelBinding | undefined,\n): ControlModelBinding | undefined {\n if (model === undefined) return undefined\n return isControlModelBinding(model) ? model : defineControlModel(model)\n}\n\n/**\n * Create a complete control model binding for FormBuilder, SettingsModal and the PluginWorkspaceView sidebar from a simple controls data model.\n *\n * @example Recommended\n * ```ts\n * const workspaceModel = defineControlModel({\n * controls: { threshold: { type: 'number', default: 0.05 } },\n * })\n * ```\n */\nexport function defineControlModel(model: ControlModel): ControlModelBinding {\n const {\n controls: rootControls,\n sections: rootSections,\n views: modelViews,\n components,\n componentBindings,\n componentProps,\n componentPropsById,\n ...baseOptions\n } = model\n const resolvedComponentBindings = componentBindings ?? components\n const controls: ControlSchema = {}\n const views: Record<string, ControlViewConfig> = {}\n const sections: Record<string, ControlSectionConfig> = {}\n\n const defaultViewId = model.view ?? 'default'\n const defaultSectionId = model.section ?? 'controls'\n\n if (rootControls) {\n registerSectionOptions(sections, defaultSectionId, {\n id: defaultSectionId,\n label: model.sectionLabel,\n title: model.sectionLabel,\n columns: model.columns,\n })\n appendModelControls(controls, rootControls, defaultViewId, defaultSectionId)\n }\n\n for (const [sectionId, section] of Object.entries(rootSections ?? {})) {\n registerSectionOptions(sections, sectionId, controlModelSectionOptions(section))\n appendModelControls(controls, section.controls, defaultViewId, sectionId, section.sidebar)\n }\n\n for (const [viewId, view] of Object.entries(modelViews ?? {})) {\n const {\n controls: viewControls,\n sections: viewSections,\n section,\n sectionLabel,\n sectionDescription,\n ...viewConfig\n } = view\n\n views[viewId] = omitUndefined(viewConfig)\n\n if (viewControls) {\n const sectionId = section ?? `${viewId}-controls`\n const label = sectionLabel ?? view.label\n registerSectionOptions(sections, sectionId, {\n id: sectionId,\n label,\n title: label,\n description: sectionDescription,\n columns: model.columns,\n })\n appendModelControls(controls, viewControls, viewId, sectionId)\n }\n\n for (const [sectionKey, sectionConfig] of Object.entries(viewSections ?? {})) {\n const sectionId = sectionConfig.id ?? `${viewId}-${sectionKey}`\n registerSectionOptions(sections, sectionId, controlModelSectionOptions(sectionConfig))\n appendModelControls(controls, sectionConfig.controls, viewId, sectionId, sectionConfig.sidebar)\n }\n }\n\n const controlOptions: ControlWorkspaceOptions = {\n ...baseOptions,\n }\n\n if (Object.keys(views).length > 0) {\n controlOptions.views = views\n }\n\n if (Object.keys(sections).length > 0) {\n controlOptions.sections = sections\n }\n\n return {\n controls,\n controlOptions,\n ...(resolvedComponentBindings === undefined ? {} : { componentBindings: resolvedComponentBindings }),\n ...(componentProps === undefined ? {} : { componentProps }),\n ...(componentPropsById === undefined ? {} : { componentPropsById }),\n }\n}\n\nfunction appendModelControls(\n target: ControlSchema,\n source: ControlSchema,\n viewId: string,\n sectionId: string,\n sidebar?: boolean | ControlSidebarConfig,\n): void {\n for (const [name, input] of Object.entries(source)) {\n if (Object.prototype.hasOwnProperty.call(target, name)) {\n throw new Error(\n `Duplicate control \"${name}\" in defineControlModel(). Control names must be unique across views and sections.`,\n )\n }\n\n const definition = normalizeControlDefinition(input)\n target[name] = omitUndefined({\n ...definition,\n view: definition.view ?? viewId,\n section: definition.section ?? sectionId,\n sidebar: definition.sidebar ?? sidebar,\n })\n }\n}\n\nfunction controlModelSectionOptions(section: ControlModelSectionConfig): ControlSectionConfig {\n const { controls: _controls, sidebar: _sidebar, ...options } = section\n return omitUndefined(options)\n}\n\nfunction registerSectionOptions(\n target: Record<string, ControlSectionConfig>,\n sectionId: string,\n options: ControlSectionConfig,\n): void {\n target[sectionId] = omitUndefined({\n ...(target[sectionId] ?? {}),\n ...options,\n id: sectionId,\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"controlSchemaModel-BtFNZj8t.js","names":[],"sources":["../src/composables/controlSchemaModel.ts"],"sourcesContent":["import type {\n ControlModel,\n ControlModelBinding,\n ControlModelSectionConfig,\n ControlSchema,\n ControlSectionConfig,\n ControlSidebarConfig,\n ControlViewConfig,\n ControlWorkspaceOptions,\n} from './controlSchemaTypes'\nimport {\n normalizeControlDefinition,\n} from './controlSchemaNormalize'\nimport {\n omitUndefined,\n} from './controlSchemaUtils'\n\nexport function isControlModelBinding<TBinding extends ControlModelBinding = ControlModelBinding>(\n model: unknown,\n): model is TBinding {\n return (\n typeof model === 'object'\n && model !== null\n && 'controls' in model\n && 'controlOptions' in model\n )\n}\n\nexport function resolveControlModel(\n model: ControlModel | ControlModelBinding | undefined,\n): ControlModelBinding | undefined {\n if (model === undefined) return undefined\n return isControlModelBinding(model) ? model : defineControlModel(model)\n}\n\n/**\n * Create a complete control model binding for FormBuilder, SettingsModal and the PluginWorkspaceView sidebar from a simple controls data model.\n *\n * @example Recommended\n * ```ts\n * const workspaceModel = defineControlModel({\n * controls: { threshold: { type: 'number', default: 0.05 } },\n * })\n * ```\n */\nexport function defineControlModel(model: ControlModel): ControlModelBinding {\n const {\n controls: rootControls,\n sections: rootSections,\n views: modelViews,\n components,\n componentBindings,\n componentProps,\n componentPropsById,\n ...baseOptions\n } = model\n const resolvedComponentBindings = componentBindings ?? components\n const controls: ControlSchema = {}\n const views: Record<string, ControlViewConfig> = {}\n const sections: Record<string, ControlSectionConfig> = {}\n\n const defaultViewId = model.view ?? 'default'\n const defaultSectionId = model.section ?? 'controls'\n\n if (rootControls) {\n registerSectionOptions(sections, defaultSectionId, {\n id: defaultSectionId,\n label: model.sectionLabel,\n title: model.sectionLabel,\n columns: model.columns,\n })\n appendModelControls(controls, rootControls, defaultViewId, defaultSectionId)\n }\n\n for (const [sectionId, section] of Object.entries(rootSections ?? {})) {\n registerSectionOptions(sections, sectionId, controlModelSectionOptions(section))\n appendModelControls(controls, section.controls, defaultViewId, sectionId, section.sidebar)\n }\n\n for (const [viewId, view] of Object.entries(modelViews ?? {})) {\n const {\n controls: viewControls,\n sections: viewSections,\n section,\n sectionLabel,\n sectionDescription,\n ...viewConfig\n } = view\n\n views[viewId] = omitUndefined(viewConfig)\n\n if (viewControls) {\n const sectionId = section ?? `${viewId}-controls`\n const label = sectionLabel ?? view.label\n registerSectionOptions(sections, sectionId, {\n id: sectionId,\n label,\n title: label,\n description: sectionDescription,\n columns: model.columns,\n })\n appendModelControls(controls, viewControls, viewId, sectionId)\n }\n\n for (const [sectionKey, sectionConfig] of Object.entries(viewSections ?? {})) {\n const sectionId = sectionConfig.id ?? `${viewId}-${sectionKey}`\n registerSectionOptions(sections, sectionId, controlModelSectionOptions(sectionConfig))\n appendModelControls(controls, sectionConfig.controls, viewId, sectionId, sectionConfig.sidebar)\n }\n }\n\n const controlOptions: ControlWorkspaceOptions = {\n ...baseOptions,\n }\n\n if (Object.keys(views).length > 0) {\n controlOptions.views = views\n }\n\n if (Object.keys(sections).length > 0) {\n controlOptions.sections = sections\n }\n\n return {\n controls,\n controlOptions,\n ...(resolvedComponentBindings === undefined ? {} : { componentBindings: resolvedComponentBindings }),\n ...(componentProps === undefined ? {} : { componentProps }),\n ...(componentPropsById === undefined ? {} : { componentPropsById }),\n }\n}\n\nfunction appendModelControls(\n target: ControlSchema,\n source: ControlSchema,\n viewId: string,\n sectionId: string,\n sidebar?: boolean | ControlSidebarConfig,\n): void {\n for (const [name, input] of Object.entries(source)) {\n if (Object.prototype.hasOwnProperty.call(target, name)) {\n throw new Error(\n `Duplicate control \"${name}\" in defineControlModel(). Control names must be unique across views and sections.`,\n )\n }\n\n const definition = normalizeControlDefinition(input)\n target[name] = omitUndefined({\n ...definition,\n view: definition.view ?? viewId,\n section: definition.section ?? sectionId,\n sidebar: definition.sidebar ?? sidebar,\n })\n }\n}\n\nfunction controlModelSectionOptions(section: ControlModelSectionConfig): ControlSectionConfig {\n const { controls: _controls, sidebar: _sidebar, ...options } = section\n return omitUndefined(options)\n}\n\nfunction registerSectionOptions(\n target: Record<string, ControlSectionConfig>,\n sectionId: string,\n options: ControlSectionConfig,\n): void {\n target[sectionId] = omitUndefined({\n ...(target[sectionId] ?? {}),\n ...options,\n id: sectionId,\n })\n}\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
- import { a as BaseButton_default, n as BaseModal_default, o as __exportAll } from "./useDropdownState-uFIz6Yv8.js";
1
+ import { a as BaseButton_default, n as BaseModal_default, o as __exportAll } from "./useDropdownState-CcBzUYZ6.js";
2
2
  import { d as MintApiError, o as useApi, t as useExperimentStore } from "./experiment-DyO54FQB.js";
3
- import { A as formatRelativeTime, C as formatExperimentDate, I as FormField_default, K as BaseInput_default, S as experimentIdFromRoute, T as FileUploader_default, V as BaseSelect_default, _ as APP_EXPERIMENT_KEY, b as SORT_OPTIONS, c as SecretInput_default, i as getInjectedPlatformContext, n as ResourcePickerListInternal_default, r as Skeleton_default, s as TagsInput_default, u as pluginSecrets_exports, v as useAppExperiment, w as resolveExperimentCode, x as datePresetToISO, y as DATE_PRESET_OPTIONS, z as BaseCheckbox_default } from "./records-BAymyHAn.js";
4
- import { t as SegmentedControl_default } from "./SegmentedControl-C-sckoJZ.js";
5
- import { a as normalizeSearchQuery, i as candidateMatchesSearch, n as DataStateInternal_default, o as useTextSearch, t as AlertBox_default } from "./AlertBox-CexONPhA.js";
6
- import { n as ActionMenu_default, t as useRequest } from "./useRequest-D9-3BS-3.js";
3
+ import { B as BaseCheckbox_default, C as formatExperimentDate, E as FileUploader_default, H as BaseSelect_default, L as FormField_default, S as experimentIdFromRoute, T as ActionMenu_default, _ as APP_EXPERIMENT_KEY, b as SORT_OPTIONS, c as SecretInput_default, i as getInjectedPlatformContext, j as formatRelativeTime, n as ResourcePickerListInternal_default, q as BaseInput_default, r as Skeleton_default, s as TagsInput_default, u as pluginSecrets_exports, v as useAppExperiment, w as resolveExperimentCode, x as datePresetToISO, y as DATE_PRESET_OPTIONS } from "./records-GtiVMlTQ.js";
4
+ import { t as SegmentedControl_default } from "./SegmentedControl-B8KgyOjd.js";
5
+ import { a as normalizeSearchQuery, i as candidateMatchesSearch, n as DataStateInternal_default, o as useTextSearch, t as AlertBox_default } from "./AlertBox-Cai0w7gF.js";
7
6
  import { hasAllPermissions } from "./permissions.js";
8
- import { i as JobsStatusTray_default, r as useRealtime } from "./useRealtime-jOetF2mM.js";
9
- import { r as useExperimentSelector, t as ExperimentSelectorModal_default } from "./ExperimentSelectorModal-CUkKmgfr.js";
10
- import { t as experimentStatus_exports } from "./experimentStatus-DCn2QKG7.js";
7
+ import { i as JobsStatusTray_default, r as useRealtime } from "./useRealtime-BLQEjbuq.js";
8
+ import { t as useRequest } from "./useRequest-CXyPw3eh.js";
9
+ import { r as useExperimentSelector, t as ExperimentSelectorModal_default } from "./ExperimentSelectorModal-Bfh5bdkv.js";
10
+ import { t as experimentStatus_exports } from "./experimentStatus-Deokk7Br.js";
11
11
  import { t as ANALYSIS_FILE_ARTIFACT_SCHEMA } from "./analysisArtifactTypes-Cy3D0Ipg.js";
12
- import { t as ExperimentPopover_default } from "./ExperimentPopover-Bbd6RaoH.js";
13
- import { a as readTableFileAsCsv, c as useExperimentData, d as unwrapExperimentDesignData, i as readFileAsText, l as extractSampleNamesFromDesignData, n as detectDelimiter, o as useFileImport, r as parseDelimitedText, s as validateImportFile, t as useExperimentSamples, u as extractSampleOptionsFromDesignData } from "./useExperimentSamples-DEDAKa2E.js";
12
+ import { t as ExperimentPopover_default } from "./ExperimentPopover-DYy_s0kI.js";
13
+ import { a as readTableFileAsCsv, c as useExperimentData, d as unwrapExperimentDesignData, i as readFileAsText, l as extractSampleNamesFromDesignData, n as detectDelimiter, o as useFileImport, r as parseDelimitedText, s as validateImportFile, t as useExperimentSamples, u as extractSampleOptionsFromDesignData } from "./useExperimentSamples-CpNXvpUn.js";
14
14
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, getCurrentInstance, getCurrentScope, h, isRef, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onScopeDispose, openBlock, readonly, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toValue, unref, useTemplateRef, watch, withCtx, withModifiers } from "vue";
15
15
  import { CircleCheck, CircleDashed, CircleMinus, CircleX, CloudUpload, File, Loader, RefreshCw, TriangleAlert, X } from "lucide-vue-next";
16
16
  //#region src/composables/useArtifacts.ts
@@ -3280,7 +3280,9 @@ function useVersionedSave(options) {
3280
3280
  const conflict = ref(null);
3281
3281
  const stale = ref(null);
3282
3282
  const fieldLabel = options.fieldLabel ?? fieldNameLabel;
3283
+ let reloadToken = 0;
3283
3284
  async function send(version) {
3285
+ if (saving.value) return void 0;
3284
3286
  saving.value = true;
3285
3287
  try {
3286
3288
  const headers = version == null ? {} : { "If-Match": `"v${version}"` };
@@ -3292,22 +3294,35 @@ function useVersionedSave(options) {
3292
3294
  const refused = conflictVersion(cause);
3293
3295
  if (!refused) throw cause;
3294
3296
  conflict.value = refused;
3297
+ stale.value = null;
3295
3298
  return;
3296
3299
  } finally {
3297
3300
  saving.value = false;
3298
3301
  }
3299
3302
  }
3300
3303
  async function reload() {
3304
+ reloadToken += 1;
3301
3305
  await options.reload();
3302
3306
  conflict.value = null;
3303
3307
  stale.value = null;
3304
3308
  }
3305
- function onEvent(event) {
3306
- if (event.type === "resync" || saving.value || event.topic !== toValue(options.topic)) return;
3307
- if (!toValue(options.dirty)) {
3308
- reload().catch(() => {});
3309
+ async function autoReload(event) {
3310
+ const token = ++reloadToken;
3311
+ try {
3312
+ await options.reload(true);
3313
+ } catch {
3309
3314
  return;
3310
3315
  }
3316
+ if (token !== reloadToken || conflict.value) return;
3317
+ if (toValue(options.dirty)) markStale(event);
3318
+ else stale.value = null;
3319
+ }
3320
+ function onEvent(event) {
3321
+ if (event.type === "resync" || saving.value || conflict.value || event.topic !== toValue(options.topic)) return;
3322
+ if (!toValue(options.dirty)) autoReload(event);
3323
+ else markStale(event);
3324
+ }
3325
+ function markStale(event) {
3311
3326
  const actor = event.actor_id && options.userName?.(event.actor_id) || "Someone";
3312
3327
  const previous = stale.value;
3313
3328
  stale.value = {
@@ -3321,6 +3336,7 @@ function useVersionedSave(options) {
3321
3336
  return topic ? [topic] : [];
3322
3337
  }, onEvent);
3323
3338
  watch(() => toValue(options.topic), () => {
3339
+ reloadToken += 1;
3324
3340
  conflict.value = null;
3325
3341
  stale.value = null;
3326
3342
  });
@@ -3863,4 +3879,4 @@ var data_exports = /* @__PURE__ */ __exportAll({
3863
3879
  //#endregion
3864
3880
  export { ArtifactSaveDialog_default as _, usePlatformFilePickerAdapter as a, encodePlatformPickerPath as c, StaleFormBanner_default as d, VersionConflictDialog_default as f, ExperimentCodeBadge_default as g, FilePicker_default as h, useFileBrowser as i, fieldNameLabel as l, AuditTrail_default as m, buildAnalysisArtifactTargetQuery as n, createFilePickerAdapter as o, BatchProgressList_default as p, parseAnalysisArtifactTarget as r, decodePlatformPickerPath as s, data_exports as t, useVersionedSave as u, ArtifactSelectorModal_default as v, useArtifacts as y };
3865
3881
 
3866
- //# sourceMappingURL=data-CfY7o8QC.js.map
3882
+ //# sourceMappingURL=data-CJztFns8.js.map