@useinsider/guido 3.18.2-beta.8ef3138 → 3.18.2-beta.9be830c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/config/schemas.js +15 -13
- package/dist/components/Guido.vue.js +7 -7
- package/dist/components/Guido.vue2.js +2 -2
- package/dist/components/organisms/AutoSaveController.vue2.js +10 -8
- package/dist/components/organisms/header/AutoSaveStatus.vue.js +17 -0
- package/dist/components/organisms/header/AutoSaveStatus.vue2.js +27 -0
- package/dist/components/organisms/header/EditorActions.vue.js +13 -13
- package/dist/components/organisms/header/EditorActions.vue2.js +36 -52
- package/dist/components/organisms/header/EditorActionsMenu.vue.js +20 -0
- package/dist/components/organisms/header/EditorActionsMenu.vue2.js +48 -0
- package/dist/components/organisms/header/HeaderWrapper.vue.js +6 -6
- package/dist/components/organisms/header/HeaderWrapper.vue2.js +9 -17
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +28 -23
- package/dist/components/organisms/header/MiddleSlot.vue.js +4 -4
- package/dist/components/organisms/header/MiddleSlot.vue2.js +8 -7
- package/dist/components/organisms/header/RightSlot.vue.js +9 -8
- package/dist/components/organisms/header/RightSlot.vue2.js +13 -18
- package/dist/components/organisms/header/accessibility/AccessibilityToolbar.vue.js +18 -0
- package/dist/components/organisms/header/accessibility/AccessibilityToolbar.vue2.js +37 -0
- package/dist/components/organisms/header/accessibility/ColorVisionSelect.vue.js +24 -0
- package/dist/components/organisms/header/accessibility/ColorVisionSelect.vue2.js +48 -0
- package/dist/components/organisms/onboarding/EditorTabBarOnboarding.vue.js +19 -0
- package/dist/components/organisms/onboarding/EditorTabBarOnboarding.vue2.js +82 -0
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue.js +12 -12
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +54 -36
- package/dist/composables/useAccessibilityApi.js +35 -0
- package/dist/composables/useCustomInterfaceAppearance.js +31 -28
- package/dist/config/i18n/en/labels.json.js +36 -4
- package/dist/config/i18n/en/tooltips.json.js +2 -1
- package/dist/guido.css +1 -1
- package/dist/node_modules/@vueuse/core/index.js +102 -0
- package/dist/node_modules/@vueuse/shared/index.js +40 -28
- package/dist/sprite.svg +6 -0
- package/dist/src/@types/config/schemas.d.ts +4 -0
- package/dist/src/components/organisms/AutoSaveController.vue.d.ts +3 -1
- package/dist/src/components/organisms/header/EditorActionsMenu.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -3
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -3
- package/dist/src/components/organisms/header/accessibility/AccessibilityToolbar.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/accessibility/ColorVisionSelect.vue.d.ts +2 -0
- package/dist/src/components/organisms/onboarding/EditorTabBarOnboarding.vue.d.ts +2 -0
- package/dist/src/composables/useAccessibilityApi.d.ts +15 -0
- package/dist/src/composables/useActionsApi.d.ts +2 -2
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/stores/config.d.ts +18 -0
- package/dist/src/stores/editor.d.ts +107 -0
- package/dist/src/stores/onboarding.d.ts +552 -1
- package/dist/src/stores/version-history.d.ts +1 -1
- package/dist/src/utils/liquidDynamicContent.d.ts +20 -0
- package/dist/src/utils/timeUtil.d.ts +10 -0
- package/dist/static/styles/components/accessibility.css.js +282 -0
- package/dist/static/styles/variables.css.js +2 -0
- package/dist/stores/editor.js +13 -4
- package/dist/stores/onboarding.js +39 -18
- package/dist/utils/genericUtil.js +64 -61
- package/dist/utils/liquidDynamicContent.js +15 -0
- package/dist/utils/timeUtil.js +7 -17
- package/package.json +1 -1
- package/dist/components/organisms/header/AutoSaveToggle.vue.js +0 -22
- package/dist/components/organisms/header/AutoSaveToggle.vue2.js +0 -19
- /package/dist/src/components/organisms/header/{AutoSaveToggle.vue.d.ts → AutoSaveStatus.vue.d.ts} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BaseDynamicContent } from '@@/Types/generic';
|
|
2
|
+
export type DynamicContentFormat = NonNullable<BaseDynamicContent['format']>;
|
|
3
|
+
/** Format key the dynamic-content picker sends for a custom date/time format. */
|
|
4
|
+
export declare const TIME_FORMAT_KEY = "time-format";
|
|
5
|
+
/** Wraps a Liquid filter argument in whichever quote style the value itself does not use. */
|
|
6
|
+
export declare const quoteArgument: (value: string) => string | null;
|
|
7
|
+
/**
|
|
8
|
+
* `{ key: 'time-format', value: '%Y-%m-%d' }` -> `date: "%Y-%m-%d"`.
|
|
9
|
+
*
|
|
10
|
+
* Only a custom date/time strftime pattern has a Liquid equivalent. Anything else returns null so
|
|
11
|
+
* the caller emits a plain tag rather than one that silently lost — or literally printed — its
|
|
12
|
+
* format.
|
|
13
|
+
* @example formatToLiquidFilter({ key: 'time-format', value: '%b %-d, %Y' }) -> date: "%b %-d, %Y"
|
|
14
|
+
*/
|
|
15
|
+
export declare const formatToLiquidFilter: (format: DynamicContentFormat) => string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Inverse of `formatToLiquidFilter` — reads the picker format back out of one filter segment, so a
|
|
18
|
+
* reopened tag restores its selection in the host's format dropdown.
|
|
19
|
+
*/
|
|
20
|
+
export declare const liquidFilterToFormat: (segment: string) => DynamicContentFormat | null;
|
|
@@ -6,3 +6,13 @@
|
|
|
6
6
|
* @example formatLocalTime(date, true) -> 12:20:02 (UTC+3 Istanbul)
|
|
7
7
|
*/
|
|
8
8
|
export declare const formatLocalTime: (date: Date, useTimezone?: boolean) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Auto-save timestamp parts for the header status label. The component picks the
|
|
11
|
+
* copy: same day -> "Autosaved at {time}, Today"; earlier -> "Autosaved at {date}".
|
|
12
|
+
* @example autoSaveTimestamp(date) -> { isToday: true, time: '20:01', date: '16.07.2026' }
|
|
13
|
+
*/
|
|
14
|
+
export declare const autoSaveTimestamp: (date: Date, now?: Date) => {
|
|
15
|
+
isToday: boolean;
|
|
16
|
+
time: string;
|
|
17
|
+
date: string;
|
|
18
|
+
};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
const e = `/* Stripo Accessibility Checker panel (ue-accessibility-panel).
|
|
2
|
+
Stripo's defaults derive icon/button/outline colors from --ue-primary-color,
|
|
3
|
+
whose stock hue is green (129) — Figma DT-33912 wants Insider blue. */
|
|
4
|
+
|
|
5
|
+
/* Stripo sizes the panel to its content (max-height: 100%), so short tabs (Ignored, empty
|
|
6
|
+
states) end mid-page; the design keeps it full height in every state. */
|
|
7
|
+
ue-ui-simple-panel.accessibility-panel,
|
|
8
|
+
ue-accessibility-panel {
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* The refresh button only renders once results land; reserve its 50x50 slot so the
|
|
13
|
+
header keeps the same height and title width while the check is loading. */
|
|
14
|
+
ue-accessibility-panel .header-control-panel-right {
|
|
15
|
+
min-width: 50px;
|
|
16
|
+
min-height: 50px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Failed / Passed / Ignored count chips. Stripo paints them as filled
|
|
20
|
+
red/green/blue pills via .accent.error / .accent.success. */
|
|
21
|
+
ue-accessibility-panel .tabs-header .accent {
|
|
22
|
+
min-width: 21px;
|
|
23
|
+
margin-left: 8px;
|
|
24
|
+
padding: 3px 5px;
|
|
25
|
+
border: 1px solid var(--guido-color-gray-300);
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
background-color: var(--guido-color-white);
|
|
28
|
+
color: var(--guido-color-gray-800);
|
|
29
|
+
font-size: 13px;
|
|
30
|
+
font-weight: 400;
|
|
31
|
+
line-height: 16px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ue-accessibility-panel .tabs-header button.checked .accent {
|
|
35
|
+
border-color: var(--guido-color-primary-500);
|
|
36
|
+
color: var(--guido-color-primary-500);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Issue card */
|
|
40
|
+
ue-accessibility-panel .issue-card-surface {
|
|
41
|
+
border-radius: 8px;
|
|
42
|
+
outline: 1px solid var(--guido-color-gray-300);
|
|
43
|
+
outline-offset: -1px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ue-accessibility-panel .issue-card-surface--active {
|
|
47
|
+
outline-color: var(--guido-color-primary-500);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ue-accessibility-panel .issue-card-title {
|
|
51
|
+
color: var(--guido-color-gray-800);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Per-issue help "?" icon: 14x14 glyph centered in a 24x24 hit area. Stripo
|
|
55
|
+
renders the ue-icon svg at width/height 100%, so it fills the whole box —
|
|
56
|
+
pin the svg to 14px and center it. */
|
|
57
|
+
ue-accessibility-panel .issue-card-header-row .icon-help {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
justify-content: center;
|
|
61
|
+
width: 24px;
|
|
62
|
+
height: 24px;
|
|
63
|
+
color: var(--guido-color-gray-600);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
ue-accessibility-panel .issue-card-header-row .icon-help svg {
|
|
67
|
+
width: 14px;
|
|
68
|
+
height: 14px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Severity icons: Critical (cross-circle), Serious (warning), Moderate (info) */
|
|
72
|
+
ue-accessibility-panel .issue-card-header-row ue-icon-component.danger {
|
|
73
|
+
color: var(--guido-color-danger-500);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ue-accessibility-panel .issue-card-header-row ue-icon-component.warning {
|
|
77
|
+
color: var(--guido-color-warning-500);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ue-accessibility-panel .issue-card-header-row ue-icon-component.info {
|
|
81
|
+
color: var(--guido-color-primary-500);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Passed tab is read-only. Stripo already blocks pointer events on these controls but only
|
|
85
|
+
styles the alt-text input as disabled; give the selects and color inputs the same look. */
|
|
86
|
+
ue-accessibility-passed-tab input,
|
|
87
|
+
ue-accessibility-passed-tab ue-select .toggle-select-button {
|
|
88
|
+
opacity: 0.6;
|
|
89
|
+
cursor: not-allowed;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Contrast card rows (Figma 4522:11243): a 10px section inset holding 50px rows with 16px
|
|
93
|
+
side padding, so labels and swatches sit 26px in while the action buttons stay at 10px. */
|
|
94
|
+
ue-accessibility-panel .controls-separator-line:has(.fit-to-color) {
|
|
95
|
+
padding: 10px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Passed cards pin a 24px instance-count badge 8px off the bottom-right corner, where the
|
|
99
|
+
right-aligned ratio now ends; keep the last row clear of it. */
|
|
100
|
+
ue-accessibility-passed-tab .controls-separator-line:has(.fit-to-color) {
|
|
101
|
+
padding-bottom: 34px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ue-accessibility-panel .controls-separator-line:has(.fit-to-color) .sub-container.two-columns {
|
|
105
|
+
box-sizing: border-box;
|
|
106
|
+
min-height: 50px;
|
|
107
|
+
padding: 5px 16px;
|
|
108
|
+
align-items: center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Ratio value: Stripo left-aligns it in a swatch-wide box; the design ends it at the
|
|
112
|
+
swatches' right edge, behind a 16px glyph in a 24px icon box. */
|
|
113
|
+
ue-accessibility-panel .controls-list.fit-to-color {
|
|
114
|
+
justify-content: flex-end;
|
|
115
|
+
align-items: center;
|
|
116
|
+
gap: 0;
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
line-height: 16px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
ue-accessibility-panel .controls-list.fit-to-color ue-icon-component {
|
|
122
|
+
align-items: center;
|
|
123
|
+
justify-content: center;
|
|
124
|
+
width: 24px;
|
|
125
|
+
height: 24px;
|
|
126
|
+
margin: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
ue-accessibility-panel .controls-list.fit-to-color ue-icon-component svg {
|
|
130
|
+
width: 16px;
|
|
131
|
+
height: 16px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
ue-accessibility-panel .controls-list.fit-to-color ue-icon-component.warning {
|
|
135
|
+
color: var(--guido-color-warning-500);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Empty states (Figma 5122:17577, DS InNoData): the DS "no-personalization" art above a
|
|
139
|
+
title and description, centered in the tab. Failed/Ignored text comes from localePatch as
|
|
140
|
+
"Title\\nDescription" and ::first-line styles the title; Passed renders nothing when empty,
|
|
141
|
+
so it gets the same box from generated content. */
|
|
142
|
+
ue-accessibility-panel {
|
|
143
|
+
--ue-accessibility-image-width: 240px;
|
|
144
|
+
--ue-accessibility-image-height: 240px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* The scroll area only grows to its content (max-height: 100%); stretch it to the panel
|
|
148
|
+
bottom so the empty state can center in the space below the tabs. */
|
|
149
|
+
ue-accessibility-panel ue-scrollable-container:has(.accessibility-list-empty, ue-accessibility-passed-tab:empty) {
|
|
150
|
+
flex-grow: 1;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
ue-accessibility-panel ue-scrollable-container:has(.accessibility-list-empty, ue-accessibility-passed-tab:empty) .ue-scrollable {
|
|
154
|
+
height: 100%;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
ue-accessibility-panel .ue-scrollable-content:has(.accessibility-list-empty, ue-accessibility-passed-tab:empty) {
|
|
158
|
+
display: flex;
|
|
159
|
+
flex-direction: column;
|
|
160
|
+
justify-content: center;
|
|
161
|
+
min-height: 100%;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
ue-accessibility-panel .accessibility-list-empty.light-theme.failed-list,
|
|
165
|
+
ue-accessibility-panel .accessibility-list-empty.light-theme.ignored-list,
|
|
166
|
+
ue-accessibility-passed-tab:empty::before {
|
|
167
|
+
display: block;
|
|
168
|
+
height: auto;
|
|
169
|
+
margin: 0;
|
|
170
|
+
padding: 248px 16px 0;
|
|
171
|
+
background: url("https://image.useinsider.com/insider-design-system/img/speacial/no-personalization.svg") no-repeat center top / 240px 240px;
|
|
172
|
+
color: var(--guido-color-neutral-500);
|
|
173
|
+
font-size: 15px;
|
|
174
|
+
line-height: 24px;
|
|
175
|
+
text-align: center;
|
|
176
|
+
white-space: pre-line;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Stripo renders nothing at all for an empty Passed tab, so this copy cannot come from the
|
|
180
|
+
localePatch like its Failed/Ignored siblings in src/config/i18n/en/labels.json — keep the
|
|
181
|
+
three wordings in step by hand. \`display: block\` makes the host a block container so
|
|
182
|
+
::first-line below can reach the title inside the generated content. */
|
|
183
|
+
ue-accessibility-passed-tab:empty {
|
|
184
|
+
display: block;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
ue-accessibility-passed-tab:empty::before {
|
|
188
|
+
content: "No Passed Items\\A You have no passed items.";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Title is 18/24 with InNoData's 8px gap below it; a 40px line box gives both, and its
|
|
192
|
+
extra 8px on top is why the padding above is 248px, not 240 + 16. */
|
|
193
|
+
ue-accessibility-panel .accessibility-list-empty::first-line,
|
|
194
|
+
ue-accessibility-passed-tab:empty::first-line {
|
|
195
|
+
color: var(--guido-color-neutral-700);
|
|
196
|
+
font-size: 18px;
|
|
197
|
+
line-height: 40px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Card actions: Ignore / Un-ignore / Auto-tune are neutral, Apply is primary */
|
|
201
|
+
ue-accessibility-panel .e2e-ignore-button > .button,
|
|
202
|
+
ue-accessibility-panel .e2e-unignore-button > .button,
|
|
203
|
+
ue-accessibility-panel .e2e-auto-tune-button > .button {
|
|
204
|
+
border: none;
|
|
205
|
+
background-color: var(--guido-color-neutral-200);
|
|
206
|
+
color: var(--guido-color-neutral-800);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
ue-accessibility-panel .e2e-ignore-button > .button .icon-button,
|
|
210
|
+
ue-accessibility-panel .e2e-unignore-button > .button .icon-button,
|
|
211
|
+
ue-accessibility-panel .e2e-auto-tune-button > .button .icon-button {
|
|
212
|
+
color: var(--guido-color-neutral-800);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
ue-accessibility-panel .e2e-ignore-button > .button:hover:not(:disabled,.disabled),
|
|
216
|
+
ue-accessibility-panel .e2e-unignore-button > .button:hover:not(:disabled,.disabled),
|
|
217
|
+
ue-accessibility-panel .e2e-auto-tune-button > .button:hover:not(:disabled,.disabled) {
|
|
218
|
+
background-color: var(--guido-color-neutral-100);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
ue-accessibility-panel .e2e-apply-button > .button {
|
|
222
|
+
border: none;
|
|
223
|
+
background-color: var(--guido-color-primary-100);
|
|
224
|
+
color: var(--guido-color-primary-500);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
ue-accessibility-panel .e2e-apply-button > .button .icon-button {
|
|
228
|
+
color: var(--guido-color-primary-500);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
ue-accessibility-panel .e2e-apply-button > .button:hover:not(:disabled,.disabled) {
|
|
232
|
+
background-color: var(--guido-color-primary-0);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Re-run check button (header control). Stripo tints the rotate icon with
|
|
236
|
+
--ue-primary-color; Figma DT-33912 wants Insider primary. Not inside
|
|
237
|
+
ue-accessibility-panel, so scoped by its own e2e class. */
|
|
238
|
+
.e2e-accessibility-refresh .icon-button {
|
|
239
|
+
color: var(--guido-color-primary-500);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* Help-icon hint. The popover is portalled outside the panel, so it cannot be
|
|
243
|
+
scoped to ue-accessibility-panel. Stripo tints the link with --ue-primary-color. */
|
|
244
|
+
.ue-popover.dark,
|
|
245
|
+
.ue-popover.dark-tiny {
|
|
246
|
+
border-radius: 4px;
|
|
247
|
+
background: var(--guido-color-gray-800);
|
|
248
|
+
box-shadow: 0 15px 17.5px rgb(0 0 0 / 10%), 0 8px 5px rgb(0 0 0 / 10%);
|
|
249
|
+
color: var(--guido-color-white);
|
|
250
|
+
font-size: 13px;
|
|
251
|
+
line-height: 16px;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.ue-popover.dark .popup-pointer ue-icon-component svg,
|
|
255
|
+
.ue-popover.dark-tiny .popup-pointer ue-icon-component svg {
|
|
256
|
+
fill: var(--guido-color-gray-800);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Any anchor in the hint, not just the ue-description wrapper: the accessibility
|
|
260
|
+
checker's "Read more … ACT Rules Community Group forum." link renders outside it
|
|
261
|
+
and would otherwise keep Stripo's primary tint, unreadable on the dark surface.
|
|
262
|
+
The ue-description forms match Stripo's own \`.ue-popover.dark-tiny ue-description a\`
|
|
263
|
+
specificity; this file is appended last, so the tie goes to Figma's white link. */
|
|
264
|
+
.ue-popover.dark a,
|
|
265
|
+
.ue-popover.dark-tiny a,
|
|
266
|
+
.ue-popover.dark ue-description a,
|
|
267
|
+
.ue-popover.dark-tiny ue-description a {
|
|
268
|
+
color: var(--guido-color-white);
|
|
269
|
+
text-decoration: underline;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Stripo ships \`ue-description a { display: none }\`, which hides the per-rule "Read more"
|
|
273
|
+
link even though it already carries the right ACT/Deque URL. Re-show only those links,
|
|
274
|
+
keyed by host, so no other editor hint starts showing links Stripo meant to hide. */
|
|
275
|
+
.ue-popover ue-description a[href^="https://act-rules.github.io/"],
|
|
276
|
+
.ue-popover ue-description a[href^="https://dequeuniversity.com/"] {
|
|
277
|
+
display: inline;
|
|
278
|
+
}
|
|
279
|
+
`;
|
|
280
|
+
export {
|
|
281
|
+
e as default
|
|
282
|
+
};
|
|
@@ -14,8 +14,10 @@ const o = `:host {
|
|
|
14
14
|
--guido-color-gray-0: #F9F9F9;
|
|
15
15
|
--guido-color-neutral-800: #222938;
|
|
16
16
|
--guido-color-neutral-700: #2C3546;
|
|
17
|
+
--guido-color-neutral-500: #5D6980;
|
|
17
18
|
--guido-color-neutral-200: #DCDFE6;
|
|
18
19
|
--guido-color-neutral-100: #EFF2F4;
|
|
20
|
+
--guido-color-warning-500: #FFBF00;
|
|
19
21
|
--guido-color-danger-300: #e84342;
|
|
20
22
|
--guido-color-danger-500: #DC2A2A;
|
|
21
23
|
--guido-box-shadow: 0 4px 12px 0 rgba(44,53,70,0.15);
|
package/dist/stores/editor.js
CHANGED
|
@@ -6,6 +6,9 @@ const o = e("guidoEditor", {
|
|
|
6
6
|
isSaveAsTemplateDrawerOpen: !1,
|
|
7
7
|
isVersionHistoryOpen: !1,
|
|
8
8
|
isPreviewModeOpen: !1,
|
|
9
|
+
isAccessibilityTestingOpen: !1,
|
|
10
|
+
imagesHidden: !1,
|
|
11
|
+
colorVisionDeficiency: "",
|
|
9
12
|
editorVisualMode: "desktop",
|
|
10
13
|
hasChanges: !1,
|
|
11
14
|
isStripoInitialized: !1,
|
|
@@ -17,20 +20,26 @@ const o = e("guidoEditor", {
|
|
|
17
20
|
}),
|
|
18
21
|
getters: {
|
|
19
22
|
// Middle Slot
|
|
20
|
-
isEditorToolbarVisible: (i) => !i.isVersionHistoryOpen && !i.isPreviewModeOpen,
|
|
23
|
+
isEditorToolbarVisible: (i) => !i.isVersionHistoryOpen && !i.isPreviewModeOpen && !i.isAccessibilityTestingOpen,
|
|
21
24
|
isUndoButtonDisabled: (i) => i.loadingStatus || i.isPreviewModeOpen,
|
|
22
25
|
isRedoButtonDisabled: (i) => i.loadingStatus || i.isPreviewModeOpen,
|
|
23
26
|
isCodeEditorButtonDisabled: (i) => i.loadingStatus || i.isPreviewModeOpen,
|
|
24
27
|
isPreviewButtonDisabled: (i) => i.loadingStatus,
|
|
25
28
|
isViewOptionsDisabled: (i) => i.loadingStatus || i.isPreviewModeOpen,
|
|
26
29
|
// Right Slot
|
|
30
|
+
// Normal editing: neither the version-history nor the accessibility-testing
|
|
31
|
+
// takeover, both of which swap the right slot — kebab included — for their own
|
|
32
|
+
// controls, so anything anchored to it has nothing to point at.
|
|
33
|
+
isNormalMode: (i) => !i.isVersionHistoryOpen && !i.isAccessibilityTestingOpen,
|
|
27
34
|
isVersionHistoryButtonDisabled: (i) => i.loadingStatus || i.isPreviewModeOpen,
|
|
28
35
|
isExportButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
29
36
|
isSaveAsButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
30
37
|
isTestButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
|
|
31
|
-
isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen,
|
|
32
|
-
// Autosave
|
|
33
|
-
|
|
38
|
+
isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen || i.isAccessibilityTestingOpen,
|
|
39
|
+
// Autosave. Accessibility testing belongs with the other takeovers: the mode drives
|
|
40
|
+
// Stripo through simulations (hidden images, color-vision filters) that a save
|
|
41
|
+
// landing mid-simulation would capture.
|
|
42
|
+
isInSaveableState: (i) => !i.loadingStatus && !i.isVersionHistoryOpen && !i.isPreviewModeOpen && !i.isCodeEditorOpen && !i.isAccessibilityTestingOpen
|
|
34
43
|
}
|
|
35
44
|
});
|
|
36
45
|
export {
|
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import { useOnboardingApi as
|
|
1
|
+
import { useOnboardingApi as t } from "../services/onboardingApi.js";
|
|
2
2
|
import { defineStore as e } from "pinia";
|
|
3
|
-
const
|
|
3
|
+
const r = () => ({
|
|
4
4
|
cardIndex: 0,
|
|
5
5
|
isActive: !1,
|
|
6
6
|
config: []
|
|
7
7
|
}), a = () => ({
|
|
8
8
|
onboardings: {
|
|
9
|
-
newVersionPopup:
|
|
10
|
-
genericOnboarding:
|
|
11
|
-
textBlockOnboarding:
|
|
12
|
-
versionHistoryOnboarding:
|
|
13
|
-
ampOnboarding:
|
|
14
|
-
itemsOnboarding:
|
|
9
|
+
newVersionPopup: r(),
|
|
10
|
+
genericOnboarding: r(),
|
|
11
|
+
textBlockOnboarding: r(),
|
|
12
|
+
versionHistoryOnboarding: r(),
|
|
13
|
+
ampOnboarding: r(),
|
|
14
|
+
itemsOnboarding: r(),
|
|
15
|
+
editorTabBarOnboarding: r()
|
|
15
16
|
},
|
|
16
17
|
userModalState: {},
|
|
17
|
-
isFetched: !1
|
|
18
|
-
|
|
18
|
+
isFetched: !1,
|
|
19
|
+
// Onboardings the user closed in this page session. The saved state cannot stand in
|
|
20
|
+
// for it: close() fills it even when the save fails, and a test stub can keep
|
|
21
|
+
// reporting "unseen". Being wiped by another onboarding is deliberately not in here,
|
|
22
|
+
// so an interrupted tour can come back once that other one is done.
|
|
23
|
+
closedThisSession: []
|
|
24
|
+
}), g = e("guidoOnboarding", {
|
|
19
25
|
state: () => a(),
|
|
20
26
|
getters: {
|
|
21
27
|
getOnboarding: (n) => (i) => n.onboardings[i],
|
|
@@ -44,6 +50,16 @@ const t = () => ({
|
|
|
44
50
|
const { itemsOnboarding: i } = n.onboardings;
|
|
45
51
|
return i.config[i.cardIndex];
|
|
46
52
|
},
|
|
53
|
+
getEditorTabBarCurrentCard: (n) => {
|
|
54
|
+
const { editorTabBarOnboarding: i } = n.onboardings;
|
|
55
|
+
return i.config[i.cardIndex];
|
|
56
|
+
},
|
|
57
|
+
// Every tab-bar tour card after the first points at a row inside the kebab menu,
|
|
58
|
+
// so the menu has to stay open under them.
|
|
59
|
+
isEditorActionsMenuPinned: (n) => {
|
|
60
|
+
const { editorTabBarOnboarding: i } = n.onboardings;
|
|
61
|
+
return i.isActive && i.cardIndex > 0;
|
|
62
|
+
},
|
|
47
63
|
shouldShowOnboarding: (n) => (i) => {
|
|
48
64
|
const o = n.userModalState.Guido;
|
|
49
65
|
return i === "newVersionPopup" && (o != null && o.genericOnboarding) ? !1 : o ? !o[i] : !0;
|
|
@@ -63,7 +79,12 @@ const t = () => ({
|
|
|
63
79
|
this.shouldShowOnboarding(n) && !this.isActive(n) && this.start(n);
|
|
64
80
|
},
|
|
65
81
|
async close(n) {
|
|
66
|
-
|
|
82
|
+
this.closedThisSession.includes(n) || this.closedThisSession.push(n), this.onboardings[n].isActive = !1, this.onboardings[n].cardIndex = 0, this.onboardings[n].config = [];
|
|
83
|
+
try {
|
|
84
|
+
await this.setUserModalState(n, "true", "Guido");
|
|
85
|
+
} catch (i) {
|
|
86
|
+
console.warn("guido:onboarding:close-not-persisted", n, i);
|
|
87
|
+
}
|
|
67
88
|
},
|
|
68
89
|
next(n) {
|
|
69
90
|
this.onboardings[n].cardIndex < this.onboardings[n].config.length - 1 && this.onboardings[n].cardIndex++;
|
|
@@ -72,14 +93,14 @@ const t = () => ({
|
|
|
72
93
|
this.onboardings[n].cardIndex > 0 && this.onboardings[n].cardIndex--;
|
|
73
94
|
},
|
|
74
95
|
updateCardPosition(n, i, o) {
|
|
75
|
-
const
|
|
76
|
-
|
|
96
|
+
const s = this.onboardings[n].config[i];
|
|
97
|
+
s && (s.top = o.top, s.position = o.position);
|
|
77
98
|
},
|
|
78
99
|
setConfig(n, i) {
|
|
79
100
|
this.onboardings[n].config = i ?? [], this.onboardings[n].cardIndex >= this.onboardings[n].config.length && (this.onboardings[n].cardIndex = 0);
|
|
80
101
|
},
|
|
81
102
|
async onDiscoverNowClicked() {
|
|
82
|
-
await this.setUserModalState("newVersionPopup", "true", "Guido"), await this.setUserModalState("genericOnboarding", "true", "Guido")
|
|
103
|
+
this.start("genericOnboarding"), await this.setUserModalState("newVersionPopup", "true", "Guido"), await this.setUserModalState("genericOnboarding", "true", "Guido");
|
|
83
104
|
},
|
|
84
105
|
onRemindMeLater() {
|
|
85
106
|
sessionStorage.setItem("newVersionPopupDismissed", "true");
|
|
@@ -93,7 +114,7 @@ const t = () => ({
|
|
|
93
114
|
async fetchUserModalState() {
|
|
94
115
|
if (this.isFetched)
|
|
95
116
|
return;
|
|
96
|
-
const { fetchUserModalState: n } =
|
|
117
|
+
const { fetchUserModalState: n } = t();
|
|
97
118
|
try {
|
|
98
119
|
const i = await n();
|
|
99
120
|
this.userModalState = i, this.isFetched = !0;
|
|
@@ -101,11 +122,11 @@ const t = () => ({
|
|
|
101
122
|
}
|
|
102
123
|
},
|
|
103
124
|
async setUserModalState(n, i, o) {
|
|
104
|
-
const { setUserModalState:
|
|
105
|
-
await
|
|
125
|
+
const { setUserModalState: s } = t();
|
|
126
|
+
await s(n, i, o), this.isFetched = !1, await this.fetchUserModalState();
|
|
106
127
|
}
|
|
107
128
|
}
|
|
108
129
|
});
|
|
109
130
|
export {
|
|
110
|
-
|
|
131
|
+
g as useOnboardingStore
|
|
111
132
|
};
|
|
@@ -1,75 +1,78 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { formatToLiquidFilter as b, quoteArgument as y, liquidFilterToFormat as h } from "./liquidDynamicContent.js";
|
|
2
|
+
const g = (t) => {
|
|
3
|
+
if (!t.includes("="))
|
|
4
|
+
return null;
|
|
5
|
+
const [r, e] = t.split("=");
|
|
6
|
+
return { key: r.trim(), value: e.trim() };
|
|
7
|
+
}, c = "default:", f = (t) => {
|
|
8
|
+
if (!t.startsWith(c))
|
|
9
|
+
return t;
|
|
10
|
+
const r = t.slice(c.length).trim(), e = (l) => r.length >= 2 && r.startsWith(l) && r.endsWith(l);
|
|
11
|
+
return e('"') || e("'") ? r.slice(1, -1) : r;
|
|
12
|
+
}, k = (t) => {
|
|
13
|
+
const e = t.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((a) => a.trim()), [l] = e, s = {
|
|
14
|
+
text: t.label,
|
|
15
|
+
value: l || ""
|
|
5
16
|
};
|
|
6
|
-
if (
|
|
7
|
-
const [,
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
n ? r.format = n : l || (r.fallback = e), l && (r.fallback = l);
|
|
17
|
+
if (e.length >= 2) {
|
|
18
|
+
const [, a, n] = e;
|
|
19
|
+
if (a.startsWith(c))
|
|
20
|
+
s.fallback = f(a);
|
|
21
|
+
else {
|
|
22
|
+
const o = h(a) ?? g(a);
|
|
23
|
+
o ? s.format = o : n || (s.fallback = a), n && (s.fallback = f(n));
|
|
14
24
|
}
|
|
15
25
|
}
|
|
16
|
-
return
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
23
|
-
if (c) {
|
|
24
|
-
if (!t.fallback)
|
|
25
|
-
return {
|
|
26
|
-
label: t.text,
|
|
27
|
-
value: `{{ ${t.value} }}`
|
|
28
|
-
};
|
|
29
|
-
const r = !Number.isNaN(Number(t.fallback)) && t.fallback.trim() !== "" ? t.fallback : `"${t.fallback}"`;
|
|
30
|
-
return {
|
|
31
|
-
label: `${t.text} | ${t.fallback}`,
|
|
32
|
-
value: `{{ ${t.value} | default: ${r} }}`
|
|
33
|
-
};
|
|
34
|
-
}
|
|
26
|
+
return s;
|
|
27
|
+
}, p = (t) => {
|
|
28
|
+
const e = !Number.isNaN(Number(t)) && t.trim() !== "" ? t : y(t);
|
|
29
|
+
return e === null ? null : `${c} ${e}`;
|
|
30
|
+
}, v = (t) => {
|
|
31
|
+
const r = t.format ? b(t.format) : null, e = t.fallback ? p(t.fallback) : null, l = [t.value, r, e].filter(Boolean);
|
|
35
32
|
return {
|
|
36
|
-
label: t.
|
|
37
|
-
value:
|
|
33
|
+
label: [t.text, r, e && t.fallback].filter(Boolean).join(" | "),
|
|
34
|
+
value: `{{ ${l.join(" | ")} }}`
|
|
38
35
|
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
}, i = (t, r = !1) => t.map((e) => r ? v(e) : e.format ? {
|
|
37
|
+
label: `${e.text} | ${e.format.key}=${e.format.value}`,
|
|
38
|
+
value: `{{${e.value}|${e.format.key}=${e.format.value}}}`
|
|
39
|
+
} : {
|
|
40
|
+
label: e.fallback ? `${e.text} | ${e.fallback}` : e.text,
|
|
41
|
+
value: e.fallback ? `{{${e.value}|${e.fallback}}}` : `{{${e.value}}}`
|
|
42
|
+
}), $ = (t) => {
|
|
43
|
+
const r = [], e = /* @__PURE__ */ new Set(), l = (a) => {
|
|
44
|
+
Array.isArray(a) && a.forEach((n) => {
|
|
45
|
+
const o = [...n.children ?? [], ...n.select_items ?? []];
|
|
46
|
+
if (o.length > 0) {
|
|
47
|
+
l(o);
|
|
45
48
|
return;
|
|
46
49
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
50
|
+
const u = n.text || n.tag_text;
|
|
51
|
+
u && n.value && !e.has(n.value) && (e.add(n.value), r.push({ text: u, value: n.value }));
|
|
49
52
|
});
|
|
50
|
-
}, [
|
|
51
|
-
return s
|
|
52
|
-
},
|
|
53
|
-
const
|
|
53
|
+
}, [s] = Object.values(t ?? {});
|
|
54
|
+
return l(s), r;
|
|
55
|
+
}, d = (t, r, e = !1) => {
|
|
56
|
+
const l = new Set(t.map((a) => a.value)), s = r.filter((a) => l.has(a.value) ? !1 : (l.add(a.value), !0));
|
|
54
57
|
return [
|
|
55
|
-
...
|
|
56
|
-
...
|
|
58
|
+
...i(t, e),
|
|
59
|
+
...i(s, e)
|
|
57
60
|
];
|
|
58
|
-
},
|
|
59
|
-
var
|
|
60
|
-
return ((
|
|
61
|
-
},
|
|
62
|
-
if (
|
|
61
|
+
}, F = () => {
|
|
62
|
+
var t;
|
|
63
|
+
return ((t = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : t.getAttribute("content")) ?? "";
|
|
64
|
+
}, T = (t) => typeof t == "string" ? t : typeof t == "number" ? String(t) : "", x = (t) => {
|
|
65
|
+
if (t === null || typeof t != "object" || Array.isArray(t))
|
|
63
66
|
return !1;
|
|
64
|
-
const
|
|
65
|
-
return
|
|
67
|
+
const r = Object.getPrototypeOf(t);
|
|
68
|
+
return r === Object.prototype || r === null;
|
|
66
69
|
};
|
|
67
70
|
export {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
T as asText,
|
|
72
|
+
d as buildMergeTagEntries,
|
|
73
|
+
i as dynamicContentToMergeTags,
|
|
74
|
+
$ as flattenDynamicContentList,
|
|
75
|
+
F as getCsrfToken,
|
|
76
|
+
x as isPlainObject,
|
|
77
|
+
k as mergeTagToDynamicContent
|
|
75
78
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const E = "time-format", r = "date", u = new RegExp(`^${r}\\s*:\\s*(?:"([^"]*)"|'([^']*)')$`), s = /%[-_0^#]?\d*[a-zA-Z%]/, c = new RegExp(s, "g"), l = /\b(?:Y{2,4}|M{2,4}|D{1,4}|d{3,4}|H{2}|h{2}|m{2}|s{2}|S{1,3}|A|a)\b/, T = (t) => t.includes('"') ? t.includes("'") ? null : `'${t}'` : `"${t}"`, i = (t) => s.test(t) && !l.test(t.replace(c, "")), R = (t) => {
|
|
2
|
+
if (t.key !== E || !i(t.value ?? ""))
|
|
3
|
+
return null;
|
|
4
|
+
const n = T(t.value);
|
|
5
|
+
return n === null ? null : `${r}: ${n}`;
|
|
6
|
+
}, _ = (t) => {
|
|
7
|
+
const [, n, o] = t.match(u) ?? [], e = n ?? o;
|
|
8
|
+
return e ? { key: E, value: e } : null;
|
|
9
|
+
};
|
|
10
|
+
export {
|
|
11
|
+
E as TIME_FORMAT_KEY,
|
|
12
|
+
R as formatToLiquidFilter,
|
|
13
|
+
_ as liquidFilterToFormat,
|
|
14
|
+
T as quoteArgument
|
|
15
|
+
};
|