@useinsider/guido 3.2.0-beta.51b7991 → 3.2.0-beta.556da4b
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/README.md +25 -1
- package/dist/@types/config/schemas.js +38 -36
- package/dist/components/Guido.vue.js +4 -4
- package/dist/components/Guido.vue2.js +35 -34
- package/dist/components/organisms/AutoSaveController.vue.js +17 -0
- package/dist/components/organisms/AutoSaveController.vue2.js +13 -0
- package/dist/components/organisms/header/AutoSaveToggle.vue.js +22 -0
- package/dist/components/organisms/header/AutoSaveToggle.vue2.js +19 -0
- package/dist/components/organisms/header/RightSlot.vue.js +8 -8
- package/dist/components/organisms/header/RightSlot.vue2.js +9 -8
- package/dist/composables/useAutoSave.js +71 -0
- package/dist/composables/useSave.js +16 -16
- package/dist/extensions/Blocks/Recommendation/block.js +28 -35
- package/dist/extensions/Blocks/Recommendation/services/configService.js +4 -11
- package/dist/guido.css +1 -1
- package/dist/src/@types/config/schemas.d.ts +4 -0
- package/dist/src/components/Guido.vue.d.ts +1 -1
- package/dist/src/components/organisms/AutoSaveController.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/AutoSaveToggle.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
- package/dist/src/composables/useAutoSave.d.ts +3 -0
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useSave.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +3 -11
- package/dist/src/stores/autosave.d.ts +12 -0
- package/dist/src/stores/config.d.ts +18 -0
- package/dist/src/stores/editor.d.ts +23 -0
- package/dist/src/utils/timeUtil.d.ts +8 -0
- package/dist/stores/autosave.js +17 -0
- package/dist/stores/editor.js +3 -1
- package/dist/utils/timeUtil.js +19 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,7 +143,8 @@ const config: GuidoConfigInput = {
|
|
|
143
143
|
displayConditions?: boolean, // Default: true
|
|
144
144
|
unsubscribe?: boolean, // Default: true
|
|
145
145
|
modulesDisabled?: boolean, // Default: false - Disable modules panel
|
|
146
|
-
liquidSyntax?: boolean,
|
|
146
|
+
liquidSyntax?: boolean, // Default: false - Enable Liquid template syntax
|
|
147
|
+
autosave?: boolean, // Default: false - Show the Auto Save toggle in the header. See wiki/AUTOSAVE.md.
|
|
147
148
|
},
|
|
148
149
|
|
|
149
150
|
// Optional: Callbacks
|
|
@@ -202,6 +203,7 @@ interface SavedTemplateDetails {
|
|
|
202
203
|
config: number[];
|
|
203
204
|
};
|
|
204
205
|
metadata: Metadata;
|
|
206
|
+
silent: boolean; // true when triggered by autosave, false when user clicked Save
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
interface Metadata {
|
|
@@ -327,6 +329,28 @@ const config: GuidoConfigInput = {
|
|
|
327
329
|
|
|
328
330
|
---
|
|
329
331
|
|
|
332
|
+
## Autosave
|
|
333
|
+
|
|
334
|
+
Guido ships an opt-in **autosave** that saves on a 3-minute interval and when the user leaves the tab. Enable it with the `features.autosave` feature flag — this **shows an "Auto Save" toggle in the editor header**; the end user switches autosave on per session.
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
const config: GuidoConfigInput = {
|
|
338
|
+
identity: { templateId: 'tpl-123', userId: 'user-456' },
|
|
339
|
+
partner: { name: 'partner' },
|
|
340
|
+
features: {
|
|
341
|
+
autosave: true, // Default: false — shows the Auto Save toggle in the header
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
- Default is `false` — integrations see no change unless they opt in.
|
|
347
|
+
- Autosave reuses the same save pipeline as the Save button, so your existing `@save:complete` handler receives autosave output identically to a manual save. No new events or callbacks.
|
|
348
|
+
- Toggle state is **session-only** (Pinia) — resets to OFF on reload.
|
|
349
|
+
|
|
350
|
+
For a deep dive on triggers, guards, and limitations, see **[wiki/AUTOSAVE.md](wiki/AUTOSAVE.md)**.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
330
354
|
## HTML Compiler Rules
|
|
331
355
|
|
|
332
356
|
Add custom rules to transform HTML during export:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ModuleFolderDefaults as b } from "../../enums/defaults.js";
|
|
2
|
-
import { object as
|
|
2
|
+
import { object as a, number as p, optional as e, string as t, pipe as u, picklist as n, minLength as d, custom as S, boolean as o, array as c, literal as l, variant as k } from "../../node_modules/valibot/dist/index.js";
|
|
3
3
|
const m = {
|
|
4
4
|
/** Promotional/marketing emails */
|
|
5
5
|
PROMOTIONAL: 1,
|
|
@@ -12,7 +12,7 @@ const m = {
|
|
|
12
12
|
ARCHITECT: 49,
|
|
13
13
|
/** Unsubscribe page builder */
|
|
14
14
|
UNSUBSCRIBE_PAGES: 97
|
|
15
|
-
}, h =
|
|
15
|
+
}, h = a({
|
|
16
16
|
/** Unique identifier for the template being edited */
|
|
17
17
|
templateId: u(
|
|
18
18
|
t(),
|
|
@@ -25,12 +25,12 @@ const m = {
|
|
|
25
25
|
),
|
|
26
26
|
/** Optional variation ID for A/B testing */
|
|
27
27
|
variationId: e(t())
|
|
28
|
-
}),
|
|
28
|
+
}), f = a({
|
|
29
29
|
/** Fallback font name (e.g., "Georgia") */
|
|
30
30
|
name: t(),
|
|
31
31
|
/** Fallback font family (e.g., "serif" or "sans-serif") */
|
|
32
32
|
family: t()
|
|
33
|
-
}),
|
|
33
|
+
}), y = a({
|
|
34
34
|
/** Partner/organization name (required) */
|
|
35
35
|
name: u(
|
|
36
36
|
t(),
|
|
@@ -53,8 +53,8 @@ const m = {
|
|
|
53
53
|
/** Display name for the current user */
|
|
54
54
|
username: e(t(), "Guido User"),
|
|
55
55
|
/** Fallback font settings from partner settings — used to match backend size calculation */
|
|
56
|
-
fallbackFont: e(
|
|
57
|
-
}), A =
|
|
56
|
+
fallbackFont: e(f)
|
|
57
|
+
}), A = a({
|
|
58
58
|
/** Display text for the dynamic content */
|
|
59
59
|
text: t(),
|
|
60
60
|
/** Template variable value (e.g., {{username}}) */
|
|
@@ -63,12 +63,12 @@ const m = {
|
|
|
63
63
|
fallback: e(t()),
|
|
64
64
|
/** Optional formatting options */
|
|
65
65
|
format: e(
|
|
66
|
-
|
|
66
|
+
a({
|
|
67
67
|
key: t(),
|
|
68
68
|
value: t()
|
|
69
69
|
})
|
|
70
70
|
)
|
|
71
|
-
}), R =
|
|
71
|
+
}), R = a({
|
|
72
72
|
/** Initial HTML content */
|
|
73
73
|
html: e(t(), ""),
|
|
74
74
|
/** Initial CSS content */
|
|
@@ -83,13 +83,13 @@ const m = {
|
|
|
83
83
|
/** Selected unsubscribe page IDs */
|
|
84
84
|
selectedUnsubscribePages: e(c(p()), []),
|
|
85
85
|
/** Force recreate template in Stripo storage (use true when updating externally modified templates) */
|
|
86
|
-
forceRecreate: e(
|
|
87
|
-
}), C =
|
|
86
|
+
forceRecreate: e(o(), !1)
|
|
87
|
+
}), C = a({
|
|
88
88
|
/** Sender display name */
|
|
89
89
|
senderName: e(t(), ""),
|
|
90
90
|
/** Email subject line */
|
|
91
91
|
subject: e(t(), "")
|
|
92
|
-
}), T =
|
|
92
|
+
}), T = a({
|
|
93
93
|
/** Locale for the editor UI */
|
|
94
94
|
locale: e(t(), "en"),
|
|
95
95
|
/** Path to translations object */
|
|
@@ -102,28 +102,30 @@ const m = {
|
|
|
102
102
|
savedModulesFolderName: e(t(), b.SAVED_MODULES),
|
|
103
103
|
/** Folder name for default/prebuilt modules (used by Stripo plugin panel for path construction) */
|
|
104
104
|
defaultModulesFolderName: e(t(), b.DEFAULT_MODULES)
|
|
105
|
-
}), I =
|
|
105
|
+
}), I = a({
|
|
106
106
|
/** Whether to show the header bar */
|
|
107
|
-
showHeader: e(
|
|
107
|
+
showHeader: e(o(), !0),
|
|
108
108
|
/** Custom label for back button (if shown) */
|
|
109
109
|
backButtonLabel: e(t())
|
|
110
|
-
}), E =
|
|
110
|
+
}), E = a({
|
|
111
111
|
/** Enable dynamic content insertion */
|
|
112
|
-
dynamicContent: e(
|
|
112
|
+
dynamicContent: e(o(), !0),
|
|
113
113
|
/** Enable save as template functionality */
|
|
114
|
-
saveAsTemplate: e(
|
|
114
|
+
saveAsTemplate: e(o(), !0),
|
|
115
115
|
/** Enable version history */
|
|
116
|
-
versionHistory: e(
|
|
116
|
+
versionHistory: e(o(), !0),
|
|
117
117
|
/** Enable test message sending */
|
|
118
|
-
testMessage: e(
|
|
118
|
+
testMessage: e(o(), !0),
|
|
119
119
|
/** Enable display conditions */
|
|
120
|
-
displayConditions: e(
|
|
120
|
+
displayConditions: e(o(), !0),
|
|
121
121
|
/** Enable unsubscribe block */
|
|
122
|
-
unsubscribe: e(
|
|
122
|
+
unsubscribe: e(o(), !0),
|
|
123
123
|
/** Disable modules panel in the editor */
|
|
124
|
-
modulesDisabled: e(
|
|
124
|
+
modulesDisabled: e(o(), !1),
|
|
125
125
|
/** Enable Liquid template syntax */
|
|
126
|
-
liquidSyntax: e(
|
|
126
|
+
liquidSyntax: e(o(), !1),
|
|
127
|
+
/** Enable autosave (3-min interval + tab-hide). User toggles on/off from the header. */
|
|
128
|
+
autosave: e(o(), !1)
|
|
127
129
|
}), g = n([
|
|
128
130
|
"amp-accordion",
|
|
129
131
|
"amp-carousel",
|
|
@@ -146,7 +148,7 @@ const m = {
|
|
|
146
148
|
"unsubscribe-block",
|
|
147
149
|
"coupon-block",
|
|
148
150
|
"items-block"
|
|
149
|
-
]), L =
|
|
151
|
+
]), L = a({
|
|
150
152
|
/** Default blocks to exclude from the editor */
|
|
151
153
|
excludeDefaults: e(
|
|
152
154
|
c(g),
|
|
@@ -157,14 +159,14 @@ const m = {
|
|
|
157
159
|
c(O),
|
|
158
160
|
[]
|
|
159
161
|
)
|
|
160
|
-
}), r =
|
|
162
|
+
}), r = a({
|
|
161
163
|
/** Unique identifier for the rule */
|
|
162
164
|
id: t(),
|
|
163
165
|
/** Human-readable description */
|
|
164
166
|
description: e(t()),
|
|
165
167
|
/** Priority for rule ordering (lower = earlier) */
|
|
166
168
|
priority: p()
|
|
167
|
-
}), M =
|
|
169
|
+
}), M = a({
|
|
168
170
|
...r.entries,
|
|
169
171
|
type: l("replace"),
|
|
170
172
|
/** String to search for */
|
|
@@ -172,8 +174,8 @@ const m = {
|
|
|
172
174
|
/** Replacement string */
|
|
173
175
|
replacement: t(),
|
|
174
176
|
/** Replace all occurrences (default: false) */
|
|
175
|
-
replaceAll: e(
|
|
176
|
-
}), N =
|
|
177
|
+
replaceAll: e(o())
|
|
178
|
+
}), N = a({
|
|
177
179
|
...r.entries,
|
|
178
180
|
type: l("regex"),
|
|
179
181
|
/** Regex pattern string */
|
|
@@ -182,12 +184,12 @@ const m = {
|
|
|
182
184
|
replacement: t(),
|
|
183
185
|
/** Regex flags (e.g., 'gi') */
|
|
184
186
|
flags: e(t())
|
|
185
|
-
}), D =
|
|
187
|
+
}), D = a({
|
|
186
188
|
...r.entries,
|
|
187
189
|
type: l("remove"),
|
|
188
190
|
/** Strings or patterns to remove */
|
|
189
191
|
targets: c(t())
|
|
190
|
-
}), v =
|
|
192
|
+
}), v = a({
|
|
191
193
|
...r.entries,
|
|
192
194
|
type: l("custom"),
|
|
193
195
|
/** Custom processor function */
|
|
@@ -200,12 +202,12 @@ const m = {
|
|
|
200
202
|
N,
|
|
201
203
|
D,
|
|
202
204
|
v
|
|
203
|
-
]), U =
|
|
205
|
+
]), U = a({
|
|
204
206
|
/** Custom compiler rules to apply */
|
|
205
207
|
customRules: e(c(x), []),
|
|
206
208
|
/** Skip default compiler rules */
|
|
207
|
-
ignoreDefaultRules: e(
|
|
208
|
-
}), B =
|
|
209
|
+
ignoreDefaultRules: e(o(), !1)
|
|
210
|
+
}), B = a({
|
|
209
211
|
/**
|
|
210
212
|
* External validation handler called before save completes.
|
|
211
213
|
* Return false to cancel the save operation.
|
|
@@ -216,12 +218,12 @@ const m = {
|
|
|
216
218
|
"externalValidation must be a function"
|
|
217
219
|
)
|
|
218
220
|
)
|
|
219
|
-
}), H =
|
|
221
|
+
}), H = a({
|
|
220
222
|
// Required sections
|
|
221
223
|
/** Identity configuration (required) */
|
|
222
224
|
identity: h,
|
|
223
225
|
/** Partner configuration (required) */
|
|
224
|
-
partner:
|
|
226
|
+
partner: y,
|
|
225
227
|
// Optional sections (with defaults)
|
|
226
228
|
/** Template content and presets */
|
|
227
229
|
template: e(R, {}),
|
|
@@ -249,12 +251,12 @@ export {
|
|
|
249
251
|
A as DynamicContentSchema,
|
|
250
252
|
T as EditorSchema,
|
|
251
253
|
C as EmailHeaderSchema,
|
|
252
|
-
|
|
254
|
+
f as FallbackFontSchema,
|
|
253
255
|
E as FeaturesSchema,
|
|
254
256
|
H as GuidoConfigSchema,
|
|
255
257
|
h as IdentitySchema,
|
|
256
258
|
m as MessageType,
|
|
257
|
-
|
|
259
|
+
y as PartnerSchema,
|
|
258
260
|
s as ProductType,
|
|
259
261
|
N as RegexRuleSchema,
|
|
260
262
|
D as RemoveRuleSchema,
|
|
@@ -3,7 +3,7 @@ import i from "./Guido.vue2.js";
|
|
|
3
3
|
import a from "../_virtual/_plugin-vue2_normalizer.js";
|
|
4
4
|
var t = function() {
|
|
5
5
|
var o = this, r = o._self._c, e = o._self._setupProxy;
|
|
6
|
-
return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : o._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.FilterSelectionDrawer), r(e.SaveAsTemplateDrawer), e.isTestPartner() ? o._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(p) {
|
|
6
|
+
return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), r(e.AutoSaveController), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : o._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.FilterSelectionDrawer), r(e.SaveAsTemplateDrawer), e.isTestPartner() ? o._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(p) {
|
|
7
7
|
return e.emit("onboarding:finished");
|
|
8
8
|
} } }), r(e.UnsubscribeWrapper), r(e.LoadingWrapper)], 1);
|
|
9
9
|
}, n = [], s = /* @__PURE__ */ a(
|
|
@@ -12,9 +12,9 @@ var t = function() {
|
|
|
12
12
|
n,
|
|
13
13
|
!1,
|
|
14
14
|
null,
|
|
15
|
-
"
|
|
15
|
+
"fffc13d6"
|
|
16
16
|
);
|
|
17
|
-
const
|
|
17
|
+
const l = s.exports;
|
|
18
18
|
export {
|
|
19
|
-
|
|
19
|
+
l as default
|
|
20
20
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent as j, defineAsyncComponent as
|
|
1
|
+
import { defineComponent as j, defineAsyncComponent as N, ref as R, computed as I, watch as J, onMounted as Q, onUnmounted as X } from "vue";
|
|
2
2
|
import { provideGuidoActions as Y } from "../composables/useGuidoActions.js";
|
|
3
3
|
import { usePartner as Z } from "../composables/usePartner.js";
|
|
4
4
|
import { useStripo as ee } from "../composables/useStripo.js";
|
|
@@ -6,42 +6,43 @@ import { useTimerClone as te } from "../composables/useTimerClone.js";
|
|
|
6
6
|
import { migrate as W } from "../config/migrator/index.js";
|
|
7
7
|
import { ModuleFolderDefaults as B } from "../enums/defaults.js";
|
|
8
8
|
import { RIBBON_SELECTOR as oe } from "../enums/onboarding.js";
|
|
9
|
-
import ne from "./organisms/
|
|
9
|
+
import ne from "./organisms/AutoSaveController.vue.js";
|
|
10
|
+
import re from "./organisms/base/Toaster.vue.js";
|
|
10
11
|
import se from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import { useStripoApi as
|
|
16
|
-
import { useConfigStore as
|
|
17
|
-
import { useDynamicContentStore as
|
|
18
|
-
import { useEditorStore as
|
|
19
|
-
import { usePreviewStore as
|
|
20
|
-
import { useUnsubscribeStore as
|
|
21
|
-
const
|
|
12
|
+
import ce from "./organisms/header/HeaderWrapper.vue.js";
|
|
13
|
+
import ae from "./organisms/LoadingWrapper.vue.js";
|
|
14
|
+
import ie from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
|
|
15
|
+
import me from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
|
|
16
|
+
import { useStripoApi as de } from "../services/stripoApi.js";
|
|
17
|
+
import { useConfigStore as le } from "../stores/config.js";
|
|
18
|
+
import { useDynamicContentStore as ue } from "../stores/dynamic-content.js";
|
|
19
|
+
import { useEditorStore as pe } from "../stores/editor.js";
|
|
20
|
+
import { usePreviewStore as fe } from "../stores/preview.js";
|
|
21
|
+
import { useUnsubscribeStore as ve } from "../stores/unsubscribe.js";
|
|
22
|
+
const Ie = /* @__PURE__ */ j({
|
|
22
23
|
__name: "Guido",
|
|
23
24
|
props: {
|
|
24
25
|
config: null
|
|
25
26
|
},
|
|
26
27
|
emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
|
|
27
|
-
setup(H, { expose: x, emit:
|
|
28
|
-
const
|
|
28
|
+
setup(H, { expose: x, emit: r }) {
|
|
29
|
+
const S = H, G = N(
|
|
29
30
|
() => import("./organisms/email-preview/PreviewContainer.vue.js")
|
|
30
|
-
), z =
|
|
31
|
+
), z = N(
|
|
31
32
|
() => import("./organisms/onboarding/OnboardingWrapper.vue.js")
|
|
32
|
-
),
|
|
33
|
-
a.init(
|
|
34
|
-
const u =
|
|
33
|
+
), b = R(), d = R(), l = ue(), g = ve(), a = le();
|
|
34
|
+
a.init(S.config);
|
|
35
|
+
const u = pe(), q = fe(), i = I(() => u.hasChanges), { isTestPartner: K } = Z(), w = () => {
|
|
35
36
|
var e;
|
|
36
|
-
return (e =
|
|
37
|
+
return (e = b.value) == null ? void 0 : e.handleSave(!0);
|
|
37
38
|
}, {
|
|
38
39
|
templateId: p,
|
|
39
40
|
userId: E,
|
|
40
41
|
partnerName: D,
|
|
41
42
|
username: C,
|
|
42
43
|
template: t,
|
|
43
|
-
editor:
|
|
44
|
-
} = a, m = (t == null ? void 0 : t.html) || "", T = (t == null ? void 0 : t.css) || "", f = (t == null ? void 0 : t.preselectedDynamicContent) || [], k = (
|
|
44
|
+
editor: s
|
|
45
|
+
} = a, m = (t == null ? void 0 : t.html) || "", T = (t == null ? void 0 : t.css) || "", f = (t == null ? void 0 : t.preselectedDynamicContent) || [], k = (s == null ? void 0 : s.savedModulesFolderName) || B.SAVED_MODULES, F = (s == null ? void 0 : s.defaultModulesFolderName) || B.DEFAULT_MODULES;
|
|
45
46
|
u.templateId = p;
|
|
46
47
|
const v = {
|
|
47
48
|
emailId: p,
|
|
@@ -53,38 +54,38 @@ const Re = /* @__PURE__ */ j({
|
|
|
53
54
|
}, L = {
|
|
54
55
|
preselectedDynamicContentList: f,
|
|
55
56
|
onReady: () => {
|
|
56
|
-
console.debug("guido:ready"),
|
|
57
|
+
console.debug("guido:ready"), r("ready");
|
|
57
58
|
}
|
|
58
|
-
}, { initPlugin: U } = ee(v, L), { getDefaultTemplate: _ } =
|
|
59
|
+
}, { initPlugin: U } = ee(v, L), { getDefaultTemplate: _ } = de(), { cloneTimersOnSave: M, hasTimerBlocks: O } = te(), V = I(() => {
|
|
59
60
|
var e;
|
|
60
61
|
return !((e = a.ui) != null && e.showHeader);
|
|
61
62
|
});
|
|
62
63
|
Y({
|
|
63
64
|
onBack: () => {
|
|
64
|
-
console.debug("guido:back"),
|
|
65
|
+
console.debug("guido:back"), r("back");
|
|
65
66
|
},
|
|
66
67
|
onSaveStart: () => {
|
|
67
|
-
console.debug("guido:save:start"),
|
|
68
|
+
console.debug("guido:save:start"), r("save:start");
|
|
68
69
|
},
|
|
69
70
|
onSaveComplete: (e) => {
|
|
70
71
|
const n = { ...e, metadata: v };
|
|
71
|
-
console.debug("guido:save:complete", n),
|
|
72
|
+
console.debug("guido:save:complete", n), r("save:complete", n);
|
|
72
73
|
},
|
|
73
74
|
onTestEmailClick: () => {
|
|
74
|
-
console.debug("guido:test-email:click"),
|
|
75
|
+
console.debug("guido:test-email:click"), r("test-email:click");
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
78
|
const P = (e) => {
|
|
78
79
|
console.debug("dynamic-content:close", e), l.setSelectedDynamicContent(e), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: e }));
|
|
79
|
-
},
|
|
80
|
+
}, A = () => {
|
|
80
81
|
console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
|
|
81
82
|
};
|
|
82
83
|
J(() => i.value, () => {
|
|
83
|
-
|
|
84
|
+
r("on-change", i.value);
|
|
84
85
|
});
|
|
85
86
|
const y = (e) => {
|
|
86
87
|
const n = e, { attribute: o, position: $ } = n.detail;
|
|
87
|
-
console.debug("dynamic-content:open", n.detail),
|
|
88
|
+
console.debug("dynamic-content:open", n.detail), r("dynamic-content:open", o, $);
|
|
88
89
|
};
|
|
89
90
|
let c = null;
|
|
90
91
|
const h = () => {
|
|
@@ -119,13 +120,13 @@ const Re = /* @__PURE__ */ j({
|
|
|
119
120
|
}), x({
|
|
120
121
|
dynamicContent: {
|
|
121
122
|
insert: P,
|
|
122
|
-
close:
|
|
123
|
+
close: A
|
|
123
124
|
},
|
|
124
125
|
hasChanges: i,
|
|
125
126
|
saveSilent: w
|
|
126
|
-
}), { __sfc: !0, PreviewContainer: G, OnboardingWrapper: z, headerWrapperRef:
|
|
127
|
+
}), { __sfc: !0, PreviewContainer: G, OnboardingWrapper: z, headerWrapperRef: b, wrapperRef: d, dynamicContentStore: l, unsubscribeStore: g, props: S, configStore: a, editorStore: u, previewStore: q, hasChanges: i, isTestPartner: K, saveSilent: w, templateId: p, userId: E, partnerName: D, username: C, templateConfig: t, editorConfig: s, html: m, css: T, preselectedDynamicContentList: f, savedModulesFolderName: k, defaultModulesFolderName: F, emit: r, metadata: v, options: L, initPlugin: U, getDefaultTemplate: _, cloneTimersOnSave: M, hasTimerBlocks: O, noHeader: V, insertDynamicContent: P, closeDynamicContent: A, handleDynamicContentOpen: y, ribbonObserver: c, updateRibbonOffset: h, AutoSaveController: ne, Toaster: re, FilterSelectionDrawer: se, HeaderWrapper: ce, LoadingWrapper: ae, SaveAsTemplateDrawer: ie, UnsubscribeWrapper: me };
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
export {
|
|
130
|
-
|
|
131
|
+
Ie as default
|
|
131
132
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import n from "./AutoSaveController.vue2.js";
|
|
2
|
+
import t from "../../_virtual/_plugin-vue2_normalizer.js";
|
|
3
|
+
var o = function() {
|
|
4
|
+
var r = this, e = r._self._c;
|
|
5
|
+
return r._self._setupProxy, e("div", { staticClass: "d-n" });
|
|
6
|
+
}, s = [], _ = /* @__PURE__ */ t(
|
|
7
|
+
n,
|
|
8
|
+
o,
|
|
9
|
+
s,
|
|
10
|
+
!1,
|
|
11
|
+
null,
|
|
12
|
+
null
|
|
13
|
+
);
|
|
14
|
+
const f = _.exports;
|
|
15
|
+
export {
|
|
16
|
+
f as default
|
|
17
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineComponent as t } from "vue";
|
|
2
|
+
import { useAutoSave as r } from "../../composables/useAutoSave.js";
|
|
3
|
+
import { useSave as s } from "../../composables/useSave.js";
|
|
4
|
+
const f = /* @__PURE__ */ t({
|
|
5
|
+
__name: "AutoSaveController",
|
|
6
|
+
setup(a) {
|
|
7
|
+
const { save: e } = s(), o = () => e(!1, !0);
|
|
8
|
+
return r(o), { __sfc: !0, save: e, backgroundSave: o };
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
export {
|
|
12
|
+
f as default
|
|
13
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import o from "./AutoSaveToggle.vue2.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import i from "../../../_virtual/_plugin-vue2_normalizer.js";
|
|
4
|
+
var n = function() {
|
|
5
|
+
var e = this, a = e._self._c, t = e._self._setupProxy;
|
|
6
|
+
return t.isFeatureEnabled("autosave") ? a("div", { staticClass: "d-f a-i-c mr-3 auto-save-toggle", on: { mouseenter: function(s) {
|
|
7
|
+
t.isHovered = !0;
|
|
8
|
+
}, mouseleave: function(s) {
|
|
9
|
+
t.isHovered = !1;
|
|
10
|
+
} } }, [a(t.InToggle, { attrs: { id: "guido__autosave-toggle", name: "guido-autosave-toggle", checked: t.autosaveStore.isOn, disable: t.editorStore.loadingStatus }, on: { click: t.toggle } }), a("span", { staticClass: "ml-2 auto-save-toggle__label t-c-55" }, [e._v(" " + e._s(t.trans("email-editor.auto-save")) + " ")]), t.autosaveStore.status === t.AUTOSAVE_STATUS.SAVING ? a("span", { staticClass: "ml-2 d-f a-i-c f-s-1" }, [a(t.InLoading, { attrs: { "color-class": "i-c-53", size: "16" } }), a("span", { staticClass: "ml-1 t-c-53" }, [e._v(" " + e._s(t.trans("newsletter.saving")) + " ")])], 1) : t.lastSavedLabel ? a("span", { staticClass: "ml-2 f-s-1 t-c-53" }, [e._v(" " + e._s(t.lastSavedLabel) + " ")]) : e._e(), t.isHovered ? a(t.InInfoBox, { staticClass: "auto-save-toggle__info-box", attrs: { id: "guido__autosave-info-box", size: "small", variant: "information", "description-text": t.trans("email-editor.auto-save-description"), "title-text": t.trans("email-editor.auto-save-title") } }) : e._e()], 1) : e._e();
|
|
11
|
+
}, l = [], r = /* @__PURE__ */ i(
|
|
12
|
+
o,
|
|
13
|
+
n,
|
|
14
|
+
l,
|
|
15
|
+
!1,
|
|
16
|
+
null,
|
|
17
|
+
"2c964af4"
|
|
18
|
+
);
|
|
19
|
+
const d = r.exports;
|
|
20
|
+
export {
|
|
21
|
+
d as default
|
|
22
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineComponent as i, ref as f, computed as u } from "vue";
|
|
2
|
+
import { useConfig as l } from "../../../composables/useConfig.js";
|
|
3
|
+
import { useTranslations as p } from "../../../composables/useTranslations.js";
|
|
4
|
+
import { useAutosaveStore as c, AUTOSAVE_STATUS as t } from "../../../stores/autosave.js";
|
|
5
|
+
import { useEditorStore as S } from "../../../stores/editor.js";
|
|
6
|
+
import { formatLocalTime as d } from "../../../utils/timeUtil.js";
|
|
7
|
+
import { InToggle as g, InLoading as _, InInfoBox as A } from "@useinsider/design-system-vue";
|
|
8
|
+
const U = /* @__PURE__ */ i({
|
|
9
|
+
__name: "AutoSaveToggle",
|
|
10
|
+
setup(v) {
|
|
11
|
+
const { isFeatureEnabled: e } = l(), r = S(), o = c(), s = p(), n = f(!1), a = u(() => o.status !== t.SAVED || !o.lastSavedAt ? "" : d(o.lastSavedAt));
|
|
12
|
+
return { __sfc: !0, isFeatureEnabled: e, editorStore: r, autosaveStore: o, trans: s, isHovered: n, lastSavedLabel: a, toggle: (m) => {
|
|
13
|
+
o.isOn = m;
|
|
14
|
+
}, AUTOSAVE_STATUS: t, InInfoBox: A, InLoading: _, InToggle: g };
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
export {
|
|
18
|
+
U as default
|
|
19
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
return e("div", { staticClass: "d-f a-i-c" }, [t.isLiquidEnabled && !t.editorStore.isVersionHistoryOpen ? e(t.InChips, { staticClass: "mr-
|
|
6
|
-
}, a = [], n = /* @__PURE__ */
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import s from "./RightSlot.vue2.js";
|
|
2
|
+
import o from "../../../_virtual/_plugin-vue2_normalizer.js";
|
|
3
|
+
var r = function() {
|
|
4
|
+
var i = this, e = i._self._c, t = i._self._setupProxy;
|
|
5
|
+
return e("div", { staticClass: "d-f a-i-c" }, [t.editorStore.isVersionHistoryOpen ? i._e() : e(t.AutoSaveToggle), t.isLiquidEnabled && !t.editorStore.isVersionHistoryOpen ? e(t.InChips, { staticClass: "mr-1", attrs: { id: "guido__liquid-tag-chip", styles: "stroke", type: "default", value: "liquid-tags", "close-button": !1, "disabled-status": t.editorStore.loadingStatus, interactive: !1, text: t.trans("email-editor.liquid-tags-enabled") } }) : i._e(), t.editorStore.isVersionHistoryOpen ? e(t.RestoreButton) : e(t.EditorActions, { ref: "editorActionsRef" })], 1);
|
|
6
|
+
}, a = [], n = /* @__PURE__ */ o(
|
|
7
|
+
s,
|
|
8
|
+
r,
|
|
9
9
|
a,
|
|
10
10
|
!1,
|
|
11
11
|
null,
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { defineComponent as a, ref as f, computed as p } from "vue";
|
|
2
2
|
import { useConfig as u } from "../../../composables/useConfig.js";
|
|
3
3
|
import { useTranslations as d } from "../../../composables/useTranslations.js";
|
|
4
|
-
import { useEditorStore as
|
|
5
|
-
import { InChips as
|
|
6
|
-
import _ from "./
|
|
7
|
-
import S from "./
|
|
8
|
-
|
|
4
|
+
import { useEditorStore as l } from "../../../stores/editor.js";
|
|
5
|
+
import { InChips as c } from "@useinsider/design-system-vue";
|
|
6
|
+
import _ from "./AutoSaveToggle.vue.js";
|
|
7
|
+
import S from "./EditorActions.vue.js";
|
|
8
|
+
import g from "./version-history/RestoreButton.vue.js";
|
|
9
|
+
const T = /* @__PURE__ */ a({
|
|
9
10
|
__name: "RightSlot",
|
|
10
11
|
setup(h, { expose: r }) {
|
|
11
|
-
const { isFeatureEnabled: o } = u(),
|
|
12
|
+
const { isFeatureEnabled: o } = u(), i = d(), n = l(), t = f(null), s = p(() => o("liquidSyntax"));
|
|
12
13
|
return r({
|
|
13
14
|
handleSave: (m) => {
|
|
14
15
|
var e;
|
|
15
16
|
return (e = t.value) == null ? void 0 : e.handleSave(m);
|
|
16
17
|
}
|
|
17
|
-
}), { __sfc: !0, isFeatureEnabled: o, trans:
|
|
18
|
+
}), { __sfc: !0, isFeatureEnabled: o, trans: i, editorStore: n, editorActionsRef: t, isLiquidEnabled: s, InChips: c, AutoSaveToggle: _, EditorActions: S, RestoreButton: g };
|
|
18
19
|
}
|
|
19
20
|
});
|
|
20
21
|
export {
|
|
21
|
-
|
|
22
|
+
T as default
|
|
22
23
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useConfig as m } from "./useConfig.js";
|
|
2
|
+
import { useAutosaveStore as A, AUTOSAVE_STATUS as s } from "../stores/autosave.js";
|
|
3
|
+
import { useEditorStore as E } from "../stores/editor.js";
|
|
4
|
+
import { computed as f, watch as p, onUnmounted as y } from "vue";
|
|
5
|
+
const I = 18e4, r = 6e4, T = (b) => {
|
|
6
|
+
const { isFeatureEnabled: S } = m(), a = E(), t = A();
|
|
7
|
+
let i = null, c = 0;
|
|
8
|
+
const u = f(
|
|
9
|
+
() => S("autosave") && t.isOn
|
|
10
|
+
), g = () => a.hasChanges && a.isInSaveableState, h = () => ({
|
|
11
|
+
hasChanges: a.hasChanges,
|
|
12
|
+
isInSaveableState: a.isInSaveableState
|
|
13
|
+
}), l = async (e) => {
|
|
14
|
+
if (!u.value) {
|
|
15
|
+
console.debug("guido:autosave:skipped", { trigger: e, reason: "not-active" });
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!g()) {
|
|
19
|
+
console.debug("guido:autosave:skipped", { trigger: e, reason: "gates-blocked", gates: h() });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (t.status === s.SAVING) {
|
|
23
|
+
console.debug("guido:autosave:skipped", { trigger: e, reason: "already-saving" });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.debug("guido:autosave:save-start", { trigger: e }), t.status = s.SAVING;
|
|
27
|
+
try {
|
|
28
|
+
if (await b() === void 0) {
|
|
29
|
+
console.debug("guido:autosave:blocked", { trigger: e, reason: "save-returned-undefined" }), t.status = s.ERROR;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
a.hasChanges = !1, t.status = s.SAVED, t.lastSavedAt = /* @__PURE__ */ new Date(), console.debug("guido:autosave:save-complete", { trigger: e, at: t.lastSavedAt });
|
|
33
|
+
} catch (o) {
|
|
34
|
+
console.debug("guido:autosave:error", { trigger: e, error: o }), t.status = s.ERROR;
|
|
35
|
+
}
|
|
36
|
+
}, n = () => {
|
|
37
|
+
const { visibilityState: e } = document;
|
|
38
|
+
if (console.debug("guido:autosave:visibility-change", {
|
|
39
|
+
visibilityState: e,
|
|
40
|
+
isActive: u.value
|
|
41
|
+
}), e !== "hidden")
|
|
42
|
+
return;
|
|
43
|
+
const o = Date.now() - c;
|
|
44
|
+
if (o < r) {
|
|
45
|
+
console.debug("guido:autosave:visibility-debounced", {
|
|
46
|
+
sinceLastMs: o,
|
|
47
|
+
debounceMs: r
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
c = Date.now(), l("visibility");
|
|
52
|
+
}, d = () => {
|
|
53
|
+
i && (clearInterval(i), i = null);
|
|
54
|
+
}, v = () => {
|
|
55
|
+
document.removeEventListener("visibilitychange", n), window.removeEventListener("pagehide", n);
|
|
56
|
+
};
|
|
57
|
+
p(
|
|
58
|
+
u,
|
|
59
|
+
(e) => {
|
|
60
|
+
console.debug("guido:autosave:active-changed", { active: e }), e ? (d(), i = setInterval(() => {
|
|
61
|
+
console.debug("guido:autosave:interval-tick"), l("interval");
|
|
62
|
+
}, I), document.addEventListener("visibilitychange", n), window.addEventListener("pagehide", n)) : (d(), v(), t.status = s.IDLE);
|
|
63
|
+
},
|
|
64
|
+
{ immediate: !0 }
|
|
65
|
+
), y(() => {
|
|
66
|
+
d(), v(), t.status = s.IDLE, t.lastSavedAt = null;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
export {
|
|
70
|
+
T as useAutoSave
|
|
71
|
+
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { useActionsApi as
|
|
2
|
-
import { useConfig as
|
|
3
|
-
import { useSaveStart as
|
|
4
|
-
import { useSyncModuleExtractor as
|
|
5
|
-
import { useStripoApi as
|
|
6
|
-
import { useTemplatePreparation as
|
|
7
|
-
import { useHtmlValidator as
|
|
8
|
-
import { useCouponBlockValidator as
|
|
9
|
-
import { useLiquidValidator as
|
|
10
|
-
const
|
|
11
|
-
const o =
|
|
12
|
-
return { save: async (p = !1) => {
|
|
1
|
+
import { useActionsApi as x } from "./useActionsApi.js";
|
|
2
|
+
import { useConfig as y } from "./useConfig.js";
|
|
3
|
+
import { useSaveStart as w, useSaveComplete as C } from "./useGuidoActions.js";
|
|
4
|
+
import { useSyncModuleExtractor as H } from "./useSyncModuleExtractor.js";
|
|
5
|
+
import { useStripoApi as b } from "../services/stripoApi.js";
|
|
6
|
+
import { useTemplatePreparation as q } from "../utils/templatePreparation.js";
|
|
7
|
+
import { useHtmlValidator as L } from "./useHtmlValidator.js";
|
|
8
|
+
import { useCouponBlockValidator as P } from "./validators/useCouponBlockValidator.js";
|
|
9
|
+
import { useLiquidValidator as E } from "./validators/useLiquidValidator.js";
|
|
10
|
+
const j = () => {
|
|
11
|
+
const o = w(), s = C(), { validateHtml: r } = L(), { validateLiquidSyntax: l } = E(), { validateCouponBlockTags: n } = P(), { callbacks: a, isFeatureEnabled: d } = y(), { extractSyncModuleData: u } = H(), { setSyncModuleUnsubscriptionPages: c } = b(), { editorSave: m } = x();
|
|
12
|
+
return { save: async (p = !1, f = !1) => {
|
|
13
13
|
var i;
|
|
14
14
|
o();
|
|
15
|
-
const { prepareTemplateDetails:
|
|
15
|
+
const { prepareTemplateDetails: v } = q(), t = await v();
|
|
16
16
|
if (!n(t.compiledHtml))
|
|
17
17
|
return;
|
|
18
18
|
if (d("liquidSyntax")) {
|
|
@@ -23,10 +23,10 @@ const h = () => {
|
|
|
23
23
|
if ((i = a.value) != null && i.externalValidation && !await a.value.externalValidation(t))
|
|
24
24
|
return;
|
|
25
25
|
await m();
|
|
26
|
-
const { unsubscribePayload:
|
|
27
|
-
return await c(
|
|
26
|
+
const { unsubscribePayload: S, stripoModules: V } = u(t.rawHtml);
|
|
27
|
+
return await c(S), t.modules = V, p || s({ ...t, silent: f }), t;
|
|
28
28
|
} };
|
|
29
29
|
};
|
|
30
30
|
export {
|
|
31
|
-
|
|
31
|
+
j as useSave
|
|
32
32
|
};
|
|
@@ -8,8 +8,8 @@ import { regenerateMobileProductRows as C } from "./controls/main/utils.js";
|
|
|
8
8
|
import { ensureMobileCssRulesExist as g, setMobileLayoutOptOut as d, hasMobileLayoutOptOut as A } from "./controls/mobileLayout/cssRules.js";
|
|
9
9
|
import { RecommendationConfigService as c } from "./services/configService.js";
|
|
10
10
|
import { useRecommendationExtensionStore as p } from "./store/recommendation.js";
|
|
11
|
-
import { getDefaultTemplate as
|
|
12
|
-
const f = B.Recommendation,
|
|
11
|
+
import { getDefaultTemplate as E } from "./templates/grid/template.js";
|
|
12
|
+
const f = B.Recommendation, a = "recommendation-block-v2", l = "recommendation-id";
|
|
13
13
|
let h = !1;
|
|
14
14
|
class q extends b {
|
|
15
15
|
constructor() {
|
|
@@ -56,7 +56,7 @@ class q extends b {
|
|
|
56
56
|
*/
|
|
57
57
|
getTemplate() {
|
|
58
58
|
const t = this._generateNextId();
|
|
59
|
-
return this._pendingBlockId = t,
|
|
59
|
+
return this._pendingBlockId = t, E(t);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
62
|
* Called when a new block is dropped into the template
|
|
@@ -68,20 +68,13 @@ class q extends b {
|
|
|
68
68
|
onCreated(t) {
|
|
69
69
|
const e = this._pendingBlockId ?? this._generateNextId();
|
|
70
70
|
this._pendingBlockId = null, this._assignRecommendationId(t, e);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const a = this._getBlockElement(t);
|
|
79
|
-
a && (d(this.api, a, !0), C({
|
|
80
|
-
currentNode: t,
|
|
81
|
-
documentModifier: this.api.getDocumentModifier()
|
|
82
|
-
}));
|
|
83
|
-
}
|
|
84
|
-
s.patchCurrentBlockConfig({ language: i.language }, { triggerRefetch: !1 });
|
|
71
|
+
const o = c.initializeConfig(this.api, t, { recommendationId: e }), i = p();
|
|
72
|
+
i.setCurrentBlock(e), g(this.api);
|
|
73
|
+
const s = this._getBlockElement(t);
|
|
74
|
+
s && (d(this.api, s, !0), C({
|
|
75
|
+
currentNode: t,
|
|
76
|
+
documentModifier: this.api.getDocumentModifier()
|
|
77
|
+
})), i.patchCurrentBlockConfig({ language: o.language }, { triggerRefetch: !1 });
|
|
85
78
|
}
|
|
86
79
|
/**
|
|
87
80
|
* Called when the document changes or template is loaded
|
|
@@ -104,10 +97,10 @@ class q extends b {
|
|
|
104
97
|
c.needsMigration(t) && this._migrateFromLegacy(t);
|
|
105
98
|
try {
|
|
106
99
|
h || (g(this.api), h = !0);
|
|
107
|
-
const e = c.getConfig(t),
|
|
108
|
-
if (
|
|
109
|
-
const
|
|
110
|
-
A(
|
|
100
|
+
const e = c.getConfig(t), o = this._getBlockElement(t);
|
|
101
|
+
if (o) {
|
|
102
|
+
const i = !e.mobileLayoutEnabled;
|
|
103
|
+
A(o) !== i && d(this.api, o, i);
|
|
111
104
|
}
|
|
112
105
|
} catch {
|
|
113
106
|
}
|
|
@@ -131,10 +124,10 @@ class q extends b {
|
|
|
131
124
|
let t = 0;
|
|
132
125
|
try {
|
|
133
126
|
const e = this.api.getDocumentRoot();
|
|
134
|
-
e && "querySelectorAll" in e && e.querySelectorAll(`.${
|
|
135
|
-
if ("getAttribute" in
|
|
136
|
-
const s =
|
|
137
|
-
|
|
127
|
+
e && "querySelectorAll" in e && e.querySelectorAll(`.${a}`).forEach((i) => {
|
|
128
|
+
if ("getAttribute" in i) {
|
|
129
|
+
const s = i.getAttribute(l), m = s ? parseInt(s) : 0;
|
|
130
|
+
m > t && (t = m);
|
|
138
131
|
}
|
|
139
132
|
});
|
|
140
133
|
} catch {
|
|
@@ -148,11 +141,11 @@ class q extends b {
|
|
|
148
141
|
* added classes via setAttribute.
|
|
149
142
|
*/
|
|
150
143
|
_assignRecommendationId(t, e) {
|
|
151
|
-
const
|
|
152
|
-
if (!
|
|
144
|
+
const o = this._getBlockElement(t);
|
|
145
|
+
if (!o)
|
|
153
146
|
return;
|
|
154
|
-
const
|
|
155
|
-
|
|
147
|
+
const i = this.api.getDocumentModifier();
|
|
148
|
+
i.modifyHtml(o).setAttribute(l, e.toString()), i.apply(new y(`Assign recommendation ID ${e}`));
|
|
156
149
|
}
|
|
157
150
|
/**
|
|
158
151
|
* Gets the recommendation-id from a block node
|
|
@@ -161,11 +154,11 @@ class q extends b {
|
|
|
161
154
|
const e = this._getBlockElement(t);
|
|
162
155
|
if (!e || !("getAttribute" in e))
|
|
163
156
|
return null;
|
|
164
|
-
const
|
|
165
|
-
if (!
|
|
157
|
+
const o = e.getAttribute(l);
|
|
158
|
+
if (!o)
|
|
166
159
|
return null;
|
|
167
|
-
const
|
|
168
|
-
return Number.isNaN(
|
|
160
|
+
const i = parseInt(o);
|
|
161
|
+
return Number.isNaN(i) ? null : i;
|
|
169
162
|
}
|
|
170
163
|
/**
|
|
171
164
|
* Gets the block element (the element with BLOCK_CLASS)
|
|
@@ -173,10 +166,10 @@ class q extends b {
|
|
|
173
166
|
_getBlockElement(t) {
|
|
174
167
|
if ("getAttribute" in t) {
|
|
175
168
|
const e = t.getAttribute("class");
|
|
176
|
-
if (e && e.includes(
|
|
169
|
+
if (e && e.includes(a))
|
|
177
170
|
return t;
|
|
178
171
|
}
|
|
179
|
-
return "querySelector" in t ? t.querySelector(`.${
|
|
172
|
+
return "querySelector" in t ? t.querySelector(`.${a}`) ?? null : null;
|
|
180
173
|
}
|
|
181
174
|
/**
|
|
182
175
|
* Migrate configuration from legacy format
|
|
@@ -85,28 +85,21 @@ class C {
|
|
|
85
85
|
*
|
|
86
86
|
* Called when a block is first created (dropped into template).
|
|
87
87
|
* Can optionally merge in partial config from migration.
|
|
88
|
-
*
|
|
89
|
-
* The `wasFreshDrop` flag distinguishes a brand-new drop (no prior config)
|
|
90
|
-
* from a clone (Stripo replays the source's setNodeConfig payload before
|
|
91
|
-
* onCreated fires). Callers use this to skip side-effects already inherited
|
|
92
|
-
* from the source.
|
|
93
88
|
* @example
|
|
94
89
|
* // In Block.onCreated lifecycle
|
|
95
|
-
*
|
|
90
|
+
* RecommendationConfigService.initializeConfig(this.api, node);
|
|
96
91
|
* @param api - Stripo extension API with document modifier
|
|
97
92
|
* @param node - The immutable HTML node to initialize
|
|
98
93
|
* @param partialConfig - Optional partial config to merge with defaults
|
|
99
|
-
* @returns The initialized configuration
|
|
94
|
+
* @returns The initialized configuration
|
|
100
95
|
*/
|
|
101
96
|
static initializeConfig(i, t, o) {
|
|
102
|
-
if (this.hasConfig(t))
|
|
103
|
-
return { config: o ? this.updateConfig(i, t, o, "Initialize recommendation block") : this.getConfig(t), wasFreshDrop: !1 };
|
|
104
97
|
const n = o ? this.mergeWithDefaults(o) : this.cloneDefaults();
|
|
105
98
|
return this.saveConfig(i, t, n, "Initialize recommendation block"), g({
|
|
106
99
|
currentNode: t,
|
|
107
100
|
documentModifier: i.getDocumentModifier(),
|
|
108
101
|
currency: n.currency
|
|
109
|
-
}),
|
|
102
|
+
}), n;
|
|
110
103
|
}
|
|
111
104
|
/**
|
|
112
105
|
* Save complete configuration to a node
|
|
@@ -150,7 +143,7 @@ class C {
|
|
|
150
143
|
const c = t.getAttribute("data-row-spacing");
|
|
151
144
|
c && (o.rowSpacing = parseInt(c) || e.rowSpacing);
|
|
152
145
|
}
|
|
153
|
-
return this.initializeConfig(i, t, o)
|
|
146
|
+
return this.initializeConfig(i, t, o);
|
|
154
147
|
}
|
|
155
148
|
/**
|
|
156
149
|
* Check if configuration needs migration
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gap-16[data-v-3b53a736],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-cd76c125] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.editor-actions[data-v-4e2a4adb]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-
|
|
1
|
+
.gap-16[data-v-3b53a736],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-cd76c125] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-64c52560]{gap:8px}.version-history__toolbar[data-v-64c52560]{gap:4px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-4e2a4adb]{gap:4px}.header-wrapper[data-v-5c02dcc7]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-fffc13d6]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-fffc13d6]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-fffc13d6]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-df672485]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-df672485]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-df672485]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-df672485]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-df672485]{object-fit:cover;transform:scale(1)}[data-v-43c617a7] .guido__verion-history-view-option-selection-desktop svg,[data-v-43c617a7] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-43c617a7] .in-segments-wrapper__button_selected,[data-v-43c617a7] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-988f8da6]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-988f8da6]{min-height:504px}.iframe-wrapper[data-v-e0424e99]{width:258px}.iframe-scaled[data-v-e0424e99]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-7419ae06] .vueperslides__bullets,[data-v-796d193b] .vueperslides__bullets{pointer-events:none!important}[data-v-796d193b] .vueperslides__parallax-wrapper{height:110px!important}[data-v-cadfc82d] .vueperslides__bullets{pointer-events:none!important}[data-v-cadfc82d] .vueperslides__parallax-wrapper{height:110px!important}
|
|
@@ -178,6 +178,8 @@ export declare const FeaturesSchema: v.ObjectSchema<{
|
|
|
178
178
|
readonly modulesDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
179
179
|
/** Enable Liquid template syntax */
|
|
180
180
|
readonly liquidSyntax: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
181
|
+
/** Enable autosave (3-min interval + tab-hide). User toggles on/off from the header. */
|
|
182
|
+
readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
181
183
|
}, undefined>;
|
|
182
184
|
/**
|
|
183
185
|
* Default block types available in Stripo
|
|
@@ -501,6 +503,8 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
|
|
|
501
503
|
readonly modulesDisabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
502
504
|
/** Enable Liquid template syntax */
|
|
503
505
|
readonly liquidSyntax: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
506
|
+
/** Enable autosave (3-min interval + tab-hide). User toggles on/off from the header. */
|
|
507
|
+
readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
504
508
|
}, undefined>, {}>;
|
|
505
509
|
/** Block configuration */
|
|
506
510
|
readonly blocks: v.OptionalSchema<v.ObjectSchema<{
|
|
@@ -11,7 +11,7 @@ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToOption<__
|
|
|
11
11
|
close: () => void;
|
|
12
12
|
};
|
|
13
13
|
hasChanges: import("vue").ComputedRef<boolean>;
|
|
14
|
-
saveSilent: () => Promise<Omit<SavedTemplateDetails, "metadata"> | undefined> | undefined;
|
|
14
|
+
saveSilent: () => Promise<Omit<SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
|
|
15
15
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {
|
|
16
16
|
"dynamic-content:open": (detail: {
|
|
17
17
|
text: string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
2
|
+
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata"> | undefined> | undefined;
|
|
2
|
+
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
|
|
3
3
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
4
4
|
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata"> | undefined> | undefined;
|
|
2
|
+
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
|
|
3
3
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
4
4
|
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
|
-
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata"> | undefined> | undefined;
|
|
2
|
+
handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
|
|
3
3
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
4
4
|
export default _default;
|
|
@@ -62,6 +62,7 @@ export declare const useConfig: () => {
|
|
|
62
62
|
unsubscribe: boolean;
|
|
63
63
|
modulesDisabled: boolean;
|
|
64
64
|
liquidSyntax: boolean;
|
|
65
|
+
autosave: boolean;
|
|
65
66
|
};
|
|
66
67
|
blocks: {
|
|
67
68
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -159,6 +160,7 @@ export declare const useConfig: () => {
|
|
|
159
160
|
unsubscribe: boolean;
|
|
160
161
|
modulesDisabled: boolean;
|
|
161
162
|
liquidSyntax: boolean;
|
|
163
|
+
autosave: boolean;
|
|
162
164
|
} | null>;
|
|
163
165
|
blocks: import("vue").ComputedRef<{
|
|
164
166
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { SavedTemplateDetails } from '@@/Types/stripo';
|
|
2
2
|
export declare const useSave: () => {
|
|
3
|
-
save: (
|
|
3
|
+
save: (suppressEmit?: boolean, silent?: boolean) => Promise<Omit<SavedTemplateDetails, "metadata" | "silent"> | undefined>;
|
|
4
4
|
};
|
|
@@ -95,23 +95,15 @@ export declare class RecommendationConfigService {
|
|
|
95
95
|
*
|
|
96
96
|
* Called when a block is first created (dropped into template).
|
|
97
97
|
* Can optionally merge in partial config from migration.
|
|
98
|
-
*
|
|
99
|
-
* The `wasFreshDrop` flag distinguishes a brand-new drop (no prior config)
|
|
100
|
-
* from a clone (Stripo replays the source's setNodeConfig payload before
|
|
101
|
-
* onCreated fires). Callers use this to skip side-effects already inherited
|
|
102
|
-
* from the source.
|
|
103
98
|
* @example
|
|
104
99
|
* // In Block.onCreated lifecycle
|
|
105
|
-
*
|
|
100
|
+
* RecommendationConfigService.initializeConfig(this.api, node);
|
|
106
101
|
* @param api - Stripo extension API with document modifier
|
|
107
102
|
* @param node - The immutable HTML node to initialize
|
|
108
103
|
* @param partialConfig - Optional partial config to merge with defaults
|
|
109
|
-
* @returns The initialized configuration
|
|
104
|
+
* @returns The initialized configuration
|
|
110
105
|
*/
|
|
111
|
-
static initializeConfig(api: DocumentModifierApi, node: ImmutableHtmlNode, partialConfig?: PartialNodeConfig):
|
|
112
|
-
config: RecommendationNodeConfig;
|
|
113
|
-
wasFreshDrop: boolean;
|
|
114
|
-
};
|
|
106
|
+
static initializeConfig(api: DocumentModifierApi, node: ImmutableHtmlNode, partialConfig?: PartialNodeConfig): RecommendationNodeConfig;
|
|
115
107
|
/**
|
|
116
108
|
* Save complete configuration to a node
|
|
117
109
|
*
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const AUTOSAVE_STATUS: {
|
|
2
|
+
readonly IDLE: "idle";
|
|
3
|
+
readonly SAVING: "saving";
|
|
4
|
+
readonly SAVED: "saved";
|
|
5
|
+
readonly ERROR: "error";
|
|
6
|
+
};
|
|
7
|
+
export type AutosaveStatus = typeof AUTOSAVE_STATUS[keyof typeof AUTOSAVE_STATUS];
|
|
8
|
+
export declare const useAutosaveStore: import("pinia").StoreDefinition<"guidoAutosave", {
|
|
9
|
+
isOn: boolean;
|
|
10
|
+
lastSavedAt: Date | null;
|
|
11
|
+
status: AutosaveStatus;
|
|
12
|
+
}, {}, {}>;
|
|
@@ -67,6 +67,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
67
67
|
unsubscribe: boolean;
|
|
68
68
|
modulesDisabled: boolean;
|
|
69
69
|
liquidSyntax: boolean;
|
|
70
|
+
autosave: boolean;
|
|
70
71
|
};
|
|
71
72
|
blocks: {
|
|
72
73
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -170,6 +171,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
170
171
|
unsubscribe: boolean;
|
|
171
172
|
modulesDisabled: boolean;
|
|
172
173
|
liquidSyntax: boolean;
|
|
174
|
+
autosave: boolean;
|
|
173
175
|
};
|
|
174
176
|
blocks: {
|
|
175
177
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -273,6 +275,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
273
275
|
unsubscribe: boolean;
|
|
274
276
|
modulesDisabled: boolean;
|
|
275
277
|
liquidSyntax: boolean;
|
|
278
|
+
autosave: boolean;
|
|
276
279
|
};
|
|
277
280
|
blocks: {
|
|
278
281
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -376,6 +379,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
376
379
|
unsubscribe: boolean;
|
|
377
380
|
modulesDisabled: boolean;
|
|
378
381
|
liquidSyntax: boolean;
|
|
382
|
+
autosave: boolean;
|
|
379
383
|
};
|
|
380
384
|
blocks: {
|
|
381
385
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -479,6 +483,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
479
483
|
unsubscribe: boolean;
|
|
480
484
|
modulesDisabled: boolean;
|
|
481
485
|
liquidSyntax: boolean;
|
|
486
|
+
autosave: boolean;
|
|
482
487
|
};
|
|
483
488
|
blocks: {
|
|
484
489
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -582,6 +587,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
582
587
|
unsubscribe: boolean;
|
|
583
588
|
modulesDisabled: boolean;
|
|
584
589
|
liquidSyntax: boolean;
|
|
590
|
+
autosave: boolean;
|
|
585
591
|
};
|
|
586
592
|
blocks: {
|
|
587
593
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -685,6 +691,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
685
691
|
unsubscribe: boolean;
|
|
686
692
|
modulesDisabled: boolean;
|
|
687
693
|
liquidSyntax: boolean;
|
|
694
|
+
autosave: boolean;
|
|
688
695
|
};
|
|
689
696
|
blocks: {
|
|
690
697
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -788,6 +795,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
788
795
|
unsubscribe: boolean;
|
|
789
796
|
modulesDisabled: boolean;
|
|
790
797
|
liquidSyntax: boolean;
|
|
798
|
+
autosave: boolean;
|
|
791
799
|
};
|
|
792
800
|
blocks: {
|
|
793
801
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -891,6 +899,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
891
899
|
unsubscribe: boolean;
|
|
892
900
|
modulesDisabled: boolean;
|
|
893
901
|
liquidSyntax: boolean;
|
|
902
|
+
autosave: boolean;
|
|
894
903
|
};
|
|
895
904
|
blocks: {
|
|
896
905
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -994,6 +1003,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
994
1003
|
unsubscribe: boolean;
|
|
995
1004
|
modulesDisabled: boolean;
|
|
996
1005
|
liquidSyntax: boolean;
|
|
1006
|
+
autosave: boolean;
|
|
997
1007
|
};
|
|
998
1008
|
blocks: {
|
|
999
1009
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1097,6 +1107,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1097
1107
|
unsubscribe: boolean;
|
|
1098
1108
|
modulesDisabled: boolean;
|
|
1099
1109
|
liquidSyntax: boolean;
|
|
1110
|
+
autosave: boolean;
|
|
1100
1111
|
};
|
|
1101
1112
|
blocks: {
|
|
1102
1113
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1200,6 +1211,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1200
1211
|
unsubscribe: boolean;
|
|
1201
1212
|
modulesDisabled: boolean;
|
|
1202
1213
|
liquidSyntax: boolean;
|
|
1214
|
+
autosave: boolean;
|
|
1203
1215
|
};
|
|
1204
1216
|
blocks: {
|
|
1205
1217
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1303,6 +1315,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1303
1315
|
unsubscribe: boolean;
|
|
1304
1316
|
modulesDisabled: boolean;
|
|
1305
1317
|
liquidSyntax: boolean;
|
|
1318
|
+
autosave: boolean;
|
|
1306
1319
|
};
|
|
1307
1320
|
blocks: {
|
|
1308
1321
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1406,6 +1419,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1406
1419
|
unsubscribe: boolean;
|
|
1407
1420
|
modulesDisabled: boolean;
|
|
1408
1421
|
liquidSyntax: boolean;
|
|
1422
|
+
autosave: boolean;
|
|
1409
1423
|
};
|
|
1410
1424
|
blocks: {
|
|
1411
1425
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1509,6 +1523,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1509
1523
|
unsubscribe: boolean;
|
|
1510
1524
|
modulesDisabled: boolean;
|
|
1511
1525
|
liquidSyntax: boolean;
|
|
1526
|
+
autosave: boolean;
|
|
1512
1527
|
};
|
|
1513
1528
|
blocks: {
|
|
1514
1529
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1612,6 +1627,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1612
1627
|
unsubscribe: boolean;
|
|
1613
1628
|
modulesDisabled: boolean;
|
|
1614
1629
|
liquidSyntax: boolean;
|
|
1630
|
+
autosave: boolean;
|
|
1615
1631
|
};
|
|
1616
1632
|
blocks: {
|
|
1617
1633
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1715,6 +1731,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1715
1731
|
unsubscribe: boolean;
|
|
1716
1732
|
modulesDisabled: boolean;
|
|
1717
1733
|
liquidSyntax: boolean;
|
|
1734
|
+
autosave: boolean;
|
|
1718
1735
|
};
|
|
1719
1736
|
blocks: {
|
|
1720
1737
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -1818,6 +1835,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1818
1835
|
unsubscribe: boolean;
|
|
1819
1836
|
modulesDisabled: boolean;
|
|
1820
1837
|
liquidSyntax: boolean;
|
|
1838
|
+
autosave: boolean;
|
|
1821
1839
|
};
|
|
1822
1840
|
blocks: {
|
|
1823
1841
|
excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
|
|
@@ -263,4 +263,27 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
|
|
|
263
263
|
templateId: string;
|
|
264
264
|
syncModulesEnabled: boolean;
|
|
265
265
|
}>) => boolean;
|
|
266
|
+
isInSaveableState: (state: {
|
|
267
|
+
loadingStatus: boolean;
|
|
268
|
+
isCodeEditorOpen: boolean;
|
|
269
|
+
isSaveAsTemplateDrawerOpen: boolean;
|
|
270
|
+
isVersionHistoryOpen: boolean;
|
|
271
|
+
isPreviewModeOpen: boolean;
|
|
272
|
+
editorVisualMode: string;
|
|
273
|
+
hasChanges: boolean;
|
|
274
|
+
isStripoInitialized: boolean;
|
|
275
|
+
templateId: string;
|
|
276
|
+
syncModulesEnabled: boolean;
|
|
277
|
+
} & import("pinia").PiniaCustomStateProperties<{
|
|
278
|
+
loadingStatus: boolean;
|
|
279
|
+
isCodeEditorOpen: boolean;
|
|
280
|
+
isSaveAsTemplateDrawerOpen: boolean;
|
|
281
|
+
isVersionHistoryOpen: boolean;
|
|
282
|
+
isPreviewModeOpen: boolean;
|
|
283
|
+
editorVisualMode: string;
|
|
284
|
+
hasChanges: boolean;
|
|
285
|
+
isStripoInitialized: boolean;
|
|
286
|
+
templateId: string;
|
|
287
|
+
syncModulesEnabled: boolean;
|
|
288
|
+
}>) => boolean;
|
|
266
289
|
}, {}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a Date as local time in 24-hour format.
|
|
3
|
+
* Pass `useTimezone = true` to append the UTC offset and city name — useful when the
|
|
4
|
+
* timestamp must clearly communicate the client's timezone.
|
|
5
|
+
* @example formatLocalTime(date) -> 12:20:02
|
|
6
|
+
* @example formatLocalTime(date, true) -> 12:20:02 (UTC+3 Istanbul)
|
|
7
|
+
*/
|
|
8
|
+
export declare const formatLocalTime: (date: Date, useTimezone?: boolean) => string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineStore as e } from "pinia";
|
|
2
|
+
const t = {
|
|
3
|
+
IDLE: "idle",
|
|
4
|
+
SAVING: "saving",
|
|
5
|
+
SAVED: "saved",
|
|
6
|
+
ERROR: "error"
|
|
7
|
+
}, o = e("guidoAutosave", {
|
|
8
|
+
state: () => ({
|
|
9
|
+
isOn: !1,
|
|
10
|
+
lastSavedAt: null,
|
|
11
|
+
status: t.IDLE
|
|
12
|
+
})
|
|
13
|
+
});
|
|
14
|
+
export {
|
|
15
|
+
t as AUTOSAVE_STATUS,
|
|
16
|
+
o as useAutosaveStore
|
|
17
|
+
};
|
package/dist/stores/editor.js
CHANGED
|
@@ -25,7 +25,9 @@ const o = e("guidoEditor", {
|
|
|
25
25
|
isExportButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
26
26
|
isSaveAsButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
27
27
|
isTestButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
28
|
-
isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen
|
|
28
|
+
isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen,
|
|
29
|
+
// Autosave
|
|
30
|
+
isInSaveableState: (i) => !i.loadingStatus && !i.isVersionHistoryOpen && !i.isPreviewModeOpen && !i.isCodeEditorOpen
|
|
29
31
|
}
|
|
30
32
|
});
|
|
31
33
|
export {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const r = (t) => {
|
|
2
|
+
const e = -t.getTimezoneOffset(), o = e >= 0 ? "+" : "-", n = Math.abs(e), s = Math.floor(n / 60), i = n % 60;
|
|
3
|
+
return i === 0 ? `UTC${o}${s}` : `UTC${o}${s}:${String(i).padStart(2, "0")}`;
|
|
4
|
+
}, a = () => {
|
|
5
|
+
var e;
|
|
6
|
+
const { timeZone: t } = new Intl.DateTimeFormat().resolvedOptions();
|
|
7
|
+
return ((e = t.split("/").pop()) == null ? void 0 : e.replace(/_/g, " ")) ?? t;
|
|
8
|
+
}, c = (t, e = !1) => {
|
|
9
|
+
const o = t.toLocaleTimeString([], {
|
|
10
|
+
hour: "2-digit",
|
|
11
|
+
hour12: !1,
|
|
12
|
+
minute: "2-digit",
|
|
13
|
+
second: "2-digit"
|
|
14
|
+
});
|
|
15
|
+
return e ? `${o} (${r(t)} ${a()})` : o;
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
c as formatLocalTime
|
|
19
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.2.0-beta.
|
|
3
|
+
"version": "3.2.0-beta.556da4b",
|
|
4
4
|
"description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
|
|
5
5
|
"main": "./dist/guido.umd.cjs",
|
|
6
6
|
"module": "./dist/library.js",
|