@feedmepos/mf-menu 0.32.66-dev.2 → 0.32.66-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.
- package/dist/{App-D0YpNkYr.js → App-bCL9DMmd.js} +6 -6
- package/dist/{ApplyProduct.vue_vue_type_script_setup_true_lang-YPM2sgEJ.js → ApplyProduct.vue_vue_type_script_setup_true_lang-CnoYMg6T.js} +7 -7
- package/dist/{ApplyProductDialog.vue_vue_type_script_setup_true_lang-CAXhUciI.js → ApplyProductDialog.vue_vue_type_script_setup_true_lang-Ccw08-Uw.js} +3 -3
- package/dist/{Catalog-I3XpPLoT.js → Catalog-Ds6GYriM.js} +6 -6
- package/dist/{Category-CfCp_M4X.js → Category-CnFL0t4m.js} +4 -4
- package/dist/{Category-BTmqDRbK.js → Category-DY_XSrsn.js} +4 -4
- package/dist/{CookingGuide-BRHwTegP.js → CookingGuide-BTk8BaAd.js} +5 -5
- package/dist/{CustomAttributeChip.vue_vue_type_script_setup_true_lang-ksv-RMn2.js → CustomAttributeChip.vue_vue_type_script_setup_true_lang-BgI4r-xU.js} +1 -1
- package/dist/{Group-Bwj6UATr.js → Group-860k7lB8.js} +3 -3
- package/dist/{Group-BvrANEY8.js → Group-BSMIM376.js} +1 -1
- package/dist/{Group.vue_vue_type_script_setup_true_lang-CYLH4YhA.js → Group.vue_vue_type_script_setup_true_lang-DWA-dDCM.js} +7 -7
- package/dist/{GroupMarkupPriceDialog.vue_vue_type_script_setup_true_lang-DWpeinru.js → GroupMarkupPriceDialog.vue_vue_type_script_setup_true_lang-dKJjPwe3.js} +5 -5
- package/dist/{ImportProductDialog.vue_vue_type_script_setup_true_lang-DEvUaDcb.js → ImportProductDialog.vue_vue_type_script_setup_true_lang-H2rtSZTK.js} +9 -8
- package/dist/{Ingredient-B8n9cRsp.js → Ingredient-BYDjOmNr.js} +4 -4
- package/dist/{InventoryBinding.vue_vue_type_script_setup_true_lang-92V2JZvW.js → InventoryBinding.vue_vue_type_script_setup_true_lang-Bdhyk7wJ.js} +2 -2
- package/dist/{LinkProductSideSheet-LF2pdsYn.js → LinkProductSideSheet-CQS8yW-C.js} +4 -4
- package/dist/{MenuSetting-DrObZATH.js → MenuSetting-BmK8AlkW.js} +7 -7
- package/dist/{OrderPacing-CIP1oshR.js → OrderPacing-TJ6ZYLYV.js} +5 -5
- package/dist/{PrintRoute-BUErmYxT.js → PrintRoute-CR9yyKNK.js} +5 -5
- package/dist/{Product-DBRc2y1I.js → Product-UVz9VsGm.js} +1 -1
- package/dist/{Product.vue_vue_type_script_setup_true_lang-BvtMo0M4.js → Product.vue_vue_type_script_setup_true_lang-DaUlfmGn.js} +622 -610
- package/dist/{ProductInternalTools-CnYr5piv.js → ProductInternalTools-D-SOeCcO.js} +6 -6
- package/dist/{Products-DkqJELto.js → Products-DhNIR6E7.js} +57 -57
- package/dist/{Publish-C94D_B2o.js → Publish-CsjlWTjc.js} +4 -4
- package/dist/{Recipe-DxTc4llT.js → Recipe-uwZYJm_N.js} +5 -5
- package/dist/{RestaurantAttributesSelector.vue_vue_type_script_setup_true_lang-BC59l-9q.js → RestaurantAttributesSelector.vue_vue_type_script_setup_true_lang-CF-r4vAJ.js} +1 -1
- package/dist/{RuleView.vue_vue_type_script_setup_true_lang-BpGitWig.js → RuleView.vue_vue_type_script_setup_true_lang-BfdS-xS1.js} +3 -3
- package/dist/{Scheduler-CtdYHGoQ.js → Scheduler-B1_i4bRR.js} +3 -3
- package/dist/{ServingSequence-Bx0Z7ob9.js → ServingSequence-B7TO7rNV.js} +3 -3
- package/dist/{Setting-BWKT6o_d.js → Setting-ByrEh4BA.js} +5 -5
- package/dist/{Subcategory-BckJmrDm.js → Subcategory-BWqzLw-d.js} +6 -6
- package/dist/{Takeaway-DULjBrov.js → Takeaway-BDtDA3Oz.js} +1 -1
- package/dist/{Takeaway-Dvt7GRhi.js → Takeaway-BJpHwTck.js} +4 -4
- package/dist/{Takeaway.vue_vue_type_script_setup_true_lang-BanPhJ_p.js → Takeaway.vue_vue_type_script_setup_true_lang-DaqAIPrd.js} +10 -10
- package/dist/{TranslationFieldSection.vue_vue_type_script_setup_true_lang-BA1GwxTn.js → TranslationFieldSection.vue_vue_type_script_setup_true_lang-Ctua4piB.js} +1 -1
- package/dist/{TranslationSideSheet.vue_vue_type_script_setup_true_lang-B45Qj3ka.js → TranslationSideSheet.vue_vue_type_script_setup_true_lang-CaIv_N0Y.js} +2 -2
- package/dist/{TreeEditorOpenner.vue_vue_type_script_setup_true_lang-mlqLqR9u.js → TreeEditorOpenner.vue_vue_type_script_setup_true_lang-BXJsNMO4.js} +15 -15
- package/dist/{Unit-C2rVtZXW.js → Unit-CztcKfU8.js} +2 -2
- package/dist/{Variant-C1aRShIB.js → Variant-DoKsw2Kp.js} +3 -3
- package/dist/{_id_-TNQRaQmS.js → _id_-Bm8i0F1E.js} +10 -10
- package/dist/{app-Cbzk6cOz.js → app-BGCDoU-0.js} +328 -328
- package/dist/{app-DwyLCetV.js → app-Du5OtlE9.js} +1 -1
- package/dist/app.js +1 -1
- package/dist/apps/mf-menu/src/api/media.d.ts +63 -10
- package/dist/apps/mf-menu/src/app.d.ts +120 -10
- package/dist/apps/mf-menu/src/components/feature/Fields/RangeSlider.vue.d.ts +62 -0
- package/dist/apps/mf-menu/src/components/feature/TreeEditor/composable/productImages.d.ts +95 -12
- package/dist/apps/mf-menu/src/components/feature/TreeEditor/image/ImageEditorDialog.vue.d.ts +56 -0
- package/dist/apps/mf-menu/src/composable/imageSource.d.ts +7 -0
- package/dist/apps/mf-menu/src/composable/imageVersion.d.ts +11 -0
- package/dist/apps/mf-menu/src/helper/itemOverrider.d.ts +10 -0
- package/dist/apps/mf-menu/tsconfig.app.tsbuildinfo +1 -1
- package/dist/assets/{linked-status-BY2u9ovw.js → linked-status-CGYWO8Yo.js} +4 -4
- package/dist/assets/{menu-export-BaTSKjZt.js → menu-export-D32WVYBV.js} +3 -3
- package/dist/assets/{override-menu-Ccftxk6t.js → override-menu-B2muNR2b.js} +4 -4
- package/dist/assets/{validate-menu-CLI_SnXI.js → validate-menu-DRc93ut_.js} +4 -4
- package/dist/{catalog-CVzF_mVG.js → catalog-B1szIMSS.js} +1 -1
- package/dist/{catalogSetting-C1g9ndFL.js → catalogSetting-D317tpwX.js} +1 -1
- package/dist/{currency-BMMqzZYC.js → currency-DDMkadDP.js} +1 -1
- package/dist/{dayjs.min-BozAuX2f.js → dayjs.min-BAfSpgzt.js} +2 -2
- package/dist/{discardConfirm-CFESnGLS.js → discardConfirm-ulS7oH8I.js} +1 -1
- package/dist/{index-BRt5TwuO.js → index-BNCGppNp.js} +6 -6
- package/dist/{index-CyomkF6Q.js → index-ClAWU743.js} +5 -5
- package/dist/{index-BNzLcju2.js → index-DVh6Gi2K.js} +1 -1
- package/dist/{index.vue_vue_type_script_setup_true_lang-CESDAztS.js → index.vue_vue_type_script_setup_true_lang-Cf2AKbC7.js} +18409 -18281
- package/dist/{item-Bg78_1Z3.js → item-D3jvuhGD.js} +5058 -4584
- package/dist/{jszip.min-CfmqMq7-.js → jszip.min-t1qkoubE.js} +3 -3
- package/dist/{linkProducts-Dk-7vVTM.js → linkProducts-IK0-iQJR.js} +4 -4
- package/dist/{memberPricing-BeLPeWJc.js → memberPricing-DagiXBzk.js} +1 -1
- package/dist/{menu-Cn6vin1M.js → menu-B-BBAQKK.js} +1 -1
- package/dist/{menuV2-DMl-WMCG.js → menuV2-0X1EYaDt.js} +29 -29
- package/dist/mf-menu.css +1 -1
- package/dist/{order_pacing-SVJqBJun.js → order_pacing-Cz0wFd_o.js} +5 -5
- package/dist/{priceTier-BOIqyyMG.js → priceTier-DBzOsSgm.js} +1 -1
- package/dist/{rules-Bw94jp35.js → rules-C6WjUylO.js} +3 -3
- package/dist/{scheduler-BooRYOi1.js → scheduler-aKSniDdK.js} +5 -5
- package/dist/{toExcel-FAK9N74s.js → toExcel-SxxuXoXI.js} +2 -2
- package/dist/{unit-BiH3semx.js → unit-CltVM3dM.js} +3 -3
- package/package.json +1 -1
- package/dist/apps/mf-menu/src/components/feature/TreeEditor/image/ImageUploadDialog.vue.d.ts +0 -18
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineStore as r } from "pinia";
|
|
2
|
-
import { J as a, K as s, L as l } from "./index.vue_vue_type_script_setup_true_lang-
|
|
2
|
+
import { J as a, K as s, L as l } from "./index.vue_vue_type_script_setup_true_lang-Cf2AKbC7.js";
|
|
3
3
|
const u = {
|
|
4
4
|
async read() {
|
|
5
5
|
return a(await s().get("/public-setting"));
|
package/dist/app.js
CHANGED
|
@@ -14,6 +14,15 @@ export declare function normalizeMediaRefId(refId: string): string;
|
|
|
14
14
|
export type AspectRatio = string;
|
|
15
15
|
/** Ratios every product image is expected to carry; they cannot be removed in the UI. */
|
|
16
16
|
export declare const REQUIRED_ASPECT_RATIOS: AspectRatio[];
|
|
17
|
+
/**
|
|
18
|
+
* Reserved ratio word for the uploaded image itself (backend `model.RatioOriginal`).
|
|
19
|
+
*
|
|
20
|
+
* Not a generatable ratio: `/images/create` rejects it, and on `/images/update` it
|
|
21
|
+
* selects the write-the-original mode rather than naming a variant. Kept as a constant
|
|
22
|
+
* because `AspectRatio` is a bare string — the type cannot keep the two apart, so the
|
|
23
|
+
* distinction has to be visible at the call site.
|
|
24
|
+
*/
|
|
25
|
+
export declare const RATIO_ORIGINAL = "original";
|
|
17
26
|
export type VariantStatus = "pending" | "active" | "failed";
|
|
18
27
|
export interface MediaVariant {
|
|
19
28
|
aspectRatio: AspectRatio;
|
|
@@ -106,18 +115,23 @@ export declare const mediaService: {
|
|
|
106
115
|
mode: "append" | "replace";
|
|
107
116
|
}): Promise<CreateRes>;
|
|
108
117
|
/**
|
|
109
|
-
*
|
|
110
|
-
* alone
|
|
111
|
-
*
|
|
118
|
+
* Regenerates exactly one aspect ratio, leaving every other ratio and the original
|
|
119
|
+
* alone. For rewriting the original itself, see `updateOriginal` — same endpoint,
|
|
120
|
+
* different mode, and the only one that is not AI generation.
|
|
112
121
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* - `
|
|
116
|
-
*
|
|
117
|
-
*
|
|
122
|
+
* Both modes here are AI generation, and which one runs is decided by the field that
|
|
123
|
+
* is filled (either, or both):
|
|
124
|
+
* - `base64` stores the supplied bytes as the *source* and queues generation from
|
|
125
|
+
* them. It is not a passthrough: the service trims uniform bars off the source and
|
|
126
|
+
* hands it to the model, so what lands is a redraw of the merchant's image at this
|
|
127
|
+
* ratio, not the merchant's image. Changed by media-service `db04d1f`; before that
|
|
128
|
+
* it was a synchronous byte write, which is what this client used to document.
|
|
129
|
+
* - `instruction` queues a re-edit of the variant's *current* image (with
|
|
130
|
+
* `regenerateFromOrigin`, of the original instead, discarding previous edits).
|
|
118
131
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
132
|
+
* Either way the ratio drops back to `pending` for ~40s and the request consumes one
|
|
133
|
+
* AI generation from the business's license allowance. The service rejects an update
|
|
134
|
+
* carrying neither field with `400 INVALID_PARAM`.
|
|
121
135
|
*
|
|
122
136
|
* Unlike an upload these bytes do pass through the service pod — there is no
|
|
123
137
|
* variant-level `upload-intent` — so callers must send a cropped, re-encoded image
|
|
@@ -139,6 +153,45 @@ export declare const mediaService: {
|
|
|
139
153
|
*/
|
|
140
154
|
regenerateFromOrigin?: boolean;
|
|
141
155
|
}): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Rewrites the uploaded original in place, synchronously (media-service `a0cc055`).
|
|
158
|
+
*
|
|
159
|
+
* The one mode of `/images/update` that is not AI: the bytes are stored as-is and
|
|
160
|
+
* nothing is queued, so no generation is billed. Sending `instruction`, `params` or
|
|
161
|
+
* `regenerateFromOrigin` alongside `aspectRatio: "original"` is a `400 INVALID_PARAM`
|
|
162
|
+
* — hence a separate method rather than a flag on `update`, so the invalid combination
|
|
163
|
+
* cannot be expressed here at all.
|
|
164
|
+
*
|
|
165
|
+
* `base64` may be a data URL or bare base64; the stored Content-Type is sniffed from
|
|
166
|
+
* the bytes rather than read off the data URL. The service re-reads `width`, `height`,
|
|
167
|
+
* `mimeType` and `fileSize` from them — `fileName` is deliberately left as it was.
|
|
168
|
+
* Limits are the upload's: 10 MiB decoded (`413 PAYLOAD_TOO_LARGE`, checked on the
|
|
169
|
+
* encoded length too), jpeg/png/webp only (`415 UNSUPPORTED_MEDIA_TYPE`).
|
|
170
|
+
*
|
|
171
|
+
* Two things the caller owns afterwards:
|
|
172
|
+
* - **Stale variants.** Existing ratios are retained and are *not* regenerated, so
|
|
173
|
+
* they still derive from the photo that was just replaced. Requeue the ones that
|
|
174
|
+
* should follow the original with `create({ mode: "append" })` — `generateAspectRatios`
|
|
175
|
+
* with `includeExisting` — skipping any ratio whose `imageSet` value is set, since
|
|
176
|
+
* that marks a photo the merchant supplied and must never be regenerated out from
|
|
177
|
+
* under them. It has to be `append`: `replace` also *deletes* every variant absent
|
|
178
|
+
* from the request, so requeueing a subset with it would take the merchant's own
|
|
179
|
+
* ratios down with it.
|
|
180
|
+
* - **Caches.** The URL does not change, which is the point: nothing in the menu
|
|
181
|
+
* document has to be written. The service purges the original URL from the edge, but
|
|
182
|
+
* that is fire-and-forget (and a no-op without Cloudflare credentials) and cannot
|
|
183
|
+
* reach a browser that already fetched it, so surfaces showing the image must bust
|
|
184
|
+
* their own cache with a `?t=` stamp. Safe to add: image-router only rewrites a
|
|
185
|
+
* request that carries `aspect_ratio`. Never persist the stamped URL.
|
|
186
|
+
*
|
|
187
|
+
* The response is dropped for the same reason as `update`'s, and because it carries
|
|
188
|
+
* nothing new: the URL is unchanged and the status is always `active`.
|
|
189
|
+
*/
|
|
190
|
+
updateOriginal(req: {
|
|
191
|
+
refId: string;
|
|
192
|
+
imageId: string;
|
|
193
|
+
base64: string;
|
|
194
|
+
}): Promise<void>;
|
|
142
195
|
listImages(refIds: string[]): Promise<MediaImage[]>;
|
|
143
196
|
getGenerationTask(taskId: string): Promise<GenerationTask>;
|
|
144
197
|
delete(entries: DeleteEntry[]): Promise<void>;
|
|
@@ -1966,6 +1966,29 @@ export declare const i18nMessages: {
|
|
|
1966
1966
|
};
|
|
1967
1967
|
product_image: {
|
|
1968
1968
|
hint: string;
|
|
1969
|
+
crop_hint: string;
|
|
1970
|
+
editor: {
|
|
1971
|
+
title: string;
|
|
1972
|
+
subtitle_upload: string;
|
|
1973
|
+
subtitle_counter: string;
|
|
1974
|
+
subtitle_edit: string;
|
|
1975
|
+
upload_rest: string;
|
|
1976
|
+
ratio: string;
|
|
1977
|
+
ratio_free: string;
|
|
1978
|
+
zoom: string;
|
|
1979
|
+
rotate: string;
|
|
1980
|
+
reset: string;
|
|
1981
|
+
output_original: string;
|
|
1982
|
+
output_edited: string;
|
|
1983
|
+
oversized: string;
|
|
1984
|
+
edit_notice_title: string;
|
|
1985
|
+
edit_notice_body: string;
|
|
1986
|
+
replace_notice_title: string;
|
|
1987
|
+
replace_notice_body: string;
|
|
1988
|
+
saving: string;
|
|
1989
|
+
saved: string;
|
|
1990
|
+
formats_failed: string;
|
|
1991
|
+
};
|
|
1969
1992
|
drop_hint: string;
|
|
1970
1993
|
add_file: string;
|
|
1971
1994
|
cover_badge: string;
|
|
@@ -2021,11 +2044,10 @@ export declare const i18nMessages: {
|
|
|
2021
2044
|
replace: {
|
|
2022
2045
|
title: string;
|
|
2023
2046
|
action: string;
|
|
2024
|
-
unavailable: string;
|
|
2025
2047
|
hint: string;
|
|
2026
2048
|
accepts: string;
|
|
2027
2049
|
no_file: string;
|
|
2028
|
-
|
|
2050
|
+
queued: string;
|
|
2029
2051
|
};
|
|
2030
2052
|
regenerate: {
|
|
2031
2053
|
title: string;
|
|
@@ -4000,6 +4022,29 @@ export declare const i18nMessages: {
|
|
|
4000
4022
|
};
|
|
4001
4023
|
product_image: {
|
|
4002
4024
|
hint: string;
|
|
4025
|
+
crop_hint: string;
|
|
4026
|
+
editor: {
|
|
4027
|
+
title: string;
|
|
4028
|
+
subtitle_upload: string;
|
|
4029
|
+
subtitle_counter: string;
|
|
4030
|
+
subtitle_edit: string;
|
|
4031
|
+
upload_rest: string;
|
|
4032
|
+
ratio: string;
|
|
4033
|
+
ratio_free: string;
|
|
4034
|
+
zoom: string;
|
|
4035
|
+
rotate: string;
|
|
4036
|
+
reset: string;
|
|
4037
|
+
output_original: string;
|
|
4038
|
+
output_edited: string;
|
|
4039
|
+
oversized: string;
|
|
4040
|
+
edit_notice_title: string;
|
|
4041
|
+
edit_notice_body: string;
|
|
4042
|
+
replace_notice_title: string;
|
|
4043
|
+
replace_notice_body: string;
|
|
4044
|
+
saving: string;
|
|
4045
|
+
saved: string;
|
|
4046
|
+
formats_failed: string;
|
|
4047
|
+
};
|
|
4003
4048
|
drop_hint: string;
|
|
4004
4049
|
add_file: string;
|
|
4005
4050
|
cover_badge: string;
|
|
@@ -4055,11 +4100,10 @@ export declare const i18nMessages: {
|
|
|
4055
4100
|
replace: {
|
|
4056
4101
|
title: string;
|
|
4057
4102
|
action: string;
|
|
4058
|
-
unavailable: string;
|
|
4059
4103
|
hint: string;
|
|
4060
4104
|
accepts: string;
|
|
4061
4105
|
no_file: string;
|
|
4062
|
-
|
|
4106
|
+
queued: string;
|
|
4063
4107
|
};
|
|
4064
4108
|
regenerate: {
|
|
4065
4109
|
title: string;
|
|
@@ -6035,6 +6079,29 @@ export declare const i18nMessages: {
|
|
|
6035
6079
|
};
|
|
6036
6080
|
product_image: {
|
|
6037
6081
|
hint: string;
|
|
6082
|
+
crop_hint: string;
|
|
6083
|
+
editor: {
|
|
6084
|
+
title: string;
|
|
6085
|
+
subtitle_upload: string;
|
|
6086
|
+
subtitle_counter: string;
|
|
6087
|
+
subtitle_edit: string;
|
|
6088
|
+
upload_rest: string;
|
|
6089
|
+
ratio: string;
|
|
6090
|
+
ratio_free: string;
|
|
6091
|
+
zoom: string;
|
|
6092
|
+
rotate: string;
|
|
6093
|
+
reset: string;
|
|
6094
|
+
output_original: string;
|
|
6095
|
+
output_edited: string;
|
|
6096
|
+
oversized: string;
|
|
6097
|
+
edit_notice_title: string;
|
|
6098
|
+
edit_notice_body: string;
|
|
6099
|
+
replace_notice_title: string;
|
|
6100
|
+
replace_notice_body: string;
|
|
6101
|
+
saving: string;
|
|
6102
|
+
saved: string;
|
|
6103
|
+
formats_failed: string;
|
|
6104
|
+
};
|
|
6038
6105
|
drop_hint: string;
|
|
6039
6106
|
add_file: string;
|
|
6040
6107
|
cover_badge: string;
|
|
@@ -6090,11 +6157,10 @@ export declare const i18nMessages: {
|
|
|
6090
6157
|
replace: {
|
|
6091
6158
|
title: string;
|
|
6092
6159
|
action: string;
|
|
6093
|
-
unavailable: string;
|
|
6094
6160
|
hint: string;
|
|
6095
6161
|
accepts: string;
|
|
6096
6162
|
no_file: string;
|
|
6097
|
-
|
|
6163
|
+
queued: string;
|
|
6098
6164
|
};
|
|
6099
6165
|
regenerate: {
|
|
6100
6166
|
title: string;
|
|
@@ -8069,6 +8135,29 @@ export declare const i18nMessages: {
|
|
|
8069
8135
|
};
|
|
8070
8136
|
product_image: {
|
|
8071
8137
|
hint: string;
|
|
8138
|
+
crop_hint: string;
|
|
8139
|
+
editor: {
|
|
8140
|
+
title: string;
|
|
8141
|
+
subtitle_upload: string;
|
|
8142
|
+
subtitle_counter: string;
|
|
8143
|
+
subtitle_edit: string;
|
|
8144
|
+
upload_rest: string;
|
|
8145
|
+
ratio: string;
|
|
8146
|
+
ratio_free: string;
|
|
8147
|
+
zoom: string;
|
|
8148
|
+
rotate: string;
|
|
8149
|
+
reset: string;
|
|
8150
|
+
output_original: string;
|
|
8151
|
+
output_edited: string;
|
|
8152
|
+
oversized: string;
|
|
8153
|
+
edit_notice_title: string;
|
|
8154
|
+
edit_notice_body: string;
|
|
8155
|
+
replace_notice_title: string;
|
|
8156
|
+
replace_notice_body: string;
|
|
8157
|
+
saving: string;
|
|
8158
|
+
saved: string;
|
|
8159
|
+
formats_failed: string;
|
|
8160
|
+
};
|
|
8072
8161
|
drop_hint: string;
|
|
8073
8162
|
add_file: string;
|
|
8074
8163
|
cover_badge: string;
|
|
@@ -8124,11 +8213,10 @@ export declare const i18nMessages: {
|
|
|
8124
8213
|
replace: {
|
|
8125
8214
|
title: string;
|
|
8126
8215
|
action: string;
|
|
8127
|
-
unavailable: string;
|
|
8128
8216
|
hint: string;
|
|
8129
8217
|
accepts: string;
|
|
8130
8218
|
no_file: string;
|
|
8131
|
-
|
|
8219
|
+
queued: string;
|
|
8132
8220
|
};
|
|
8133
8221
|
regenerate: {
|
|
8134
8222
|
title: string;
|
|
@@ -10092,6 +10180,29 @@ export declare const i18nMessages: {
|
|
|
10092
10180
|
};
|
|
10093
10181
|
product_image: {
|
|
10094
10182
|
hint: string;
|
|
10183
|
+
crop_hint: string;
|
|
10184
|
+
editor: {
|
|
10185
|
+
title: string;
|
|
10186
|
+
subtitle_upload: string;
|
|
10187
|
+
subtitle_counter: string;
|
|
10188
|
+
subtitle_edit: string;
|
|
10189
|
+
upload_rest: string;
|
|
10190
|
+
ratio: string;
|
|
10191
|
+
ratio_free: string;
|
|
10192
|
+
zoom: string;
|
|
10193
|
+
rotate: string;
|
|
10194
|
+
reset: string;
|
|
10195
|
+
output_original: string;
|
|
10196
|
+
output_edited: string;
|
|
10197
|
+
oversized: string;
|
|
10198
|
+
edit_notice_title: string;
|
|
10199
|
+
edit_notice_body: string;
|
|
10200
|
+
replace_notice_title: string;
|
|
10201
|
+
replace_notice_body: string;
|
|
10202
|
+
saving: string;
|
|
10203
|
+
saved: string;
|
|
10204
|
+
formats_failed: string;
|
|
10205
|
+
};
|
|
10095
10206
|
drop_hint: string;
|
|
10096
10207
|
add_file: string;
|
|
10097
10208
|
cover_badge: string;
|
|
@@ -10147,11 +10258,10 @@ export declare const i18nMessages: {
|
|
|
10147
10258
|
replace: {
|
|
10148
10259
|
title: string;
|
|
10149
10260
|
action: string;
|
|
10150
|
-
unavailable: string;
|
|
10151
10261
|
hint: string;
|
|
10152
10262
|
accepts: string;
|
|
10153
10263
|
no_file: string;
|
|
10154
|
-
|
|
10264
|
+
queued: string;
|
|
10155
10265
|
};
|
|
10156
10266
|
regenerate: {
|
|
10157
10267
|
title: string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
2
|
+
modelValue: number;
|
|
3
|
+
min?: number | undefined;
|
|
4
|
+
max?: number | undefined;
|
|
5
|
+
step?: number | undefined;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
ariaLabel?: string | undefined;
|
|
8
|
+
/** Renders the bubble shown while dragging; no bubble when omitted. */
|
|
9
|
+
formatValue?: ((value: number) => string) | undefined;
|
|
10
|
+
}>, {
|
|
11
|
+
min: number;
|
|
12
|
+
max: number;
|
|
13
|
+
step: number;
|
|
14
|
+
disabled: boolean;
|
|
15
|
+
ariaLabel: undefined;
|
|
16
|
+
formatValue: undefined;
|
|
17
|
+
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
18
|
+
"update:modelValue": (value: number) => void;
|
|
19
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
20
|
+
modelValue: number;
|
|
21
|
+
min?: number | undefined;
|
|
22
|
+
max?: number | undefined;
|
|
23
|
+
step?: number | undefined;
|
|
24
|
+
disabled?: boolean | undefined;
|
|
25
|
+
ariaLabel?: string | undefined;
|
|
26
|
+
/** Renders the bubble shown while dragging; no bubble when omitted. */
|
|
27
|
+
formatValue?: ((value: number) => string) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
min: number;
|
|
30
|
+
max: number;
|
|
31
|
+
step: number;
|
|
32
|
+
disabled: boolean;
|
|
33
|
+
ariaLabel: undefined;
|
|
34
|
+
formatValue: undefined;
|
|
35
|
+
}>>> & Readonly<{
|
|
36
|
+
"onUpdate:modelValue"?: ((value: number) => any) | undefined;
|
|
37
|
+
}>, {
|
|
38
|
+
disabled: boolean;
|
|
39
|
+
max: number;
|
|
40
|
+
min: number;
|
|
41
|
+
step: number;
|
|
42
|
+
ariaLabel: string;
|
|
43
|
+
formatValue: (value: number) => string;
|
|
44
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
45
|
+
export default _default;
|
|
46
|
+
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
47
|
+
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
48
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
49
|
+
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
50
|
+
} : {
|
|
51
|
+
type: import('vue').PropType<T[K]>;
|
|
52
|
+
required: true;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
type __VLS_WithDefaults<P, D> = {
|
|
56
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
57
|
+
default: D[K];
|
|
58
|
+
}> : P[K];
|
|
59
|
+
};
|
|
60
|
+
type __VLS_Prettify<T> = {
|
|
61
|
+
[K in keyof T]: T[K];
|
|
62
|
+
} & {};
|
|
@@ -43,6 +43,52 @@ export declare function generateImageId(): string;
|
|
|
43
43
|
*/
|
|
44
44
|
export declare function autoAspectRatios(autoGenerate: boolean): AspectRatio[];
|
|
45
45
|
export declare function validateImageFile(file: File): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* The half of `validateImageFile` that is a real dead end.
|
|
48
|
+
*
|
|
49
|
+
* A file the browser cannot decode is refused outright, but being over
|
|
50
|
+
* `MAX_IMAGE_BYTES` is not a reason to refuse a photo any more: the editor re-encodes it
|
|
51
|
+
* under the limit (`canvasToFile`), which is the whole point of opening on upload. Call
|
|
52
|
+
* sites that hand bytes straight to media-service — Remy's output, a staged flush —
|
|
53
|
+
* still use the combined check, because nothing there can shrink a file.
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateImageType(file: File): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Longest edge the editor writes out.
|
|
58
|
+
*
|
|
59
|
+
* Generous — media-service derives every ratio from this original, and 2400px still
|
|
60
|
+
* covers a retina hero on the biggest POS screen — but bounded, so a 48MP phone photo
|
|
61
|
+
* cannot land as a 20 MB original that has to be re-encoded on every later edit.
|
|
62
|
+
*/
|
|
63
|
+
export declare const MAX_IMAGE_EDGE = 2400;
|
|
64
|
+
/**
|
|
65
|
+
* Encodes an edited canvas as a file guaranteed to be uploadable.
|
|
66
|
+
*
|
|
67
|
+
* "Guaranteed" is the job: `upload-intent` rejects anything over `MAX_IMAGE_BYTES` with a
|
|
68
|
+
* 413 and `updateOriginal` does the same on the encoded length, so the editor must not be
|
|
69
|
+
* able to hand back a file the service will refuse — that would put the merchant back at
|
|
70
|
+
* the dead end this feature exists to remove. Quality is spent first and pixels second,
|
|
71
|
+
* because a slightly softer photo beats a smaller one.
|
|
72
|
+
*
|
|
73
|
+
* PNG is kept only when the caller asks for it (a source with transparency); it has no
|
|
74
|
+
* quality lever, so it is shrunk by size alone.
|
|
75
|
+
*/
|
|
76
|
+
export declare function canvasToFile(canvas: HTMLCanvasElement, options: {
|
|
77
|
+
fileName: string;
|
|
78
|
+
mime: string;
|
|
79
|
+
maxEdge?: number;
|
|
80
|
+
maxBytes?: number;
|
|
81
|
+
}): Promise<File>;
|
|
82
|
+
/**
|
|
83
|
+
* Hands back the file untouched when it already fits `MAX_IMAGE_BYTES`, and otherwise
|
|
84
|
+
* re-encodes it under the limit exactly as the editor would — same edge cap, same
|
|
85
|
+
* PNG-stays-PNG rule.
|
|
86
|
+
*
|
|
87
|
+
* This is for the paths that upload a picked file without opening the editor (the
|
|
88
|
+
* "upload the rest as-is" batch): they get the same guarantee a confirmed edit has,
|
|
89
|
+
* instead of handing media-service bytes it will refuse with a 413.
|
|
90
|
+
*/
|
|
91
|
+
export declare function ensureUploadableImage(file: File, unreadableMessage?: string): Promise<File>;
|
|
46
92
|
/** Converts Remy's base64 result into an uploadable file without re-encoding it. */
|
|
47
93
|
export declare function dataUrlToFile(dataUrl: string, fileName?: string): Promise<File>;
|
|
48
94
|
/** `confirm` needs the real pixel size, and only the browser has it before upload. */
|
|
@@ -72,6 +118,34 @@ export declare function uploadProductImage(itemId: string, file: File, options:
|
|
|
72
118
|
imageId?: string;
|
|
73
119
|
unreadableMessage?: string;
|
|
74
120
|
}): Promise<FdoMenuV4ItemImage>;
|
|
121
|
+
/**
|
|
122
|
+
* Rewrites an existing image's original bytes, keeping its identity.
|
|
123
|
+
*
|
|
124
|
+
* This is what makes editing an uploaded photo cheap: `updateOriginal` overwrites the
|
|
125
|
+
* object in place, so `_id`, `url`, `isDefault`, `imageSet` and the item's dual-written
|
|
126
|
+
* `thumbnail` all stay as they are and the menu document needs no write at all. The
|
|
127
|
+
* returned image is the one that was passed in, unchanged — callers persist nothing.
|
|
128
|
+
*
|
|
129
|
+
* What does need doing is the ratios. media-service deliberately leaves them alone, so
|
|
130
|
+
* every ratio derived from the old photo is now stale and has to be queued again from the
|
|
131
|
+
* new one. Only the derived ones: a ratio whose `imageSet` value is set is a photo the
|
|
132
|
+
* merchant supplied for that shape, and re-deriving it would throw their work away. The
|
|
133
|
+
* requeue is `append` (via `generateAspectRatios`), never `create({ mode: "replace" })` —
|
|
134
|
+
* replace also deletes every variant missing from the request, which for a subset means
|
|
135
|
+
* deleting exactly the merchant's own ratios.
|
|
136
|
+
*
|
|
137
|
+
* `formatsRequeued` is reported rather than thrown: by the time a requeue can fail the
|
|
138
|
+
* original is already overwritten, and a rejected promise would tell the merchant their
|
|
139
|
+
* crop failed when it did not. They need to hear that the photo is saved and its formats
|
|
140
|
+
* are not, which only the caller can phrase.
|
|
141
|
+
*
|
|
142
|
+
* The caller must bump the image's cache stamp (`bumpImageVersion`) — the URL did not
|
|
143
|
+
* move, so nothing refetches on its own.
|
|
144
|
+
*/
|
|
145
|
+
export declare function updateProductImageOriginal(itemId: string, image: FdoMenuV4ItemImage, file: File): Promise<{
|
|
146
|
+
image: FdoMenuV4ItemImage;
|
|
147
|
+
formatsRequeued: boolean;
|
|
148
|
+
}>;
|
|
75
149
|
/**
|
|
76
150
|
* A file the merchant picked before the item it belongs to exists.
|
|
77
151
|
*
|
|
@@ -116,21 +190,30 @@ export declare function generateAspectRatios(itemId: string, image: FdoMenuV4Ite
|
|
|
116
190
|
/** `/images/update` carries its bytes inline, so the file has to become a data URL. */
|
|
117
191
|
export declare function readFileAsDataUrl(file: File): Promise<string>;
|
|
118
192
|
/**
|
|
119
|
-
*
|
|
193
|
+
* Queues one ratio to be generated from a photo the merchant supplies, and marks it
|
|
194
|
+
* custom.
|
|
195
|
+
*
|
|
196
|
+
* Named "replace" after what it does for the merchant, not after what reaches storage:
|
|
197
|
+
* media-service stores these bytes as the generation *source* and hands them to the
|
|
198
|
+
* model (`/images/update` with `base64`), so the variant ends up a redraw of the
|
|
199
|
+
* supplied photo rather than the photo itself. Cropping to `ratio` in the editor is what
|
|
200
|
+
* frames the subject for the model. It no longer pads the source to the ratio first: the
|
|
201
|
+
* service trims uniform bars off a generation source, so the bars were discarded before
|
|
202
|
+
* the model ever saw them — a real crop at least lets the merchant choose what survives.
|
|
120
203
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* anyway — the value exists to be checked for null, not to point somewhere else. The
|
|
126
|
-
* caller persists the returned image to save the marker.
|
|
204
|
+
* So this is asynchronous and billable, exactly like `regenerateAspectRatio`: the ratio
|
|
205
|
+
* drops back to `pending` for ~40s and one AI generation is consumed. Callers must show
|
|
206
|
+
* the ratio as generating and poll `listImages` — treating the returned image as final
|
|
207
|
+
* shows the merchant the old variant and calls it done.
|
|
127
208
|
*
|
|
128
|
-
* The
|
|
129
|
-
*
|
|
209
|
+
* The variant keeps its URL, so the only difference between the input image and the
|
|
210
|
+
* returned one is `imageSet[ratio]`: it now carries the variant URL as a marker meaning
|
|
211
|
+
* "not derived from the original". That URL is the same `{url}?aspect_ratio={ratio}` the
|
|
212
|
+
* consumer would compose anyway — the value exists to be checked for null, not to point
|
|
213
|
+
* somewhere else. The caller persists the returned image to save the marker.
|
|
130
214
|
*
|
|
131
|
-
* The
|
|
132
|
-
*
|
|
133
|
-
* variant is supposed to be exactly its ratio.
|
|
215
|
+
* The caller also has to bust its own image cache once the generation lands — the URL is
|
|
216
|
+
* "always latest" at the edge, but a browser that already fetched it will not know.
|
|
134
217
|
*/
|
|
135
218
|
export declare function replaceAspectRatioImage(itemId: string, image: FdoMenuV4ItemImage, ratio: AspectRatio, file: File): Promise<FdoMenuV4ItemImage>;
|
|
136
219
|
/**
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import "vue-advanced-cropper/dist/style.css";
|
|
2
|
+
/**
|
|
3
|
+
* What the dialog hands back: a thunk, not a file.
|
|
4
|
+
*
|
|
5
|
+
* Encoding a crop costs a full canvas re-encode, and the cropper emits `change` on every
|
|
6
|
+
* drag frame — emitting a File each time would re-encode a 12 MP photo dozens of times
|
|
7
|
+
* per gesture. So the parent gets a function and calls it once, on confirm.
|
|
8
|
+
*/
|
|
9
|
+
export type ProduceEditedImage = () => Promise<File | null>;
|
|
10
|
+
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
11
|
+
mode: "upload" | "edit" | "replace";
|
|
12
|
+
/** Absent in `replace`, where the merchant picks the photo inside the dialog. */
|
|
13
|
+
file?: File | null | undefined;
|
|
14
|
+
/** Locks the crop shape. Only `replace` sets it. */
|
|
15
|
+
ratio?: string | null | undefined;
|
|
16
|
+
/** How many generated formats a save will re-derive; drives the `edit` notice. */
|
|
17
|
+
derivedFormats?: number | undefined;
|
|
18
|
+
}>, {
|
|
19
|
+
file: null;
|
|
20
|
+
ratio: null;
|
|
21
|
+
derivedFormats: number;
|
|
22
|
+
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
23
|
+
mode: "upload" | "edit" | "replace";
|
|
24
|
+
/** Absent in `replace`, where the merchant picks the photo inside the dialog. */
|
|
25
|
+
file?: File | null | undefined;
|
|
26
|
+
/** Locks the crop shape. Only `replace` sets it. */
|
|
27
|
+
ratio?: string | null | undefined;
|
|
28
|
+
/** How many generated formats a save will re-derive; drives the `edit` notice. */
|
|
29
|
+
derivedFormats?: number | undefined;
|
|
30
|
+
}>, {
|
|
31
|
+
file: null;
|
|
32
|
+
ratio: null;
|
|
33
|
+
derivedFormats: number;
|
|
34
|
+
}>>> & Readonly<{}>, {
|
|
35
|
+
ratio: string | null;
|
|
36
|
+
file: File | null;
|
|
37
|
+
derivedFormats: number;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
39
|
+
export default _default;
|
|
40
|
+
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
41
|
+
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
42
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
43
|
+
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
44
|
+
} : {
|
|
45
|
+
type: import('vue').PropType<T[K]>;
|
|
46
|
+
required: true;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
type __VLS_WithDefaults<P, D> = {
|
|
50
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
51
|
+
default: D[K];
|
|
52
|
+
}> : P[K];
|
|
53
|
+
};
|
|
54
|
+
type __VLS_Prettify<T> = {
|
|
55
|
+
[K in keyof T]: T[K];
|
|
56
|
+
} & {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The original behind `url` as a `File`, from memory when it has been read before.
|
|
3
|
+
*
|
|
4
|
+
* Returns null when it cannot be read, exactly like `fetchImageAsBlob` — a failure is
|
|
5
|
+
* never remembered, so the next click is free to try again.
|
|
6
|
+
*/
|
|
7
|
+
export declare function readImageFile(url: string, imageId: string, filename?: string): Promise<File | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Call after the bytes behind `imageId` have been rewritten. */
|
|
2
|
+
export declare function bumpImageVersion(imageId: string): void;
|
|
3
|
+
/**
|
|
4
|
+
* Appends the current stamp for `imageId`, if it has one.
|
|
5
|
+
*
|
|
6
|
+
* Untouched images are returned as-is rather than stamped with a constant: the URL is a
|
|
7
|
+
* cache key, and a first render that already differs from what POS requests would throw
|
|
8
|
+
* away a warm edge entry for nothing.
|
|
9
|
+
*/
|
|
10
|
+
export declare function stampImageUrl(url: string, imageId: string): string;
|
|
11
|
+
export declare function stampImageUrl(url: string | null | undefined, imageId: string): string | null | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FdoItemOverriderV4 } from "@feedmepos/entity";
|
|
2
|
+
/**
|
|
3
|
+
* Pick an item's base (non-variant) overrider out of an overrider list.
|
|
4
|
+
*
|
|
5
|
+
* Catalog/scheduler overrider maps only hold entries for items that were
|
|
6
|
+
* actually overridden, so the list is often absent entirely. When it exists it
|
|
7
|
+
* is ordered `[...variantCombinations, baseOverrider]`, so index 0 is not the
|
|
8
|
+
* base overrider once the item has variants.
|
|
9
|
+
*/
|
|
10
|
+
export declare function pickBaseOverrider(overriders: FdoItemOverriderV4[] | undefined | null): FdoItemOverriderV4 | undefined;
|