@feedmepos/mf-miniprogram-v2 0.2.2-dev.2 → 0.2.2-dev.21

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 (33) hide show
  1. package/dist/App-BdvPLQMC.js +213 -0
  2. package/dist/AppTemplatePicker-CNJ6kIJk.js +237 -0
  3. package/dist/BrandFontPicker-kQKWf1hL.js +241 -0
  4. package/dist/BrandKitView-RaUWE69b.js +249 -0
  5. package/dist/{ControlPlaneView-DmhLvgWt.js → ControlPlaneView-l_gDDBtb.js} +8854 -8140
  6. package/dist/EcosystemView-CBEL5PT2.js +186 -0
  7. package/dist/{LegacyWorkspaceEntry-7DvIosoj.js → LegacyWorkspaceEntry-lEMtmdIe.js} +1 -1
  8. package/dist/MobileProjectsView-BruZHfdq.js +312 -0
  9. package/dist/{ModuleCenterView-Dqp-2hbL.js → ModuleCenterView-DI6Pakkr.js} +34 -34
  10. package/dist/{ModuleDetailView-cpQ_UfS9.js → ModuleDetailView-DteTTb-3.js} +49 -49
  11. package/dist/{PagesView-BHo_fnWa.js → PagesView-BYzldeqE.js} +1 -1
  12. package/dist/{PortalSettingsView-CkW-avwg.js → PortalSettingsView-Bl4z9cFG.js} +4 -4
  13. package/dist/StatusBadge.vue_vue_type_script_setup_true_lang-CMgQ0bd_.js +30 -0
  14. package/dist/TemplateCenterView-DNjVytwE.js +364 -0
  15. package/dist/{WorkspaceEntryView-ZdXuMQoJ.js → WorkspaceEntryView-BIumdrty.js} +1 -1
  16. package/dist/app.js +27 -10
  17. package/dist/{controlPlane-wUT1G_Gr.js → controlPlane-sXaC6pAh.js} +9 -9
  18. package/dist/{index-BDHUHtRw.js → index-CIJWcl_6.js} +25 -15
  19. package/dist/package.json +2 -1
  20. package/dist/{portalContext-CTVzkJV7.js → portalContext-BFTX5VVx.js} +2 -2
  21. package/dist/routes-D6BQSP4i.js +81 -0
  22. package/dist/style.css +1 -1
  23. package/dist/templatePickerFlag-BIYWgnaS.js +59 -0
  24. package/dist/useBrandKit-CkdPQRE-.js +1020 -0
  25. package/dist/{useModuleCatalog-CD5N246F.js → useModuleCatalog-Bk-gRmBb.js} +3 -3
  26. package/package.json +2 -1
  27. package/dist/App-D7vZDj-a.js +0 -213
  28. package/dist/BrandKitView-B8t8RkHr.js +0 -221
  29. package/dist/EcosystemView--S4hk_t4.js +0 -232
  30. package/dist/StatusBadge.vue_vue_type_script_setup_true_lang-Bh9Eoe_H.js +0 -26
  31. package/dist/localPreference-DneUpUrQ.js +0 -34
  32. package/dist/routes-L0ady_Wy.js +0 -53
  33. package/dist/useBrandKit-CpyR2j6m.js +0 -924
@@ -1,11 +1,11 @@
1
- import { defineComponent as C, ref as M, computed as u, watch as T, resolveComponent as g, openBlock as n, createElementBlock as l, createElementVNode as e, toDisplayString as r, createCommentVNode as _, Fragment as I, renderList as S, createVNode as k, onMounted as B, unref as d, withCtx as L, createBlock as v } from "vue";
1
+ import { defineComponent as C, ref as M, computed as u, watch as T, resolveComponent as g, openBlock as n, createElementBlock as l, createElementVNode as e, toDisplayString as i, createCommentVNode as _, Fragment as I, renderList as S, createVNode as k, onMounted as B, unref as d, withCtx as L, createBlock as v } from "vue";
2
2
  import { useRoute as N, useRouter as P } from "vue-router";
3
- import { m as q, i as A, u as F, _ as w } from "./useModuleCatalog-CD5N246F.js";
3
+ import { m as q, i as A, u as F, _ as w } from "./useModuleCatalog-Bk-gRmBb.js";
4
4
  import { useDialog as V } from "@feedmepos/ui-library";
5
5
  import { _ as E } from "./_plugin-vue_export-helper-CHgC5LLL.js";
6
- const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "detail__name fm-typo-en-title-sm-600 text-fm-color-typo-primary" }, K = { class: "detail__version fm-typo-en-body-md-400 text-fm-color-typo-tertiary" }, O = {
6
+ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "detail__name fm-typo-en-title-sm-600 text-portal-text-primary" }, K = { class: "detail__version fm-typo-en-body-md-400 text-portal-text-muted" }, O = {
7
7
  key: 0,
8
- class: "detail__description fm-typo-en-body-md-400 text-fm-color-typo-secondary"
8
+ class: "detail__description fm-typo-en-body-md-400 text-portal-text-muted"
9
9
  }, Y = { class: "detail__columns" }, G = { class: "detail__preview" }, H = {
10
10
  key: 0,
11
11
  class: "detail__note detail__note--error fm-typo-en-body-md-400"
@@ -21,7 +21,7 @@ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "deta
21
21
  }, se = {
22
22
  key: 0,
23
23
  class: "detail__optional fm-typo-en-body-sm-400"
24
- }, le = { class: "detail__section" }, ae = ["value"], re = /* @__PURE__ */ C({
24
+ }, le = { class: "detail__section" }, ae = ["value"], ie = /* @__PURE__ */ C({
25
25
  __name: "ModuleDetail",
26
26
  props: {
27
27
  entry: {},
@@ -29,24 +29,24 @@ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "deta
29
29
  previewError: {}
30
30
  },
31
31
  setup(o) {
32
- const i = o, f = V(), s = M(!1);
33
- let c;
34
- const m = u(() => q(i.entry)), y = u(
35
- () => i.previewDocument ? A(i.previewDocument, i.entry.name) : null
32
+ const r = o, b = V(), s = M(!1);
33
+ let m;
34
+ const c = u(() => q(r.entry)), p = u(
35
+ () => r.previewDocument ? A(r.previewDocument, r.entry.name) : null
36
36
  );
37
37
  T(
38
- () => i.entry.name,
38
+ () => r.entry.name,
39
39
  () => {
40
40
  s.value = !1;
41
41
  }
42
42
  );
43
43
  async function x() {
44
44
  try {
45
- await navigator.clipboard.writeText(m.value), s.value = !0, window.clearTimeout(c), c = window.setTimeout(() => {
45
+ await navigator.clipboard.writeText(c.value), s.value = !0, window.clearTimeout(m), m = window.setTimeout(() => {
46
46
  s.value = !1;
47
47
  }, 2e3);
48
48
  } catch (a) {
49
- f.open({
49
+ b.open({
50
50
  title: "Could not copy",
51
51
  message: `${a instanceof Error ? a.message : String(a)}. Select the text below and copy it manually.`,
52
52
  dismissAway: !0,
@@ -55,62 +55,62 @@ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "deta
55
55
  }
56
56
  }
57
57
  return (a, t) => {
58
- var p, D, $;
59
- const b = g("FmButton");
58
+ var y, D, $;
59
+ const f = g("FmButton");
60
60
  return n(), l("div", R, [
61
61
  e("header", j, [
62
- e("h3", z, r(o.entry.name), 1),
63
- e("span", K, r(o.entry.version), 1),
64
- o.entry.description ? (n(), l("p", O, r(o.entry.description), 1)) : _("", !0)
62
+ e("h3", z, i(o.entry.name), 1),
63
+ e("span", K, i(o.entry.version), 1),
64
+ o.entry.description ? (n(), l("p", O, i(o.entry.description), 1)) : _("", !0)
65
65
  ]),
66
66
  e("div", Y, [
67
67
  e("section", G, [
68
- t[0] || (t[0] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-fm-color-typo-tertiary" }, "Preview", -1)),
69
- o.previewError ? (n(), l("p", H, r(o.previewError), 1)) : y.value ? (n(), l("iframe", {
68
+ t[0] || (t[0] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-portal-text-muted" }, "Preview", -1)),
69
+ o.previewError ? (n(), l("p", H, i(o.previewError), 1)) : p.value ? (n(), l("iframe", {
70
70
  key: o.entry.name,
71
71
  class: "detail__frame",
72
72
  title: "module preview",
73
73
  sandbox: "allow-scripts",
74
- srcdoc: y.value
74
+ srcdoc: p.value
75
75
  }, null, 8, Q)) : (n(), l("p", J, "Loading preview…")),
76
- t[1] || (t[1] = e("p", { class: "detail__hint fm-typo-en-body-sm-400 text-fm-color-typo-tertiary" }, " Stand-in brand colours. Your business's own palette applies in the workspace preview. ", -1))
76
+ t[1] || (t[1] = e("p", { class: "detail__hint fm-typo-en-body-sm-400 text-portal-text-muted" }, " Stand-in brand colours. Your business's own palette applies in the workspace preview. ", -1))
77
77
  ]),
78
78
  e("div", U, [
79
79
  e("section", W, [
80
- t[6] || (t[6] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-fm-color-typo-tertiary" }, "Details", -1)),
80
+ t[6] || (t[6] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-portal-text-muted" }, "Details", -1)),
81
81
  e("dl", X, [
82
82
  t[2] || (t[2] = e("dt", null, "Id", -1)),
83
- e("dd", null, r(o.entry.id), 1),
83
+ e("dd", null, i(o.entry.id), 1),
84
84
  t[3] || (t[3] = e("dt", null, "Slot", -1)),
85
- e("dd", null, r(o.entry.slot ?? "—"), 1),
85
+ e("dd", null, i(o.entry.slot ?? "—"), 1),
86
86
  t[4] || (t[4] = e("dt", null, "Data shape", -1)),
87
- e("dd", null, r(o.entry.dataShape ?? "—"), 1),
87
+ e("dd", null, i(o.entry.dataShape ?? "—"), 1),
88
88
  t[5] || (t[5] = e("dt", null, "Type", -1)),
89
- e("dd", null, r(o.entry.category), 1),
90
- (p = o.entry.labels) != null && p.length ? (n(), l("dt", Z, "Labels")) : _("", !0),
91
- (D = o.entry.labels) != null && D.length ? (n(), l("dd", ee, r(o.entry.labels.join(", ")), 1)) : _("", !0)
89
+ e("dd", null, i(o.entry.category), 1),
90
+ (y = o.entry.labels) != null && y.length ? (n(), l("dt", Z, "Labels")) : _("", !0),
91
+ (D = o.entry.labels) != null && D.length ? (n(), l("dd", ee, i(o.entry.labels.join(", ")), 1)) : _("", !0)
92
92
  ])
93
93
  ]),
94
94
  e("section", te, [
95
- t[7] || (t[7] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-fm-color-typo-tertiary" }, "Props", -1)),
95
+ t[7] || (t[7] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-portal-text-muted" }, "Props", -1)),
96
96
  ($ = o.entry.props) != null && $.length ? (n(), l("ul", ne, [
97
97
  (n(!0), l(I, null, S(o.entry.props, (h) => (n(), l("li", {
98
98
  key: h.name
99
99
  }, [
100
- e("code", null, r(h.name), 1),
100
+ e("code", null, i(h.name), 1),
101
101
  h.required ? _("", !0) : (n(), l("span", se, "optional"))
102
102
  ]))), 128))
103
103
  ])) : (n(), l("p", oe, " This module declares no props interface, so it can only be offered as a like-for-like swap. "))
104
104
  ]),
105
105
  e("section", le, [
106
- t[8] || (t[8] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-fm-color-typo-tertiary" }, "Ask the agent for it", -1)),
107
- t[9] || (t[9] = e("p", { class: "detail__hint fm-typo-en-body-sm-400 text-fm-color-typo-tertiary" }, " Paste this into a workspace chat. The agent copies the module into your app's own code. ", -1)),
106
+ t[8] || (t[8] = e("h4", { class: "detail__label fm-typo-en-body-sm-600 text-portal-text-muted" }, "Ask the agent for it", -1)),
107
+ t[9] || (t[9] = e("p", { class: "detail__hint fm-typo-en-body-sm-400 text-portal-text-muted" }, " Paste this into a workspace chat. The agent copies the module into your app's own code. ", -1)),
108
108
  e("textarea", {
109
109
  class: "detail__prompt",
110
110
  readonly: "",
111
- value: m.value
111
+ value: c.value
112
112
  }, null, 8, ae),
113
- k(b, {
113
+ k(f, {
114
114
  class: "detail__copy",
115
115
  size: "md",
116
116
  variant: s.value ? "secondary" : "primary",
@@ -124,22 +124,22 @@ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "deta
124
124
  ]);
125
125
  };
126
126
  }
127
- }), ie = /* @__PURE__ */ E(re, [["__scopeId", "data-v-ad739f79"]]), de = { class: "shell" }, ce = { class: "page" }, me = { class: "page__inner" }, ue = { class: "page__head" }, ye = {
127
+ }), re = /* @__PURE__ */ E(ie, [["__scopeId", "data-v-dc44acc5"]]), de = { class: "shell" }, me = { class: "page" }, ce = { class: "page__inner" }, ue = { class: "page__head" }, pe = {
128
128
  key: 0,
129
129
  class: "page__note fm-typo-en-body-md-400"
130
- }, pe = /* @__PURE__ */ C({
130
+ }, ye = /* @__PURE__ */ C({
131
131
  __name: "ModuleDetailView",
132
132
  setup(o) {
133
- const i = N(), f = P(), s = F(), c = u(() => String(i.params.name ?? "")), m = u(() => s.find(c.value)), y = u(() => s.entries.value === null);
133
+ const r = N(), b = P(), s = F(), m = u(() => String(r.params.name ?? "")), c = u(() => s.find(m.value)), p = u(() => s.entries.value === null);
134
134
  return B(() => s.load()), (x, a) => {
135
- const t = g("FmIcon"), b = g("RouterLink");
135
+ const t = g("FmIcon"), f = g("RouterLink");
136
136
  return n(), l("div", de, [
137
- e("div", ce, [
138
- e("div", me, [
137
+ e("div", me, [
138
+ e("div", ce, [
139
139
  e("header", ue, [
140
- k(b, {
140
+ k(f, {
141
141
  class: "page__back",
142
- to: { name: "miniprogram-v2-module-center", query: d(i).query }
142
+ to: { name: "miniprogram-v2-module-center", query: d(r).query }
143
143
  }, {
144
144
  default: L(() => [
145
145
  k(t, {
@@ -152,38 +152,38 @@ const R = { class: "detail" }, j = { class: "detail__head" }, z = { class: "deta
152
152
  _: 1
153
153
  }, 8, ["to"])
154
154
  ]),
155
- y.value ? (n(), l("p", ye, "Loading…")) : d(s).loadError.value ? (n(), v(w, {
155
+ p.value ? (n(), l("p", pe, "Loading…")) : d(s).loadError.value ? (n(), v(w, {
156
156
  key: 1,
157
157
  icon: "error_outline",
158
158
  tone: "error",
159
159
  title: "Could not load the module library",
160
160
  message: d(s).loadError.value,
161
161
  "action-label": "Try again",
162
- onAction: a[0] || (a[0] = (p) => d(s).load(!0))
162
+ onAction: a[0] || (a[0] = (y) => d(s).load(!0))
163
163
  }, null, 8, ["message"])) : d(s).unpublished.value ? (n(), v(w, {
164
164
  key: 2,
165
165
  icon: "widgets",
166
166
  title: "No module library has been published yet",
167
167
  message: "Nothing has been published for this page to show."
168
- })) : m.value ? (n(), v(ie, {
168
+ })) : c.value ? (n(), v(re, {
169
169
  key: 4,
170
- entry: m.value,
170
+ entry: c.value,
171
171
  "preview-document": d(s).previewDocument.value,
172
172
  "preview-error": d(s).previewError.value
173
173
  }, null, 8, ["entry", "preview-document", "preview-error"])) : (n(), v(w, {
174
174
  key: 3,
175
175
  icon: "search_off",
176
- title: `No module named “${c.value}”`,
176
+ title: `No module named “${m.value}”`,
177
177
  message: "It is not in the published library. It may have been renamed, withdrawn, or never published.",
178
178
  "action-label": "Back to the library",
179
- onAction: a[1] || (a[1] = (p) => d(f).push({ name: "miniprogram-v2-module-center", query: d(i).query }))
179
+ onAction: a[1] || (a[1] = (y) => d(b).push({ name: "miniprogram-v2-module-center", query: d(r).query }))
180
180
  }, null, 8, ["title"]))
181
181
  ])
182
182
  ])
183
183
  ]);
184
184
  };
185
185
  }
186
- }), we = /* @__PURE__ */ E(pe, [["__scopeId", "data-v-c0e81d59"]]);
186
+ }), we = /* @__PURE__ */ E(ye, [["__scopeId", "data-v-70b1bf30"]]);
187
187
  export {
188
188
  we as default
189
189
  };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as p, resolveComponent as i, openBlock as l, createElementBlock as m, createElementVNode as o, createVNode as r, unref as t, withCtx as u, createTextVNode as c } from "vue";
2
2
  import { useRoute as d } from "vue-router";
3
- import { u as g } from "./portalContext-CTVzkJV7.js";
3
+ import { u as g } from "./portalContext-BFTX5VVx.js";
4
4
  import { w as f } from "./portalNavigation-DKCfwTH8.js";
5
5
  import { P as k } from "./PortalIcon-DO0VrIoY.js";
6
6
  const w = { class: "portal-page" }, y = { class: "portal-page-inner" }, b = { class: "portal-section portal-empty" }, E = /* @__PURE__ */ p({
@@ -1,9 +1,9 @@
1
1
  import { defineComponent as k, computed as p, ref as l, onMounted as P, onScopeDispose as S, resolveComponent as x, openBlock as o, createElementBlock as n, createElementVNode as s, toDisplayString as d, createCommentVNode as h, Fragment as I, createVNode as A, unref as M } from "vue";
2
2
  import { useRoute as N } from "vue-router";
3
- import { e as _, a as $ } from "./index-BDHUHtRw.js";
4
- import { l as B, e as E } from "./controlPlane-wUT1G_Gr.js";
3
+ import { e as _, a as $ } from "./index-CIJWcl_6.js";
4
+ import { l as B, e as E } from "./controlPlane-sXaC6pAh.js";
5
5
  import { useCoreStore as F } from "@feedmepos/mf-common";
6
- import { u as U } from "./portalContext-CTVzkJV7.js";
6
+ import { u as U } from "./portalContext-BFTX5VVx.js";
7
7
  import { l as V } from "./portalNavigation-DKCfwTH8.js";
8
8
  import { _ as q } from "./_plugin-vue_export-helper-CHgC5LLL.js";
9
9
  const L = { class: "portal-page" }, R = { class: "portal-page-inner settings-page" }, T = { class: "portal-page-heading" }, D = ["href"], H = {
@@ -117,7 +117,7 @@ const L = { class: "portal-page" }, R = { class: "portal-page-inner settings-pag
117
117
  ]);
118
118
  };
119
119
  }
120
- }), ue = /* @__PURE__ */ q(X, [["__scopeId", "data-v-b72a2c99"]]);
120
+ }), ue = /* @__PURE__ */ q(X, [["__scopeId", "data-v-6c0e4447"]]);
121
121
  export {
122
122
  ue as default
123
123
  };
@@ -0,0 +1,30 @@
1
+ import { defineComponent as p, computed as a, openBlock as c, createElementBlock as l, normalizeClass as m, renderSlot as i } from "vue";
2
+ const d = /* @__PURE__ */ p({
3
+ __name: "StatusBadge",
4
+ props: {
5
+ variant: { default: "neutral" },
6
+ size: { default: "md" }
7
+ },
8
+ setup(e) {
9
+ const o = e, t = {
10
+ success: "bg-fm-color-system-success-100 text-fm-color-typo-success",
11
+ warning: "bg-fm-color-system-warning-100 text-fm-color-typo-warning",
12
+ error: "bg-fm-color-system-error-100 text-fm-color-typo-error",
13
+ info: "bg-fm-color-system-info-100 text-fm-color-typo-info",
14
+ neutral: "bg-fm-color-neutral-gray-100 text-fm-color-typo-secondary",
15
+ primary: "bg-fm-color-primary text-fm-color-typo-white"
16
+ }, r = {
17
+ xs: "rounded-[4px] px-[4px] py-[2px] text-[10px] leading-[14px] font-medium tracking-[0.2px]",
18
+ sm: "rounded-[4px] px-[6px] py-[4px] text-[12px] leading-[16px] font-medium tracking-[0.24px]",
19
+ md: "rounded-full px-8 py-2 leading-[16px]"
20
+ }, n = a(() => r[o.size]);
21
+ return (s, x) => (c(), l("span", {
22
+ class: m(["inline-flex shrink-0 items-center gap-4", [t[e.variant], n.value]])
23
+ }, [
24
+ i(s.$slots, "default")
25
+ ], 2));
26
+ }
27
+ });
28
+ export {
29
+ d as _
30
+ };
@@ -0,0 +1,364 @@
1
+ import { defineComponent as N, ref as i, computed as $, resolveComponent as T, openBlock as o, createBlock as O, withCtx as D, createElementVNode as t, createElementBlock as r, Fragment as R, createTextVNode as w, toDisplayString as u, createVNode as d, createCommentVNode as f, onMounted as M, renderList as E, unref as B } from "vue";
2
+ import { a as C } from "./routes-D6BQSP4i.js";
3
+ import { useDialog as L } from "@feedmepos/ui-library";
4
+ import { useRouter as U } from "vue-router";
5
+ import { c as F, e as P } from "./controlPlane-sXaC6pAh.js";
6
+ import { _ as S } from "./_plugin-vue_export-helper-CHgC5LLL.js";
7
+ const z = [
8
+ // `label` and `description` are MERCHANT-FACING: the portal's picker renders
9
+ // them, and they are the only thing a merchant chooses on. Say what the app does
10
+ // for their customers, never which package it is built from — the SDK is real and
11
+ // load-bearing and means nothing to the person making this decision. These are
12
+ // the exact texts merchants were already seeing via the old choice layer's own
13
+ // label/description (kept verbatim across its removal — a refactor is not the
14
+ // moment to also silently change picker copy).
15
+ {
16
+ id: "miniprogram-vue",
17
+ label: "V1 · Phone ordering",
18
+ description: "The established phone ordering experience with menu, checkout, membership, rewards and order history.",
19
+ industries: [],
20
+ environments: ["dev", "prod"],
21
+ default: !0
22
+ },
23
+ {
24
+ id: "miniprogram-vue-v2",
25
+ label: "V2 · Baseline",
26
+ description: "The FeedMe v1 customer app's interface, on the v2 kernel: order medallions, the order-history rail, a category rail beside a continuous menu, and the round reviewed in a sheet. The baseline every other v2 style departs from.",
27
+ industries: ["Food & beverage"],
28
+ // Dev only, deliberately. It has never been provisioned end-to-end: the
29
+ // preview proxy, the component-library unpack and the release build have
30
+ // only been exercised locally. Add 'prod' after a real merchant has run
31
+ // through all three.
32
+ environments: ["dev"],
33
+ restaurantStyle: "qsr"
34
+ },
35
+ // Forked from miniprogram-vue-v2 (2026-09): the coffee and tea styles used
36
+ // to be a `restaurantStyle` sharing that one directory, which meant editing
37
+ // one style's components risked changing what the other two rendered. Each
38
+ // now has its own independent directory; only `templates/block-library/` is
39
+ // still shared across all three.
40
+ {
41
+ id: "miniprogram-vue-v2-coffee",
42
+ label: "V2 · Coffee house",
43
+ description: "A calm, image-led experience for habitual pickup, premium drinks and considered customisation.",
44
+ industries: ["Food & beverage"],
45
+ environments: ["dev"],
46
+ restaurantStyle: "coffee"
47
+ },
48
+ {
49
+ id: "miniprogram-vue-v2-tea",
50
+ label: "V2 · Tea & beverage",
51
+ description: "A light, compact and option-forward experience for repeat beverage orders with many customisations.",
52
+ industries: ["Food & beverage"],
53
+ environments: ["dev"],
54
+ restaurantStyle: "tea"
55
+ }
56
+ ], G = ["href"], H = {
57
+ key: 0,
58
+ class: "portal-error",
59
+ role: "alert"
60
+ }, J = "miniprogram-vue-v2", W = /* @__PURE__ */ N({
61
+ __name: "ForkTemplateDialog",
62
+ emits: ["close", "created"],
63
+ setup(j, { emit: V }) {
64
+ const _ = V, p = i(""), m = i(""), g = i(""), c = i(!1), s = i(""), v = i(""), A = i(0), h = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, x = $(
65
+ () => !c.value && h.test(p.value.trim()) && m.value.trim().length > 0 && g.value.trim().length > 0
66
+ );
67
+ async function q() {
68
+ if (x.value) {
69
+ c.value = !0, s.value = "";
70
+ try {
71
+ const y = await F(C.forkAppTemplate(), {
72
+ method: "POST",
73
+ body: JSON.stringify({
74
+ sourceAppTemplateId: J,
75
+ newAppTemplateId: p.value.trim(),
76
+ label: m.value.trim(),
77
+ description: g.value.trim()
78
+ })
79
+ });
80
+ v.value = y.pullRequestUrl, A.value = y.fileCount, _("created");
81
+ } catch (y) {
82
+ s.value = P(y);
83
+ } finally {
84
+ c.value = !1;
85
+ }
86
+ }
87
+ }
88
+ return (y, n) => {
89
+ const k = T("FmButton"), a = T("FmTextField"), l = T("FmTextarea"), b = T("FmCard");
90
+ return o(), O(b, { class: "fork-template-dialog" }, {
91
+ default: D(() => [
92
+ n[7] || (n[7] = t("h2", null, "Create template", -1)),
93
+ v.value ? (o(), r(R, { key: 0 }, [
94
+ t("p", null, [
95
+ w(" Opened a pull request copying " + u(A.value) + " file(s) into a brand-new ", 1),
96
+ t("code", null, "templates/" + u(p.value) + "/", 1),
97
+ n[5] || (n[5] = w(" directory, and registering it in the template catalog. It needs human review and merge — once merged and deployed, it appears here and in the merchant picker automatically; there is no separate step to enable it. ", -1))
98
+ ]),
99
+ t("footer", null, [
100
+ t("a", {
101
+ class: "fork-template-dialog__review-link",
102
+ href: v.value,
103
+ target: "_blank",
104
+ rel: "noopener"
105
+ }, "Review PR", 8, G),
106
+ d(k, {
107
+ label: "Done",
108
+ onClick: n[0] || (n[0] = (e) => _("close"))
109
+ })
110
+ ])
111
+ ], 64)) : (o(), r(R, { key: 1 }, [
112
+ n[6] || (n[6] = t("p", { class: "fork-template-dialog__note" }, " Copies the v2 baseline template's whole directory into a brand-new, independent one — editing the new one can never affect the baseline or any other template. Use this to start a new restaurant style rather than editing a style that other merchants already share. ", -1)),
113
+ d(a, {
114
+ modelValue: p.value,
115
+ "onUpdate:modelValue": n[1] || (n[1] = (e) => p.value = e),
116
+ label: "New template id",
117
+ placeholder: "e.g. miniprogram-vue-v2-bakery",
118
+ "helper-text": "Lowercase, kebab-case. Also becomes the directory name and GitHub repository name.",
119
+ disabled: c.value,
120
+ rules: [(e) => h.test(e.trim()) || "Lowercase kebab-case, e.g. miniprogram-vue-v2-bakery"]
121
+ }, null, 8, ["modelValue", "disabled", "rules"]),
122
+ d(a, {
123
+ modelValue: m.value,
124
+ "onUpdate:modelValue": n[2] || (n[2] = (e) => m.value = e),
125
+ label: "Label",
126
+ placeholder: "Shown to merchants in the picker",
127
+ disabled: c.value
128
+ }, null, 8, ["modelValue", "disabled"]),
129
+ d(l, {
130
+ modelValue: g.value,
131
+ "onUpdate:modelValue": n[3] || (n[3] = (e) => g.value = e),
132
+ label: "Description",
133
+ placeholder: "One or two sentences on what the merchant gets",
134
+ disabled: c.value
135
+ }, null, 8, ["modelValue", "disabled"]),
136
+ s.value ? (o(), r("p", H, u(s.value), 1)) : f("", !0),
137
+ t("footer", null, [
138
+ d(k, {
139
+ label: "Cancel",
140
+ variant: "tertiary",
141
+ disabled: c.value,
142
+ onClick: n[4] || (n[4] = (e) => _("close"))
143
+ }, null, 8, ["disabled"]),
144
+ d(k, {
145
+ label: "Open pull request",
146
+ loading: c.value,
147
+ disabled: !x.value,
148
+ onClick: q
149
+ }, null, 8, ["loading", "disabled"])
150
+ ])
151
+ ], 64))
152
+ ]),
153
+ _: 1
154
+ });
155
+ };
156
+ }
157
+ }), K = /* @__PURE__ */ S(W, [["__scopeId", "data-v-5a38928f"]]), Q = { class: "portal-page" }, X = { class: "portal-page-inner" }, Y = { class: "portal-page-heading" }, Z = { class: "portal-page-heading__actions" }, ee = {
158
+ key: 0,
159
+ class: "portal-error",
160
+ role: "alert"
161
+ }, te = {
162
+ key: 1,
163
+ "aria-label": "Templates in review"
164
+ }, ae = { class: "template-section-heading" }, le = {
165
+ key: 0,
166
+ class: "portal-error",
167
+ role: "alert"
168
+ }, ne = {
169
+ key: 1,
170
+ class: "template-choices__list",
171
+ "aria-label": "Templates in review"
172
+ }, oe = { class: "template-choices__name" }, se = { class: "template-choices__label" }, re = { class: "template-choices__id" }, ie = { class: "template-choices__actions" }, ce = ["href"], ue = {
173
+ class: "template-choices__list",
174
+ "aria-label": "Physical templates"
175
+ }, de = { class: "template-choices__name" }, pe = { class: "template-choices__label" }, me = { key: 0 }, ve = { class: "template-choices__id" }, he = { class: "template-choices__meta" }, ge = { class: "template-choices__actions" }, _e = /* @__PURE__ */ N({
176
+ __name: "TemplateCenterView",
177
+ setup(j) {
178
+ const V = U(), _ = L(), p = i(""), m = i(null), g = i([]), c = i(!1), s = i("");
179
+ async function v() {
180
+ c.value = !0, s.value = "";
181
+ try {
182
+ const a = await F(C.pendingTemplateForks());
183
+ g.value = a.forks;
184
+ } catch (a) {
185
+ s.value = P(a);
186
+ } finally {
187
+ c.value = !1;
188
+ }
189
+ }
190
+ function A() {
191
+ _.open({
192
+ title: "Create template",
193
+ dialogComponent: K,
194
+ dialogComponentProps: { onClose: () => _.close(), onCreated: () => void v() }
195
+ });
196
+ }
197
+ const h = i(null);
198
+ async function x(a) {
199
+ h.value = a.pullRequestNumber, s.value = "";
200
+ try {
201
+ await F(C.mergePendingTemplateFork(a.pullRequestNumber), { method: "POST" }), await v();
202
+ } catch (l) {
203
+ s.value = P(l);
204
+ } finally {
205
+ h.value = null;
206
+ }
207
+ }
208
+ async function q(a) {
209
+ h.value = a.pullRequestNumber, s.value = "";
210
+ try {
211
+ await F(C.rejectPendingTemplateFork(a.pullRequestNumber), { method: "POST" }), await v();
212
+ } catch (l) {
213
+ s.value = P(l);
214
+ } finally {
215
+ h.value = null;
216
+ }
217
+ }
218
+ function y(a) {
219
+ _.open({
220
+ title: `Merge ${a.newAppTemplateId}?`,
221
+ message: "Merges the pull request into main as-is, without a code review step here. The new template takes effect on the next control-plane deploy.",
222
+ primaryActions: { text: "Merge", close: !0, variant: "primary" },
223
+ secondaryActions: { text: "Cancel", close: !0, variant: "tertiary" }
224
+ }).onPrimary(() => void x(a));
225
+ }
226
+ function n(a) {
227
+ _.open({
228
+ title: `Reject ${a.newAppTemplateId}?`,
229
+ message: "Closes the pull request without merging and deletes its branch. Nothing of this template is kept.",
230
+ primaryActions: { text: "Reject", close: !0, variant: "destructive" },
231
+ secondaryActions: { text: "Cancel", close: !0, variant: "tertiary" }
232
+ }).onPrimary(() => void q(a));
233
+ }
234
+ M(() => void v());
235
+ async function k(a) {
236
+ if (!m.value) {
237
+ m.value = a, p.value = "";
238
+ try {
239
+ const l = await F(
240
+ C.appTemplateEditingProject(a),
241
+ { method: "POST" }
242
+ );
243
+ await V.push({
244
+ name: "miniprogram-v2-project",
245
+ params: { projectId: l.projectId, view: "workspace" },
246
+ query: { tpl: "1" }
247
+ });
248
+ } catch (l) {
249
+ p.value = P(l);
250
+ } finally {
251
+ m.value = null;
252
+ }
253
+ }
254
+ }
255
+ return (a, l) => {
256
+ const b = T("FmButton");
257
+ return o(), r("div", Q, [
258
+ t("div", X, [
259
+ t("header", Y, [
260
+ l[1] || (l[1] = t("div", null, [
261
+ t("p", { class: "portal-eyebrow" }, "Internal"),
262
+ t("h1", null, "Template library")
263
+ ], -1)),
264
+ t("div", Z, [
265
+ d(b, {
266
+ label: "Create template",
267
+ variant: "primary",
268
+ onClick: l[0] || (l[0] = (e) => A())
269
+ })
270
+ ])
271
+ ]),
272
+ p.value ? (o(), r("p", ee, u(p.value), 1)) : f("", !0),
273
+ s.value || g.value.length > 0 ? (o(), r("section", te, [
274
+ t("div", ae, [
275
+ l[2] || (l[2] = t("h2", { class: "template-section-title" }, "In review", -1)),
276
+ d(b, {
277
+ label: "Refresh",
278
+ variant: "tertiary",
279
+ size: "md",
280
+ loading: c.value,
281
+ onClick: v
282
+ }, null, 8, ["loading"])
283
+ ]),
284
+ l[3] || (l[3] = t("p", { class: "template-section-note" }, " Waiting on PR review and merge. A row disappears on its own once its pull request merges or is closed — click Refresh to check. ", -1)),
285
+ s.value ? (o(), r("p", le, [
286
+ w(u(s.value) + " ", 1),
287
+ d(b, {
288
+ label: "Retry",
289
+ variant: "tertiary",
290
+ onClick: v
291
+ })
292
+ ])) : f("", !0),
293
+ g.value.length > 0 ? (o(), r("section", ne, [
294
+ (o(!0), r(R, null, E(g.value, (e) => (o(), r("article", {
295
+ key: e.newAppTemplateId,
296
+ class: "template-choices__row"
297
+ }, [
298
+ t("div", oe, [
299
+ t("span", se, u(e.newAppTemplateId), 1),
300
+ t("span", re, "Awaiting review — PR #" + u(e.pullRequestNumber), 1)
301
+ ]),
302
+ t("div", ie, [
303
+ t("a", {
304
+ class: "template-review-link",
305
+ href: e.pullRequestUrl,
306
+ target: "_blank",
307
+ rel: "noopener"
308
+ }, "Review PR", 8, ce),
309
+ d(b, {
310
+ label: "Merge",
311
+ variant: "primary",
312
+ loading: h.value === e.pullRequestNumber,
313
+ disabled: h.value !== null,
314
+ onClick: (I) => y(e)
315
+ }, null, 8, ["loading", "disabled", "onClick"]),
316
+ d(b, {
317
+ label: "Reject",
318
+ variant: "destructive",
319
+ disabled: h.value !== null,
320
+ onClick: (I) => n(e)
321
+ }, null, 8, ["disabled", "onClick"])
322
+ ])
323
+ ]))), 128))
324
+ ])) : f("", !0)
325
+ ])) : f("", !0),
326
+ l[4] || (l[4] = t("h2", { class: "template-section-title" }, "Physical templates", -1)),
327
+ l[5] || (l[5] = t("p", { class: "template-section-note" }, ' "Edit code" opens the physical template directly — the same chat + live preview a merchant project gets, saving straight to a pull request against this repo instead of a merchant repo. ', -1)),
328
+ t("section", ue, [
329
+ (o(!0), r(R, null, E(B(z), (e) => (o(), r("article", {
330
+ key: e.id,
331
+ class: "template-choices__row"
332
+ }, [
333
+ t("div", de, [
334
+ t("span", pe, [
335
+ w(u(e.label), 1),
336
+ e.default ? (o(), r("span", me, " · Default")) : f("", !0)
337
+ ]),
338
+ t("span", ve, u(e.id), 1),
339
+ t("span", he, [
340
+ e.restaurantStyle ? (o(), r(R, { key: 0 }, [
341
+ w(u(e.restaurantStyle) + " · ", 1)
342
+ ], 64)) : f("", !0),
343
+ w(u(e.industries.join(", ") || "General-purpose") + " · " + u(e.environments.join(", ")), 1)
344
+ ])
345
+ ]),
346
+ t("div", ge, [
347
+ d(b, {
348
+ label: "Edit code",
349
+ variant: "secondary",
350
+ loading: m.value === e.id,
351
+ disabled: m.value !== null,
352
+ onClick: (I) => k(e.id)
353
+ }, null, 8, ["loading", "disabled", "onClick"])
354
+ ])
355
+ ]))), 128))
356
+ ])
357
+ ])
358
+ ]);
359
+ };
360
+ }
361
+ }), Ce = /* @__PURE__ */ S(_e, [["__scopeId", "data-v-a2c82260"]]);
362
+ export {
363
+ Ce as default
364
+ };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as s, watchEffect as a, openBlock as n, createElementBlock as p } from "vue";
2
2
  import { useRoute as u, useRouter as i } from "vue-router";
3
- import { u as l } from "./portalContext-CTVzkJV7.js";
3
+ import { u as l } from "./portalContext-BFTX5VVx.js";
4
4
  import { w as m, a as f } from "./portalNavigation-DKCfwTH8.js";
5
5
  const _ = {
6
6
  class: "portal-loading",