@feedmepos/mf-menu 0.32.63-dev.1 → 0.32.63-dev.3

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 (83) hide show
  1. package/dist/{App-DhfTGlgM.js → App-DHxlR--3.js} +6 -6
  2. package/dist/{ApplyProduct.vue_vue_type_script_setup_true_lang-C5-8qdJK.js → ApplyProduct.vue_vue_type_script_setup_true_lang-6noIwjis.js} +3 -3
  3. package/dist/{ApplyProductDialog.vue_vue_type_script_setup_true_lang-CXm-0H18.js → ApplyProductDialog.vue_vue_type_script_setup_true_lang-CMI2Nh0n.js} +3 -3
  4. package/dist/{Catalog-WuZJfM6l.js → Catalog-B-S0gygH.js} +22 -22
  5. package/dist/{Category-BeIo7XWY.js → Category-DGDddfLx.js} +4 -4
  6. package/dist/{Category-D-cQQCPS.js → Category-DOhNama9.js} +4 -4
  7. package/dist/{CookingGuide-B-yvD9ZA.js → CookingGuide-CUR57F4P.js} +29 -29
  8. package/dist/{CustomAttributeChip.vue_vue_type_script_setup_true_lang-2_yzXoa4.js → CustomAttributeChip.vue_vue_type_script_setup_true_lang-bIONGM6k.js} +1 -1
  9. package/dist/{Group-CY8lUzQG.js → Group-BsGJ0omP.js} +1 -1
  10. package/dist/{Group-13i5igrS.js → Group-z-0jQPCd.js} +3 -3
  11. package/dist/{Group.vue_vue_type_script_setup_true_lang-DZhxy0tb.js → Group.vue_vue_type_script_setup_true_lang-bBWkJ2Hx.js} +7 -7
  12. package/dist/{GroupMarkupPriceDialog.vue_vue_type_script_setup_true_lang-CWqv-oUd.js → GroupMarkupPriceDialog.vue_vue_type_script_setup_true_lang-BbqcH4sM.js} +19 -19
  13. package/dist/{ImportProductDialog.vue_vue_type_script_setup_true_lang-DTs4Vpdi.js → ImportProductDialog.vue_vue_type_script_setup_true_lang-CVGilzd0.js} +4210 -4210
  14. package/dist/{Ingredient-vrUOW6gk.js → Ingredient-D38IVDXK.js} +4 -4
  15. package/dist/{InventoryBinding.vue_vue_type_script_setup_true_lang-xcVjRjqD.js → InventoryBinding.vue_vue_type_script_setup_true_lang-CKmyz9CP.js} +2 -2
  16. package/dist/{LinkProductSideSheet-DMbJG6wf.js → LinkProductSideSheet-DsBA_o9g.js} +4 -4
  17. package/dist/{MenuSetting-Di2xwm00.js → MenuSetting-D-tln58o.js} +7 -7
  18. package/dist/{OrderPacing-CCe-IcGO.js → OrderPacing-BdCEHKD9.js} +7 -7
  19. package/dist/{PrintRoute-CcfObcHY.js → PrintRoute-DKFMqyeI.js} +10 -10
  20. package/dist/{Product-ChUVnMgG.js → Product-Dzo4ljes.js} +1 -1
  21. package/dist/{Product.vue_vue_type_script_setup_true_lang-C9Qp50hL.js → Product.vue_vue_type_script_setup_true_lang-BtE2aiwU.js} +58 -58
  22. package/dist/{ProductInternalTools-D9HXhgo5.js → ProductInternalTools-Z6XR4zko.js} +14 -14
  23. package/dist/{Products-Bly2ktEC.js → Products-CCo675Ee.js} +63 -63
  24. package/dist/{Publish-C8ubb8Qf.js → Publish-tixV8Of1.js} +107 -107
  25. package/dist/{Recipe-BpMRLsyO.js → Recipe-V9kzxmlf.js} +5 -5
  26. package/dist/{RestaurantAttributesSelector.vue_vue_type_script_setup_true_lang-BD5OCDRn.js → RestaurantAttributesSelector.vue_vue_type_script_setup_true_lang-DBhAzVz3.js} +1 -1
  27. package/dist/{RuleView.vue_vue_type_script_setup_true_lang-Ba3djmX1.js → RuleView.vue_vue_type_script_setup_true_lang-D9DqmAVY.js} +3 -3
  28. package/dist/{Scheduler-CiB4b2Fn.js → Scheduler-0UpDGQKJ.js} +17 -17
  29. package/dist/{ServingSequence-BlcyW-dv.js → ServingSequence-CutiXht7.js} +3 -3
  30. package/dist/{Setting-DqkL6YYU.js → Setting-jyYmoDiq.js} +5 -5
  31. package/dist/{Subcategory-B4Jg_wtT.js → Subcategory-CQSKOLjU.js} +10 -10
  32. package/dist/{Takeaway-5G3f7jWT.js → Takeaway-CQ0m09TB.js} +1 -1
  33. package/dist/{Takeaway-5rFPYYNA.js → Takeaway-DeCthkOI.js} +4 -4
  34. package/dist/{Takeaway.vue_vue_type_script_setup_true_lang-CVsOhg_E.js → Takeaway.vue_vue_type_script_setup_true_lang-FHE6oQ0d.js} +7 -7
  35. package/dist/{TranslationFieldSection.vue_vue_type_script_setup_true_lang-CPqxA6JD.js → TranslationFieldSection.vue_vue_type_script_setup_true_lang-D9Ga3fOj.js} +1 -1
  36. package/dist/{TranslationSideSheet.vue_vue_type_script_setup_true_lang-yrNuTD-3.js → TranslationSideSheet.vue_vue_type_script_setup_true_lang-Bz32rpvX.js} +2 -2
  37. package/dist/TreeEditorOpenner.vue_vue_type_script_setup_true_lang-DCPGAyOm.js +5858 -0
  38. package/dist/{Unit-CAkdmQLg.js → Unit-_XiPfauV.js} +2 -2
  39. package/dist/{Variant-BbLQqbAK.js → Variant-DfdMywhn.js} +6 -6
  40. package/dist/{_id_-Dzacr40I.js → _id_-Yj5av4B4.js} +12 -12
  41. package/dist/{app-4yWs09Fr.js → app-BcGgfvbE.js} +102 -102
  42. package/dist/{app-Deov1985.js → app-CqdVluGs.js} +1 -1
  43. package/dist/app.js +1 -1
  44. package/dist/apps/mf-menu/src/api/media.d.ts +10 -3
  45. package/dist/apps/mf-menu/src/app.d.ts +60 -10
  46. package/dist/apps/mf-menu/src/components/feature/TreeEditor/composable/productImages.d.ts +67 -21
  47. package/dist/apps/mf-menu/src/components/feature/TreeEditor/image/ManageImageDrawer.vue.d.ts +33 -3
  48. package/dist/apps/mf-menu/src/components/feature/TreeEditor/image/ProductImageField.vue.d.ts +31 -1
  49. package/dist/apps/mf-menu/src/components/feature/TreeEditor/image/RegenerateImageDialog.vue.d.ts +10 -0
  50. package/dist/apps/mf-menu/src/helper/menuImport.d.ts +22 -0
  51. package/dist/apps/mf-menu/src/manager/menu/itemOverrider.d.ts +17 -0
  52. package/dist/apps/mf-menu/src/stores/manager/item.d.ts +0 -1
  53. package/dist/apps/mf-menu/src/views/Catalog/Edit/AddProductPopup/ProductDetail.vue.d.ts +9 -3
  54. package/dist/apps/mf-menu/tsconfig.app.tsbuildinfo +1 -1
  55. package/dist/assets/{linked-status-B2WLhKkV.js → linked-status-DdDQXL8Y.js} +3 -3
  56. package/dist/assets/{menu-export-Dcw5a_dN.js → menu-export-CK5bJyLT.js} +4 -4
  57. package/dist/assets/{override-menu-cBe2aMY6.js → override-menu-CHL7Bynw.js} +3 -3
  58. package/dist/assets/{validate-menu-BM-5GK85.js → validate-menu-g2fslPcE.js} +2 -2
  59. package/dist/{catalog-DKygS2Cs.js → catalog-B_yk-l1-.js} +1 -1
  60. package/dist/{catalogSetting-Bn2TplvM.js → catalogSetting-Dl7uIiJm.js} +1 -1
  61. package/dist/{currency-DXgNHtK8.js → currency-BpjSDqef.js} +1 -1
  62. package/dist/dayjs.min-CVH5LqOA.js +7 -0
  63. package/dist/{discardConfirm-DZwzKO-Q.js → discardConfirm-fCmrAVO1.js} +1 -1
  64. package/dist/{index-K-MBqJJo.js → index-CD_omf3p.js} +1 -1
  65. package/dist/{index-B48KLyqg.js → index-Cru6sUb6.js} +5 -5
  66. package/dist/{index-BEocaqRK.js → index-LYc0WKDO.js} +6 -6
  67. package/dist/{index.vue_vue_type_script_setup_true_lang-Nl505vPi.js → index.vue_vue_type_script_setup_true_lang-qgDBinUn.js} +7932 -7868
  68. package/dist/{item-Da3ArD-G.js → item-EPxRgVm0.js} +4904 -4654
  69. package/dist/{jszip.min-Cc2eR4Cq.js → jszip.min-CNgWv4I3.js} +52 -52
  70. package/dist/{linkProducts-GNuUxFEE.js → linkProducts-DvQ0oP1V.js} +6 -6
  71. package/dist/{memberPricing-T-jr7tn1.js → memberPricing-deWSH2K0.js} +1 -1
  72. package/dist/{menu-DSDRAil-.js → menu-DKJ7olgK.js} +1 -1
  73. package/dist/{menuV2-fTlJdjxi.js → menuV2-CB3eZiiP.js} +318 -313
  74. package/dist/mf-menu.css +1 -1
  75. package/dist/{order_pacing-Dgo1fySS.js → order_pacing-DvP19Nxa.js} +5 -5
  76. package/dist/{priceTier-aT_gIfrN.js → priceTier-DyxDcoSh.js} +1 -1
  77. package/dist/{rules-Cx2hkV20.js → rules-GmuBnHtU.js} +3 -3
  78. package/dist/{scheduler-Bd-q7yF8.js → scheduler-BWAzMbPl.js} +28 -28
  79. package/dist/{toExcel-qfjR83qT.js → toExcel-BMOGsD6n.js} +2 -2
  80. package/dist/{unit-n1T9grbM.js → unit-BCREKGn9.js} +24 -24
  81. package/package.json +1 -1
  82. package/dist/TreeEditorOpenner.vue_vue_type_script_setup_true_lang-T71R68sq.js +0 -5836
  83. package/dist/dayjs.min-DpX65tgj.js +0 -7
@@ -1,5 +1,5 @@
1
1
  import { defineStore as r } from "pinia";
2
- import { E as a, G as s, H as l } from "./index.vue_vue_type_script_setup_true_lang-Nl505vPi.js";
2
+ import { J as a, K as s, L as l } from "./index.vue_vue_type_script_setup_true_lang-qgDBinUn.js";
3
3
  const u = {
4
4
  async read() {
5
5
  return a(await s().get("/public-setting"));
package/dist/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import { F as e, i as r, j as o, o as t, r as i, u as p } from "./app-4yWs09Fr.js";
1
+ import { F as e, i as r, j as o, o as t, r as i, u as p } from "./app-BcGgfvbE.js";
2
2
  export {
3
3
  e as FmApp,
4
4
  r as i18nMessages,
@@ -113,10 +113,11 @@ export declare const mediaService: {
113
113
  * Which of the two modes runs is decided by the field that is filled:
114
114
  * - `base64` overwrites the variant with the merchant's own bytes, synchronously
115
115
  * - `instruction` queues an AI re-edit, so the ratio drops back to `pending`
116
+ * (with `regenerateFromOrigin`, it re-derives from the original instead of the
117
+ * current variant, discarding previous variant edits)
116
118
  *
117
- * Sending neither is how the panel asks for a plain "generate this again". The
118
- * integration guide only spells out the two named modes, so a 400 here means the
119
- * service declined an instruction-less regenerate, not that the caller is malformed.
119
+ * Callers must send exactly one of `base64` or `instruction`; the service rejects an
120
+ * update request that contains neither with `400 INVALID_PARAM`.
120
121
  *
121
122
  * Unlike an upload these bytes do pass through the service pod — there is no
122
123
  * variant-level `upload-intent` — so callers must send a cropped, re-encoded image
@@ -131,6 +132,12 @@ export declare const mediaService: {
131
132
  aspectRatio: AspectRatio;
132
133
  base64?: string;
133
134
  instruction?: string;
135
+ /**
136
+ * Instruction-mode modifier: re-derive from the original instead of the current
137
+ * variant. Sent only when true — the service reads the mode off which key is
138
+ * present, and an omitted flag is the same as `false`.
139
+ */
140
+ regenerateFromOrigin?: boolean;
134
141
  }): Promise<void>;
135
142
  listImages(refIds: string[]): Promise<MediaImage[]>;
136
143
  getGenerationTask(taskId: string): Promise<GenerationTask>;
@@ -977,6 +977,7 @@ export declare const i18nMessages: {
977
977
  label: string;
978
978
  placeholder: string;
979
979
  duplicate_warning: string;
980
+ duplicate_hint: string;
980
981
  };
981
982
  name: {
982
983
  label: string;
@@ -1981,6 +1982,10 @@ export declare const i18nMessages: {
1981
1982
  original: string;
1982
1983
  custom_sizing: string;
1983
1984
  custom_image_hint: string;
1985
+ remove_ratio: {
1986
+ title: string;
1987
+ message: string;
1988
+ };
1984
1989
  required: string;
1985
1990
  cover_photo: string;
1986
1991
  set_as_cover: string;
@@ -1988,7 +1993,6 @@ export declare const i18nMessages: {
1988
1993
  };
1989
1994
  purpose: {
1990
1995
  menu_grid: string;
1991
- kiosk_grid: string;
1992
1996
  };
1993
1997
  status: {
1994
1998
  pending: string;
@@ -2012,6 +2016,9 @@ export declare const i18nMessages: {
2012
2016
  title: string;
2013
2017
  message: string;
2014
2018
  };
2019
+ preview: {
2020
+ title: string;
2021
+ };
2015
2022
  replace: {
2016
2023
  title: string;
2017
2024
  action: string;
@@ -2026,8 +2033,11 @@ export declare const i18nMessages: {
2026
2033
  action: string;
2027
2034
  hint: string;
2028
2035
  instruction: string;
2029
- instruction_required: string;
2030
2036
  instruction_placeholder: string;
2037
+ base: string;
2038
+ base_current: string;
2039
+ base_original: string;
2040
+ base_original_sublabel: string;
2031
2041
  queued: string;
2032
2042
  };
2033
2043
  };
@@ -3004,6 +3014,7 @@ export declare const i18nMessages: {
3004
3014
  label: string;
3005
3015
  placeholder: string;
3006
3016
  duplicate_warning: string;
3017
+ duplicate_hint: string;
3007
3018
  };
3008
3019
  name: {
3009
3020
  label: string;
@@ -4006,6 +4017,10 @@ export declare const i18nMessages: {
4006
4017
  original: string;
4007
4018
  custom_sizing: string;
4008
4019
  custom_image_hint: string;
4020
+ remove_ratio: {
4021
+ title: string;
4022
+ message: string;
4023
+ };
4009
4024
  required: string;
4010
4025
  cover_photo: string;
4011
4026
  set_as_cover: string;
@@ -4013,7 +4028,6 @@ export declare const i18nMessages: {
4013
4028
  };
4014
4029
  purpose: {
4015
4030
  menu_grid: string;
4016
- kiosk_grid: string;
4017
4031
  };
4018
4032
  status: {
4019
4033
  pending: string;
@@ -4037,6 +4051,9 @@ export declare const i18nMessages: {
4037
4051
  title: string;
4038
4052
  message: string;
4039
4053
  };
4054
+ preview: {
4055
+ title: string;
4056
+ };
4040
4057
  replace: {
4041
4058
  title: string;
4042
4059
  action: string;
@@ -4051,8 +4068,11 @@ export declare const i18nMessages: {
4051
4068
  action: string;
4052
4069
  hint: string;
4053
4070
  instruction: string;
4054
- instruction_required: string;
4055
4071
  instruction_placeholder: string;
4072
+ base: string;
4073
+ base_current: string;
4074
+ base_original: string;
4075
+ base_original_sublabel: string;
4056
4076
  queued: string;
4057
4077
  };
4058
4078
  };
@@ -5029,6 +5049,7 @@ export declare const i18nMessages: {
5029
5049
  label: string;
5030
5050
  placeholder: string;
5031
5051
  duplicate_warning: string;
5052
+ duplicate_hint: string;
5032
5053
  };
5033
5054
  name: {
5034
5055
  label: string;
@@ -6032,6 +6053,10 @@ export declare const i18nMessages: {
6032
6053
  original: string;
6033
6054
  custom_sizing: string;
6034
6055
  custom_image_hint: string;
6056
+ remove_ratio: {
6057
+ title: string;
6058
+ message: string;
6059
+ };
6035
6060
  required: string;
6036
6061
  cover_photo: string;
6037
6062
  set_as_cover: string;
@@ -6039,7 +6064,6 @@ export declare const i18nMessages: {
6039
6064
  };
6040
6065
  purpose: {
6041
6066
  menu_grid: string;
6042
- kiosk_grid: string;
6043
6067
  };
6044
6068
  status: {
6045
6069
  pending: string;
@@ -6063,6 +6087,9 @@ export declare const i18nMessages: {
6063
6087
  title: string;
6064
6088
  message: string;
6065
6089
  };
6090
+ preview: {
6091
+ title: string;
6092
+ };
6066
6093
  replace: {
6067
6094
  title: string;
6068
6095
  action: string;
@@ -6077,8 +6104,11 @@ export declare const i18nMessages: {
6077
6104
  action: string;
6078
6105
  hint: string;
6079
6106
  instruction: string;
6080
- instruction_required: string;
6081
6107
  instruction_placeholder: string;
6108
+ base: string;
6109
+ base_current: string;
6110
+ base_original: string;
6111
+ base_original_sublabel: string;
6082
6112
  queued: string;
6083
6113
  };
6084
6114
  };
@@ -7055,6 +7085,7 @@ export declare const i18nMessages: {
7055
7085
  label: string;
7056
7086
  placeholder: string;
7057
7087
  duplicate_warning: string;
7088
+ duplicate_hint: string;
7058
7089
  };
7059
7090
  name: {
7060
7091
  label: string;
@@ -8057,6 +8088,10 @@ export declare const i18nMessages: {
8057
8088
  original: string;
8058
8089
  custom_sizing: string;
8059
8090
  custom_image_hint: string;
8091
+ remove_ratio: {
8092
+ title: string;
8093
+ message: string;
8094
+ };
8060
8095
  required: string;
8061
8096
  cover_photo: string;
8062
8097
  set_as_cover: string;
@@ -8064,7 +8099,6 @@ export declare const i18nMessages: {
8064
8099
  };
8065
8100
  purpose: {
8066
8101
  menu_grid: string;
8067
- kiosk_grid: string;
8068
8102
  };
8069
8103
  status: {
8070
8104
  pending: string;
@@ -8088,6 +8122,9 @@ export declare const i18nMessages: {
8088
8122
  title: string;
8089
8123
  message: string;
8090
8124
  };
8125
+ preview: {
8126
+ title: string;
8127
+ };
8091
8128
  replace: {
8092
8129
  title: string;
8093
8130
  action: string;
@@ -8102,8 +8139,11 @@ export declare const i18nMessages: {
8102
8139
  action: string;
8103
8140
  hint: string;
8104
8141
  instruction: string;
8105
- instruction_required: string;
8106
8142
  instruction_placeholder: string;
8143
+ base: string;
8144
+ base_current: string;
8145
+ base_original: string;
8146
+ base_original_sublabel: string;
8107
8147
  queued: string;
8108
8148
  };
8109
8149
  };
@@ -9080,6 +9120,7 @@ export declare const i18nMessages: {
9080
9120
  label: string;
9081
9121
  placeholder: string;
9082
9122
  duplicate_warning: string;
9123
+ duplicate_hint: string;
9083
9124
  };
9084
9125
  name: {
9085
9126
  label: string;
@@ -10071,6 +10112,10 @@ export declare const i18nMessages: {
10071
10112
  original: string;
10072
10113
  custom_sizing: string;
10073
10114
  custom_image_hint: string;
10115
+ remove_ratio: {
10116
+ title: string;
10117
+ message: string;
10118
+ };
10074
10119
  required: string;
10075
10120
  cover_photo: string;
10076
10121
  set_as_cover: string;
@@ -10078,7 +10123,6 @@ export declare const i18nMessages: {
10078
10123
  };
10079
10124
  purpose: {
10080
10125
  menu_grid: string;
10081
- kiosk_grid: string;
10082
10126
  };
10083
10127
  status: {
10084
10128
  pending: string;
@@ -10102,6 +10146,9 @@ export declare const i18nMessages: {
10102
10146
  title: string;
10103
10147
  message: string;
10104
10148
  };
10149
+ preview: {
10150
+ title: string;
10151
+ };
10105
10152
  replace: {
10106
10153
  title: string;
10107
10154
  action: string;
@@ -10116,8 +10163,11 @@ export declare const i18nMessages: {
10116
10163
  action: string;
10117
10164
  hint: string;
10118
10165
  instruction: string;
10119
- instruction_required: string;
10120
10166
  instruction_placeholder: string;
10167
+ base: string;
10168
+ base_current: string;
10169
+ base_original: string;
10170
+ base_original_sublabel: string;
10121
10171
  queued: string;
10122
10172
  };
10123
10173
  };
@@ -21,11 +21,13 @@ export declare const ACCEPTED_IMAGE_TYPES: string[];
21
21
  * `{timestamp}_{4 random chars}`, e.g. `2026_07_27T06_54_00_000Z_argb`.
22
22
  *
23
23
  * The entity documents this as a raw ISO datetime, but the separators are flattened to
24
- * underscores the same way menu doc ids are (`item_2026_05_12T07_11_30_037Z_1c4gzj…`).
25
- * This id is used verbatim as the media object key segment and shows up in the image
26
- * URL path, and `:` there has to be percent-encoded to be safe every id that already
27
- * travels in a path in this system avoids it. Only the image id is built this way; the
28
- * item id it is nested under is whatever the menu service issued.
24
+ * underscores because the id is used verbatim as a media object-key segment and shows
25
+ * up in the image URL path, where a `:` would have to be percent-encoded. Flattening is
26
+ * a choice for the image id only menu doc ids keep their ISO colons and dashes
27
+ * (`item_2026-08-08T03:00:00.000Z_abc123`, minted by the menu engine's generateDocId),
28
+ * and the item id reaches media-service as a refId with its colons stripped separately
29
+ * by `normalizeMediaRefId`. The item id this id is nested under is whatever the menu
30
+ * service issued.
29
31
  */
30
32
  export declare function generateImageId(): string;
31
33
  /**
@@ -41,12 +43,12 @@ export declare function validateImageFile(file: File): string | null;
41
43
  /** Converts Remy's base64 result into an uploadable file without re-encoding it. */
42
44
  export declare function dataUrlToFile(dataUrl: string, fileName?: string): Promise<File>;
43
45
  /** `confirm` needs the real pixel size, and only the browser has it before upload. */
44
- export declare function readImageDimensions(file: File): Promise<{
46
+ export declare function readImageDimensions(file: File, unreadableMessage?: string): Promise<{
45
47
  width: number;
46
48
  height: number;
47
49
  }>;
48
50
  /** Lets the form wait for in-flight uploads before it saves. */
49
- export declare function waitForPendingThumbnailUploads(): Promise<void>;
51
+ export declare function waitForPendingImageUploads(): Promise<void>;
50
52
  /**
51
53
  * Uploads one file and returns the entity value to append to `item.images`.
52
54
  *
@@ -55,8 +57,8 @@ export declare function waitForPendingThumbnailUploads(): Promise<void>;
55
57
  *
56
58
  * `imageSet` values are left null on purpose: the ratio images media-service
57
59
  * generates are reachable at `{url}?aspect_ratio={ratio}`, so there is nothing to
58
- * store. A value is only ever written when a merchant substitutes a different photo
59
- * for one ratio — the "replace image" flow, which is not built yet.
60
+ * store. A value is written only when a merchant substitutes their own photo for one
61
+ * ratio — `replaceAspectRatioImage` stamps the variant URL as the custom marker.
60
62
  *
61
63
  * `aspectRatios` has no default: it is always derived from the
62
64
  * `autoGenerateImageAspectRatio` flag via `autoAspectRatios`, and a default here would
@@ -65,6 +67,7 @@ export declare function waitForPendingThumbnailUploads(): Promise<void>;
65
67
  export declare function uploadProductImage(itemId: string, file: File, options: {
66
68
  aspectRatios: AspectRatio[];
67
69
  imageId?: string;
70
+ unreadableMessage?: string;
68
71
  }): Promise<FdoMenuV4ItemImage>;
69
72
  /**
70
73
  * A file the merchant picked before the item it belongs to exists.
@@ -92,7 +95,7 @@ export declare function releaseStagedImages(staged: StagedProductImage[]): void;
92
95
  * Uploads every staged file against the now-known item id, in the order they were
93
96
  * picked so the gallery matches what the merchant saw while filling the form.
94
97
  */
95
- export declare function flushStagedImages(itemId: string, staged: StagedProductImage[], aspectRatios: AspectRatio[]): Promise<FdoMenuV4ItemImage[]>;
98
+ export declare function flushStagedImages(itemId: string, staged: StagedProductImage[], aspectRatios: AspectRatio[], unreadableMessage?: string): Promise<FdoMenuV4ItemImage[]>;
96
99
  /**
97
100
  * Queues generation for ratios the image does not have yet.
98
101
  *
@@ -104,40 +107,83 @@ export declare function flushStagedImages(itemId: string, staged: StagedProductI
104
107
  * Note the failure shape differs from `confirm`: a single ratio that fails to queue
105
108
  * (e.g. `409 TASK_IN_PROGRESS` for a ratio already generating) fails the whole call.
106
109
  */
107
- export declare function generateAspectRatios(itemId: string, image: FdoMenuV4ItemImage, aspectRatios: AspectRatio[]): Promise<FdoMenuV4ItemImage>;
110
+ export declare function generateAspectRatios(itemId: string, image: FdoMenuV4ItemImage, aspectRatios: AspectRatio[], options?: {
111
+ includeExisting?: boolean;
112
+ }): Promise<FdoMenuV4ItemImage>;
108
113
  /** `/images/update` carries its bytes inline, so the file has to become a data URL. */
109
114
  export declare function readFileAsDataUrl(file: File): Promise<string>;
110
115
  /**
111
- * Substitutes the merchant's own photo for one generated ratio.
116
+ * Substitutes the merchant's own photo for one generated ratio and marks it custom.
117
+ *
118
+ * The variant keeps its URL and only the bytes behind it are rewritten, so the only
119
+ * difference between the input image and the returned one is `imageSet[ratio]`: it
120
+ * now carries the variant URL as a marker meaning "not derived from the original".
121
+ * That URL is the same `{url}?aspect_ratio={ratio}` the consumer would compose
122
+ * anyway — the value exists to be checked for null, not to point somewhere else. The
123
+ * caller persists the returned image to save the marker.
112
124
  *
113
- * Nothing about the entity changes: the variant keeps its URL and only the bytes
114
- * behind it are rewritten, so `imageSet` is untouched and the caller has nothing new
115
- * to save. What the caller does have to do is bust its own image cache — the URL is
116
- * "always latest" at the edge, but a browser that already fetched it will not know.
125
+ * The caller also has to bust its own image cache — the URL is "always latest" at the
126
+ * edge, but a browser that already fetched it will not know.
117
127
  *
118
128
  * The file is expected to be cropped to `ratio` and re-encoded by the dialog: these
119
129
  * bytes travel through the service pod (no variant-level upload-intent exists), and a
120
130
  * variant is supposed to be exactly its ratio.
121
131
  */
122
- export declare function replaceAspectRatioImage(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio, file: File): Promise<void>;
132
+ export declare function replaceAspectRatioImage(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio, file: File): Promise<FdoMenuV4ItemImage>;
133
+ /**
134
+ * Fallback instruction sent when the merchant regenerates without typing anything.
135
+ *
136
+ * `/images/update` takes exactly one of `base64` or `instruction`, and sending neither
137
+ * is rejected with 400 INVALID_PARAM — there is no "just roll the dice again" mode, so
138
+ * an empty box has to resolve to a real instruction rather than being omitted.
139
+ */
140
+ export declare const DEFAULT_REGENERATE_INSTRUCTION = "regenerate";
123
141
  /**
124
142
  * Asks for one ratio to be generated again, saying what to change.
125
143
  *
126
- * The instruction is required, not a nicety: `/images/update` takes exactly one of
127
- * `base64` or `instruction`, and sending neither is rejected with 400 INVALID_PARAM —
128
- * there is no "just roll the dice again" mode to fall back to.
144
+ * The instruction is optional: an empty one falls back to
145
+ * `DEFAULT_REGENERATE_INSTRUCTION` so the merchant can redo the ratio without typing
146
+ * anything.
147
+ *
148
+ * With `regenerateFromOrigin`, the ratio is re-derived from the original instead of
149
+ * the current variant, discarding previous variant edits. Per product rule this must
150
+ * only be used while `imageSet[ratio]` is null — a ratio holding a custom URL must
151
+ * never be re-derived from the original, or the merchant's own photo is silently
152
+ * thrown away.
129
153
  *
130
154
  * Queued, not immediate: the ratio goes back to `pending` for ~40s and its URL keeps
131
155
  * serving the old image until the new one lands, so there is nothing to roll back.
132
156
  */
133
- export declare function regenerateAspectRatio(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio, instruction: string): Promise<void>;
157
+ export declare function regenerateAspectRatio(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio, instruction: string, regenerateFromOrigin?: boolean): Promise<void>;
134
158
  export declare function deleteAspectRatio(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio): Promise<FdoMenuV4ItemImage>;
159
+ export interface ProductImageReference {
160
+ itemId: string;
161
+ imageId: string;
162
+ }
163
+ /** Deletes individual originals after their menu references have been saved. */
164
+ export declare function deleteProductImages(images: ProductImageReference[]): Promise<void>;
135
165
  /** Deletes the whole image, original included (`aspectRatios: null`). */
136
166
  export declare function deleteProductImage(itemId: string, imageId: string): Promise<void>;
137
167
  /** Deletes every image an item owns; used when the product itself is removed. */
138
168
  export declare function deleteAllProductImages(itemIds: string[]): Promise<void>;
139
169
  /** Enforces the single-cover rule: setting one clears the flag on every other image. */
140
170
  export declare function setCoverImage(images: FdoMenuV4ItemImage[], imageId: string, isCover: boolean): FdoMenuV4ItemImage[];
171
+ /**
172
+ * Finds original images that disappeared from the menu document.
173
+ *
174
+ * Media deletion must run only after the corresponding menu write succeeds. This keeps
175
+ * Cancel/Discard safe: the draft can omit an image without making the saved document
176
+ * point at a deleted original.
177
+ */
178
+ export declare function getRemovedProductImages(previousItems: FdoMenuV4Item[], nextItems: FdoMenuV4Item[]): ProductImageReference[];
179
+ /**
180
+ * Finds originals that exist only in an unsaved draft.
181
+ *
182
+ * Reversing `getRemovedProductImages` is intentional: the draft is treated as the
183
+ * previous state and the persisted document as the next state. These are the objects
184
+ * that must be discarded when a form is cancelled.
185
+ */
186
+ export declare function getAddedProductImages(draftItems: FdoMenuV4Item[], persistedItems: FdoMenuV4Item[]): ProductImageReference[];
141
187
  /**
142
188
  * Mirrors the backend `resolveItemThumbnail` so the raw menu document stays usable
143
189
  * for anything reading it directly (portal's own lists, v3 clients) — overrideMenu
@@ -1,16 +1,31 @@
1
- import type { FdoMenuV4ItemImage } from "@feedmepos/entity";
1
+ import type { FdoMenuV4Item, FdoMenuV4ItemImage } from "@feedmepos/entity";
2
2
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
3
3
  modelValue: boolean;
4
4
  itemId: string;
5
5
  image: FdoMenuV4ItemImage | null;
6
6
  disabled?: boolean | undefined;
7
+ /**
8
+ * Catalog override mode: the panel stays fully visible — ratio rows and their large
9
+ * previews are readable — but every media-service action (generate all, add format,
10
+ * replace, regenerate, remove) is disabled. Only the cover toggle and Update work.
11
+ */
12
+ coverOnly?: boolean | undefined;
7
13
  /**
8
14
  * Whether turning the cover off is allowed. False when this is the only image, so the
9
15
  * gallery can never be left without a cover to resolve a thumbnail from. The parent
10
16
  * also promotes a survivor when a multi-image cover is cleared, so this only guards
11
- * the no-candidate case.
17
+ * the no-candidate case. Ignored in `coverOnly` mode, where clearing the override
18
+ * cover always means falling back to the base gallery's cover — the inherited gallery
19
+ * belongs to the base item, which keeps its own cover invariant.
12
20
  */
13
21
  canClearCover?: boolean | undefined;
22
+ /**
23
+ * The module's items, so the panel can show the union of custom aspect ratios across
24
+ * every product image. Add-format is menu-wide: a ratio added anywhere appears on
25
+ * every image's panel, even before that image has generated it. Comes from whichever
26
+ * store the host context edits (global `menuStore` or TreeEditor's `menuV2`).
27
+ */
28
+ menuItems?: FdoMenuV4Item[] | undefined;
14
29
  }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
15
30
  "update:modelValue": (open: boolean) => void;
16
31
  "update:image": (image: FdoMenuV4ItemImage) => void;
@@ -19,13 +34,28 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
19
34
  itemId: string;
20
35
  image: FdoMenuV4ItemImage | null;
21
36
  disabled?: boolean | undefined;
37
+ /**
38
+ * Catalog override mode: the panel stays fully visible — ratio rows and their large
39
+ * previews are readable — but every media-service action (generate all, add format,
40
+ * replace, regenerate, remove) is disabled. Only the cover toggle and Update work.
41
+ */
42
+ coverOnly?: boolean | undefined;
22
43
  /**
23
44
  * Whether turning the cover off is allowed. False when this is the only image, so the
24
45
  * gallery can never be left without a cover to resolve a thumbnail from. The parent
25
46
  * also promotes a survivor when a multi-image cover is cleared, so this only guards
26
- * the no-candidate case.
47
+ * the no-candidate case. Ignored in `coverOnly` mode, where clearing the override
48
+ * cover always means falling back to the base gallery's cover — the inherited gallery
49
+ * belongs to the base item, which keeps its own cover invariant.
27
50
  */
28
51
  canClearCover?: boolean | undefined;
52
+ /**
53
+ * The module's items, so the panel can show the union of custom aspect ratios across
54
+ * every product image. Add-format is menu-wide: a ratio added anywhere appears on
55
+ * every image's panel, even before that image has generated it. Comes from whichever
56
+ * store the host context edits (global `menuStore` or TreeEditor's `menuV2`).
57
+ */
58
+ menuItems?: FdoMenuV4Item[] | undefined;
29
59
  }>>> & Readonly<{
30
60
  "onUpdate:modelValue"?: ((open: boolean) => any) | undefined;
31
61
  "onUpdate:image"?: ((image: FdoMenuV4ItemImage) => any) | undefined;
@@ -1,4 +1,4 @@
1
- import type { FdoMenuV4ItemImage } from "@feedmepos/entity";
1
+ import type { FdoMenuV4Item, FdoMenuV4ItemImage } from "@feedmepos/entity";
2
2
  import { type StagedProductImage } from "@/components/feature/TreeEditor/composable/productImages";
3
3
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
4
4
  itemId: string;
@@ -11,6 +11,12 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
11
11
  */
12
12
  staged?: StagedProductImage[] | null | undefined;
13
13
  disabled?: boolean | undefined;
14
+ /**
15
+ * Catalog override mode: clicking an image opens the Manage panel like Main Catalog,
16
+ * but the panel's media-service actions are disabled — only the cover toggle is
17
+ * editable. Clearing the override cover falls back to the base gallery's cover.
18
+ */
19
+ coverOnly?: boolean | undefined;
14
20
  /**
15
21
  * Legacy single-image URL from the `thumbnail` field. When set and modelValue is
16
22
  * null (the item predates multi-image), a synthetic read-only tile is shown so the
@@ -18,10 +24,18 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
18
24
  * media-service and is dropped from the emitted array the moment a real image lands.
19
25
  */
20
26
  legacyThumbnail?: string | null | undefined;
27
+ /**
28
+ * The module's items, forwarded to the Manage panel so it shows the union of custom
29
+ * aspect ratios across every product image. Sourced from whichever store the host
30
+ * context edits (global `menuStore` or TreeEditor's `menuV2`).
31
+ */
32
+ menuItems?: FdoMenuV4Item[] | undefined;
21
33
  }>, {
22
34
  staged: null;
23
35
  disabled: boolean;
36
+ coverOnly: boolean;
24
37
  legacyThumbnail: null;
38
+ menuItems: () => never[];
25
39
  }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
26
40
  "update:modelValue": (images: FdoMenuV4ItemImage[]) => void;
27
41
  "update:staged": (staged: StagedProductImage[]) => void;
@@ -36,6 +50,12 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
36
50
  */
37
51
  staged?: StagedProductImage[] | null | undefined;
38
52
  disabled?: boolean | undefined;
53
+ /**
54
+ * Catalog override mode: clicking an image opens the Manage panel like Main Catalog,
55
+ * but the panel's media-service actions are disabled — only the cover toggle is
56
+ * editable. Clearing the override cover falls back to the base gallery's cover.
57
+ */
58
+ coverOnly?: boolean | undefined;
39
59
  /**
40
60
  * Legacy single-image URL from the `thumbnail` field. When set and modelValue is
41
61
  * null (the item predates multi-image), a synthetic read-only tile is shown so the
@@ -43,15 +63,25 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
43
63
  * media-service and is dropped from the emitted array the moment a real image lands.
44
64
  */
45
65
  legacyThumbnail?: string | null | undefined;
66
+ /**
67
+ * The module's items, forwarded to the Manage panel so it shows the union of custom
68
+ * aspect ratios across every product image. Sourced from whichever store the host
69
+ * context edits (global `menuStore` or TreeEditor's `menuV2`).
70
+ */
71
+ menuItems?: FdoMenuV4Item[] | undefined;
46
72
  }>, {
47
73
  staged: null;
48
74
  disabled: boolean;
75
+ coverOnly: boolean;
49
76
  legacyThumbnail: null;
77
+ menuItems: () => never[];
50
78
  }>>> & Readonly<{
51
79
  "onUpdate:modelValue"?: ((images: FdoMenuV4ItemImage[]) => any) | undefined;
52
80
  "onUpdate:staged"?: ((staged: StagedProductImage[]) => any) | undefined;
53
81
  }>, {
54
82
  disabled: boolean;
83
+ coverOnly: boolean;
84
+ menuItems: FdoMenuV4Item[];
55
85
  staged: StagedProductImage[] | null;
56
86
  legacyThumbnail: string | null;
57
87
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -1,9 +1,19 @@
1
1
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
2
2
  /** Display label of the ratio being regenerated, e.g. `16:9`. */
3
3
  ratioLabel: string;
4
+ /**
5
+ * Whether "regenerate from the original" is offered. True only while
6
+ * `imageSet[ratio]` is null (the ratio is AI-derived), never for a custom image.
7
+ */
8
+ canRegenerateFromOrigin: boolean;
4
9
  }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
5
10
  /** Display label of the ratio being regenerated, e.g. `16:9`. */
6
11
  ratioLabel: string;
12
+ /**
13
+ * Whether "regenerate from the original" is offered. True only while
14
+ * `imageSet[ratio]` is null (the ratio is AI-derived), never for a custom image.
15
+ */
16
+ canRegenerateFromOrigin: boolean;
7
17
  }>>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
18
  export default _default;
9
19
  type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
@@ -3,6 +3,28 @@ import { FdoCustomAttribute, FdoDinero } from "@feedmepos/core/entity";
3
3
  import { FdoMenuV4, FdoMenuV4Item, FdoMenuV4VariantGroup, FdoItemOverriderV4, FdoMenuV4Catalog, FdoItemVariant } from "@feedmepos/entity";
4
4
  import { type ExportAddonGroupRow, type ExportMenuDataRow, type GroupedAddon, type GroupedItem, type itemsLinkWithGroup } from "@/helper/import-export-utils";
5
5
  import type { GroupItem } from "@/manager/menu/group";
6
+ export declare const fileMap: {
7
+ _id: string;
8
+ code: string;
9
+ name: string;
10
+ name2: string;
11
+ description: string;
12
+ variantKey: string;
13
+ variantName: string;
14
+ category: string;
15
+ subCategories: string;
16
+ orderFrom: string;
17
+ perXUnit: string;
18
+ unit: string;
19
+ openPrice: string;
20
+ price: string;
21
+ trackingCost: string;
22
+ minPrice: string;
23
+ groupByParent: string;
24
+ takeawayName: string;
25
+ takeawayPrice: string;
26
+ index: string;
27
+ };
6
28
  export declare function normalizeCatalogOverrideAdditionalCategories(item: Pick<FdoMenuV4Item, "category" | "additionalCategories">, itemOverride: Pick<FdoItemOverriderV4, "additionalCategories"> | undefined, categoryId: FdoMenuV4Item["category"]): FdoItemOverriderV4["additionalCategories"];
7
29
  export declare class MenuImport {
8
30
  menu: FdoMenuV4;
@@ -0,0 +1,17 @@
1
+ import type { FdoItemOverriderV4, FdoMenuV4Item } from "@feedmepos/entity";
2
+ export type FdoMenuV4ItemWithCoverImage = FdoMenuV4Item & {
3
+ /** Catalog/scheduler override field: the selected entry in `images`. */
4
+ image?: string | null;
5
+ };
6
+ /**
7
+ * Serializes a menu item into the override-document schema.
8
+ *
9
+ * Catalog overrides store the selected gallery entry id in the singular `image` field.
10
+ * The full gallery belongs to the base item and must not be copied into an override
11
+ * document: the overrider schema carries only a singular `image`, not the multi-image
12
+ * array, so sending `images` through the `as` cast would be silently stripped
13
+ * server-side and pinned stale in the override doc — the same trap the shelfLife
14
+ * fields fell into. `thumbnail` is dropped here too; overrideMenu derives the same
15
+ * value on its way out.
16
+ */
17
+ export declare function itemToOverrider(item: Partial<FdoMenuV4ItemWithCoverImage>): FdoItemOverriderV4[];