@designcrowd/library.brand-page 6.2.7 → 6.2.9
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/lib/src/{CreatedOnBrandCrowd-de-de-vzF6Ikn9.js → CreatedOnBrandCrowd-de-de-9uC6t5HU.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-cXu20Wxb.js → CreatedOnBrandCrowd-en-us-P6TzcklZ.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-PSfMEmIN.js → CreatedOnBrandCrowd-es-es-DimkGb1_.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CKSJaTW0.js → CreatedOnBrandCrowd-fr-ca-CL_iFuJw.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CKSJaTW0.js → CreatedOnBrandCrowd-fr-fr-CL_iFuJw.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-28G2T3DJ.js → CreatedOnBrandCrowd-pt-br-DSIjEoMv.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-28G2T3DJ.js → CreatedOnBrandCrowd-pt-pt-DSIjEoMv.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-CG2vQgBe.js → CreatedOnDcom-de-de-CKRvl9Ky.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-DzPaDxZd.js → CreatedOnDcom-en-us-ChplPDfS.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-BmN7lNDe.js → CreatedOnDcom-es-es-DCIXsW9X.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BarL0nmZ.js → CreatedOnDcom-fr-ca-lakt1nLU.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-e5Bk-c84.js → CreatedOnDcom-fr-fr-RsGK1y5g.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-89-1jjm5.js → CreatedOnDcom-pt-br-DyA4XodM.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-B9v9kExe.js → CreatedOnDcom-pt-pt-BK51dTyw.js} +1 -1
- package/lib/src/brand-page-maker/components/color-picker/BpColorPicker.stories.d.ts +3 -0
- package/lib/src/brand-page-maker/components/color-picker/BpColorPicker.stories.js +10 -0
- package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.d.ts +2 -2
- package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.js +2 -2
- package/lib/src/{bundled-translations-BNA5h0Dx.js → bundled-translations-zfiA5Tsw.js} +1 -1
- package/lib/src/{bundled-translations.de-DE-fyTHrRxT.js → bundled-translations.de-DE-ChsdSyAP.js} +13 -13
- package/lib/src/{bundled-translations.es-ES-BMmvJGGC.js → bundled-translations.es-ES-DflsWQK0.js} +17 -17
- package/lib/src/{bundled-translations.fr-CA-Bo69L_BP.js → bundled-translations.fr-CA-fpDRuZ52.js} +1 -1
- package/lib/src/{bundled-translations.fr-FR-C4yTVFOW.js → bundled-translations.fr-FR-Bub73Zt-.js} +17 -17
- package/lib/src/{bundled-translations.pt-BR-CPMPfny0.js → bundled-translations.pt-BR-BlnWE9TB.js} +13 -13
- package/lib/src/{bundled-translations.pt-PT-C6ZwYs37.js → bundled-translations.pt-PT-DmzXlnaS.js} +30 -30
- package/lib/src/bundles/bundled-translations.de-DE.json +7 -1
- package/lib/src/bundles/bundled-translations.es-ES.json +7 -1
- package/lib/src/bundles/bundled-translations.fr-CA.json +7 -1
- package/lib/src/bundles/bundled-translations.fr-FR.json +7 -1
- package/lib/src/bundles/bundled-translations.json +7 -1
- package/lib/src/bundles/bundled-translations.pt-BR.json +7 -1
- package/lib/src/bundles/bundled-translations.pt-PT.json +7 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +17 -10
- package/lib/src/css/library.brand-page-brandPage.min.css +18 -10
- package/lib/src/css/library.brand-page-designCom.min.css +17 -10
- package/lib/src/css/library.brand-page-preview.min.css +17 -10
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-BTgw6Jw7.js → lib-Ca7GMpcR.js} +11192 -11134
- package/package.json +4 -3
- package/src/brand-page-maker/components/action-bar/ActionBarNavigation.test.ts +31 -0
- package/src/brand-page-maker/components/action-bar/ActionBarNavigation.vue +1 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.navigation-slot.test.ts +58 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +5 -1
- package/src/brand-page-maker/components/color-picker/BpColorPicker.stories.ts +10 -0
- package/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.ts +2 -2
- package/src/brand-page-maker/components/color-picker/components/ColorModeSelect.test.ts +116 -0
- package/src/brand-page-maker/components/color-picker/components/ColorModeSelect.vue +7 -1
- package/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.test.ts +157 -0
- package/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.vue +10 -4
- package/src/brand-page-maker/components/navigation/Navigation.vue +6 -2
- package/src/bundles/bundled-translations.de-DE.json +7 -1
- package/src/bundles/bundled-translations.es-ES.json +7 -1
- package/src/bundles/bundled-translations.fr-CA.json +7 -1
- package/src/bundles/bundled-translations.fr-FR.json +7 -1
- package/src/bundles/bundled-translations.json +7 -1
- package/src/bundles/bundled-translations.pt-BR.json +7 -1
- package/src/bundles/bundled-translations.pt-PT.json +7 -1
- package/src/shared/color-picker/components/i18n/color-picker.de-DE.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.es-ES.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.fr-CA.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.fr-FR.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.pt-BR.json +8 -1
- package/src/shared/color-picker/components/i18n/color-picker.pt-PT.json +8 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@designcrowd/library.brand-page",
|
|
3
3
|
"description": "A collection of Maker/Designer applications",
|
|
4
|
-
"version": "6.2.
|
|
4
|
+
"version": "6.2.9",
|
|
5
5
|
"author": "Design.com Eng",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"type": "module",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"scripts": {
|
|
30
30
|
"dev": "export NODE_TLS_REJECT_UNAUTHORIZED=0 && nuxt dev nuxtapp",
|
|
31
31
|
"dev:dcom": "export tailwindTheme=designCom && nuxt dev nuxtapp",
|
|
32
|
-
"docker:publish": "docker build -t bp-maker:latest . --file ./build/Dockerfile.brand-page-lib-publish --
|
|
32
|
+
"docker:publish": "DOCKER_BUILDKIT=1 docker build -t bp-maker:latest . --file ./build/Dockerfile.brand-page-lib-publish --no-cache --secret id=npm,env=NPM_TOKEN --secret id=codeartifact,env=CODEARTIFACT_AUTH_TOKEN",
|
|
33
33
|
"lint": "eslint . && tsc --project tsconfig.lint.json --noEmit",
|
|
34
34
|
"lint:fix": "eslint --fix .",
|
|
35
35
|
"build:bp": "npm run clean:vite && npm run clean:lib && NODE_ENV=production npm run build:bp:vite && npm run build:bp:typings && npm run copy:css",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"clean:vite": "rimraf ./node_modules/.cache",
|
|
48
48
|
"copy:css": "copyfiles -fF ./public/css/global.css ./public/css/reset.css ./lib/src/css/",
|
|
49
49
|
"test": "vitest run",
|
|
50
|
+
"test:publish-dual-registry": "bash ./build/publish-dual-registry.test.sh",
|
|
50
51
|
"test:watch": "vitest watch",
|
|
51
52
|
"coverage": "echo \"To be migrated to vitest\"",
|
|
52
53
|
"storybook": "npm run clean:vite && npm run storybook:css && npm run storybook:themes && npm run storybook:start",
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
66
|
"@ckpack/vue-color": "1.6.0",
|
|
66
|
-
"@designcrowd/fe-shared-lib": "2.1.
|
|
67
|
+
"@designcrowd/fe-shared-lib": "2.1.3",
|
|
67
68
|
"@pinia/nuxt": "0.11.3",
|
|
68
69
|
"@storybook/react": "9.0.4",
|
|
69
70
|
"@tiptap/extension-bubble-menu": "3.28.0",
|
|
@@ -52,3 +52,34 @@ describe('ActionBarNavigation — Preview button', () => {
|
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
|
+
|
|
56
|
+
describe('ActionBarNavigation — navigationActionsStart slot', () => {
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
setActivePinia(createPinia());
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('renders host content ahead of Preview', () => {
|
|
62
|
+
const wrapper = shallowMount(ActionBarNavigation, {
|
|
63
|
+
slots: { navigationActionsStart: '<span data-test-host-action />' },
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const [first, second] = wrapper.element.children;
|
|
67
|
+
|
|
68
|
+
expect(first.hasAttribute('data-test-host-action')).toBe(true);
|
|
69
|
+
expect(second.hasAttribute('data-test-preview-button')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// The row is a flex row with gaps, so an extra element — even an empty one — would
|
|
73
|
+
// shift every button for hosts that don't use the slot.
|
|
74
|
+
test('adds nothing to the row when the host leaves it empty', () => {
|
|
75
|
+
const wrapper = mountBar();
|
|
76
|
+
const buttons = wrapper.findAllComponents({ name: 'Button' });
|
|
77
|
+
|
|
78
|
+
expect(wrapper.element.children).toHaveLength(buttons.length);
|
|
79
|
+
expect(
|
|
80
|
+
wrapper.element.firstElementChild?.hasAttribute(
|
|
81
|
+
'data-test-preview-button',
|
|
82
|
+
),
|
|
83
|
+
).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
data-component="action-bar-navigation"
|
|
4
4
|
class="tw-flex tw-items-center tw-border-t tw-border-solid tw-border-grayscale-600 tw-h-12 tw-px-2 lg:tw-px-0 lg:tw-h-auto lg:tw-border-none tw-gap-3 lg:tw-gap-5 tw-w-full lg:tw-justify-end tw-box-border"
|
|
5
5
|
>
|
|
6
|
+
<slot name="navigationActionsStart" />
|
|
6
7
|
<Button
|
|
7
8
|
v-if="!isAdminMaker"
|
|
8
9
|
:label="constantsTr('previewDisplayName')"
|
package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.navigation-slot.test.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
3
|
+
import { shallowMount } from '@vue/test-utils';
|
|
4
|
+
import BrandPageMaker from './BrandPageMaker.vue';
|
|
5
|
+
import BrandPageMakerMixin from './BrandPageMaker.mixin';
|
|
6
|
+
|
|
7
|
+
// The mixin's lifecycle boots the whole editor, which the header's slot plumbing doesn't
|
|
8
|
+
// need; without it the real header templates mount on their own.
|
|
9
|
+
const HeaderOnlyBrandPageMaker = {
|
|
10
|
+
...BrandPageMaker,
|
|
11
|
+
mixins: [
|
|
12
|
+
{
|
|
13
|
+
...BrandPageMakerMixin,
|
|
14
|
+
created: undefined,
|
|
15
|
+
mounted: undefined,
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const mountMaker = (slots: Record<string, string> = {}) =>
|
|
21
|
+
shallowMount(HeaderOnlyBrandPageMaker, {
|
|
22
|
+
props: { viewModel: {} },
|
|
23
|
+
slots,
|
|
24
|
+
global: {
|
|
25
|
+
stubs: { MakerNavigation: false, ActionBarNavigation: false },
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const actionRow = (wrapper: ReturnType<typeof mountMaker>): Element =>
|
|
30
|
+
wrapper.get('[data-component="action-bar-navigation"]').element;
|
|
31
|
+
|
|
32
|
+
describe('BrandPageMaker — navigationActionsStart slot', () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
setActivePinia(createPinia());
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('forwards host content into the header action row, ahead of Preview', () => {
|
|
38
|
+
const wrapper = mountMaker({
|
|
39
|
+
navigationActionsStart: '<span data-test-host-action />',
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const [first, second] = actionRow(wrapper).children;
|
|
43
|
+
|
|
44
|
+
expect(first.hasAttribute('data-test-host-action')).toBe(true);
|
|
45
|
+
expect(second.hasAttribute('data-test-preview-button')).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('leaves the action row untouched when the host provides nothing', () => {
|
|
49
|
+
const wrapper = mountMaker();
|
|
50
|
+
|
|
51
|
+
expect(wrapper.find('[data-test-host-action]').exists()).toBe(false);
|
|
52
|
+
expect(
|
|
53
|
+
actionRow(wrapper).firstElementChild?.hasAttribute(
|
|
54
|
+
'data-test-preview-button',
|
|
55
|
+
),
|
|
56
|
+
).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
@publish="saveAndPublishBrandPage(false)"
|
|
18
18
|
@preview="onPreview"
|
|
19
19
|
@create-team-cards="onCreateTeamCards"
|
|
20
|
-
|
|
20
|
+
>
|
|
21
|
+
<template v-if="$slots.navigationActionsStart" #navigationActionsStart>
|
|
22
|
+
<slot name="navigationActionsStart" />
|
|
23
|
+
</template>
|
|
24
|
+
</MakerNavigation>
|
|
21
25
|
<slot name="editButtonHeader" />
|
|
22
26
|
<div
|
|
23
27
|
class="c-brand-page-maker tw-flex tw-flex-col lg:tw-flex-row tw-box-border"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineComponent } from 'vue';
|
|
2
|
+
import { setLocaleAsync } from '@src/composables/useTranslate';
|
|
2
3
|
import ColorPickerV2 from './BpColorPickerV2.vue';
|
|
3
4
|
import ColorModeSelect from './components/ColorModeSelect.vue';
|
|
4
5
|
import GradientTypeSelector from './components/GradientTypeSelector.vue';
|
|
@@ -7,6 +8,15 @@ import GradientColorSlider from './components/GradientColorSlider.vue';
|
|
|
7
8
|
export default {
|
|
8
9
|
title: 'Components/BpColorPicker',
|
|
9
10
|
component: ColorPickerV2,
|
|
11
|
+
// All of this file's stories render labels looked up via colorPickerTr; with
|
|
12
|
+
// i18next 25, t() returns undefined before setLocaleAsync runs. A meta-level
|
|
13
|
+
// loader awaits it once for every story, including BpColorPickerV2Sample's
|
|
14
|
+
// ColorModeSelect/GradientTypeSelector rendered inside the popup.
|
|
15
|
+
loaders: [
|
|
16
|
+
async ({ globals }) => {
|
|
17
|
+
await setLocaleAsync(globals.locale);
|
|
18
|
+
},
|
|
19
|
+
],
|
|
10
20
|
};
|
|
11
21
|
|
|
12
22
|
export const ColorModeSelectComponent = () => {
|
|
@@ -7,11 +7,11 @@ export const COLOR_PICKER_MODE = {
|
|
|
7
7
|
|
|
8
8
|
export const COLOR_PICKER_MODE_OPTIONS = [
|
|
9
9
|
{
|
|
10
|
-
|
|
10
|
+
labelKey: 'colorModeSolid',
|
|
11
11
|
value: COLOR_PICKER_MODE.SOLID,
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
|
|
14
|
+
labelKey: 'colorModeGradient',
|
|
15
15
|
value: COLOR_PICKER_MODE.GRADIENT,
|
|
16
16
|
},
|
|
17
17
|
];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import i18next from 'i18next';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
setLocaleAsync,
|
|
6
|
+
supportedLocales,
|
|
7
|
+
type LocaleTypes,
|
|
8
|
+
} from '@src/composables/useTranslate';
|
|
9
|
+
import ColorModeSelect from './ColorModeSelect.vue';
|
|
10
|
+
import en from '@src/shared/color-picker/components/i18n/color-picker.json';
|
|
11
|
+
import deDE from '@src/shared/color-picker/components/i18n/color-picker.de-DE.json';
|
|
12
|
+
import esES from '@src/shared/color-picker/components/i18n/color-picker.es-ES.json';
|
|
13
|
+
import frCA from '@src/shared/color-picker/components/i18n/color-picker.fr-CA.json';
|
|
14
|
+
import frFR from '@src/shared/color-picker/components/i18n/color-picker.fr-FR.json';
|
|
15
|
+
import ptBR from '@src/shared/color-picker/components/i18n/color-picker.pt-BR.json';
|
|
16
|
+
import ptPT from '@src/shared/color-picker/components/i18n/color-picker.pt-PT.json';
|
|
17
|
+
|
|
18
|
+
// Expected values come from the locale files, not literals, so Smartling's
|
|
19
|
+
// rewrite of the wording can't turn these tests red.
|
|
20
|
+
const localeFiles: Record<LocaleTypes, typeof en> = {
|
|
21
|
+
'en-US': en,
|
|
22
|
+
'de-DE': deDE,
|
|
23
|
+
'es-ES': esES,
|
|
24
|
+
'fr-CA': frCA,
|
|
25
|
+
'fr-FR': frFR,
|
|
26
|
+
'pt-BR': ptBR,
|
|
27
|
+
'pt-PT': ptPT,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const stringsFor = (locale: LocaleTypes): (typeof en)['colorPicker'] =>
|
|
31
|
+
localeFiles[locale].colorPicker;
|
|
32
|
+
|
|
33
|
+
const NON_ENGLISH_LOCALES = supportedLocales.filter(
|
|
34
|
+
(locale) => locale !== 'en-US',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// See RecaptchaDisclosure.vue.test.ts: the shared i18next singleton only takes
|
|
38
|
+
// the language from `setLocaleAsync` on its first call.
|
|
39
|
+
const useLocale = async (locale: string): Promise<void> => {
|
|
40
|
+
await setLocaleAsync(locale as LocaleTypes);
|
|
41
|
+
await i18next.changeLanguage(locale);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const optionTexts = (wrapper: ReturnType<typeof mount>): string[] =>
|
|
45
|
+
wrapper.findAll('option').map((option) => option.text());
|
|
46
|
+
|
|
47
|
+
const mountSelect = (modelValue?: string): ReturnType<typeof mount> =>
|
|
48
|
+
mount(ColorModeSelect, { props: { modelValue } });
|
|
49
|
+
|
|
50
|
+
describe('ColorModeSelect', () => {
|
|
51
|
+
test.each(NON_ENGLISH_LOCALES)(
|
|
52
|
+
'dropdown options use the %s locale file',
|
|
53
|
+
async (locale) => {
|
|
54
|
+
await useLocale(locale);
|
|
55
|
+
|
|
56
|
+
const wrapper = mountSelect();
|
|
57
|
+
|
|
58
|
+
expect(optionTexts(wrapper)).toEqual([
|
|
59
|
+
stringsFor(locale).colorModeSolid,
|
|
60
|
+
stringsFor(locale).colorModeGradient,
|
|
61
|
+
]);
|
|
62
|
+
optionTexts(wrapper).forEach((text) => {
|
|
63
|
+
expect(text).not.toMatch(/^colorPicker\./);
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
test('English dropdown options read word for word', async () => {
|
|
69
|
+
await useLocale('en-US');
|
|
70
|
+
|
|
71
|
+
const wrapper = mountSelect();
|
|
72
|
+
|
|
73
|
+
expect(optionTexts(wrapper)).toEqual(['Solid Color', 'Gradient Color']);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// A key missing from one locale file renders as its key path on the site;
|
|
77
|
+
// the shared test singleton would hide it behind the en-US fallback.
|
|
78
|
+
test.each(supportedLocales)(
|
|
79
|
+
'every locale file defines the colour-mode keys: %s',
|
|
80
|
+
(locale) => {
|
|
81
|
+
(['colorModeSolid', 'colorModeGradient'] as const).forEach((key) => {
|
|
82
|
+
const value = stringsFor(locale)[key];
|
|
83
|
+
|
|
84
|
+
expect(typeof value, `${locale} › ${key}`).toBe('string');
|
|
85
|
+
expect(value.trim(), `${locale} › ${key}`).not.toBe('');
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
test('a gradient colour opens on the translated gradient option', async () => {
|
|
91
|
+
await useLocale('de-DE');
|
|
92
|
+
|
|
93
|
+
const wrapper = mountSelect('gradient');
|
|
94
|
+
const select = wrapper.find('select');
|
|
95
|
+
|
|
96
|
+
expect((select.element as HTMLSelectElement).value).toBe('gradient');
|
|
97
|
+
expect(wrapper.find('option:checked').text()).toBe(
|
|
98
|
+
stringsFor('de-DE').colorModeGradient,
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('picking an option emits the same value as today', async () => {
|
|
103
|
+
await useLocale('de-DE');
|
|
104
|
+
|
|
105
|
+
const wrapper = mountSelect('solid');
|
|
106
|
+
const select = wrapper.find('select');
|
|
107
|
+
|
|
108
|
+
await select.setValue('gradient');
|
|
109
|
+
await select.setValue('solid');
|
|
110
|
+
|
|
111
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([
|
|
112
|
+
['gradient'],
|
|
113
|
+
['solid'],
|
|
114
|
+
]);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -10,15 +10,21 @@
|
|
|
10
10
|
:key="index"
|
|
11
11
|
:value="mode.value"
|
|
12
12
|
>
|
|
13
|
-
{{ mode.
|
|
13
|
+
{{ colorPickerTr(mode.labelKey) }}
|
|
14
14
|
</option>
|
|
15
15
|
</select>
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script>
|
|
19
19
|
import ColorModeSelectMixin from './ColorModeSelect.mixin';
|
|
20
|
+
import { colorPickerTr } from '@src/composables/useTranslate';
|
|
20
21
|
|
|
21
22
|
export default {
|
|
22
23
|
mixins: [ColorModeSelectMixin],
|
|
24
|
+
setup() {
|
|
25
|
+
return {
|
|
26
|
+
colorPickerTr,
|
|
27
|
+
};
|
|
28
|
+
},
|
|
23
29
|
};
|
|
24
30
|
</script>
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import i18next from 'i18next';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
setLocaleAsync,
|
|
6
|
+
supportedLocales,
|
|
7
|
+
type LocaleTypes,
|
|
8
|
+
} from '@src/composables/useTranslate';
|
|
9
|
+
import GradientTypeSelector from './GradientTypeSelector.vue';
|
|
10
|
+
import en from '@src/shared/color-picker/components/i18n/color-picker.json';
|
|
11
|
+
import deDE from '@src/shared/color-picker/components/i18n/color-picker.de-DE.json';
|
|
12
|
+
import esES from '@src/shared/color-picker/components/i18n/color-picker.es-ES.json';
|
|
13
|
+
import frCA from '@src/shared/color-picker/components/i18n/color-picker.fr-CA.json';
|
|
14
|
+
import frFR from '@src/shared/color-picker/components/i18n/color-picker.fr-FR.json';
|
|
15
|
+
import ptBR from '@src/shared/color-picker/components/i18n/color-picker.pt-BR.json';
|
|
16
|
+
import ptPT from '@src/shared/color-picker/components/i18n/color-picker.pt-PT.json';
|
|
17
|
+
|
|
18
|
+
// Expected values come from the locale files, not literals, so Smartling's
|
|
19
|
+
// rewrite of the wording can't turn these tests red.
|
|
20
|
+
const localeFiles: Record<LocaleTypes, typeof en> = {
|
|
21
|
+
'en-US': en,
|
|
22
|
+
'de-DE': deDE,
|
|
23
|
+
'es-ES': esES,
|
|
24
|
+
'fr-CA': frCA,
|
|
25
|
+
'fr-FR': frFR,
|
|
26
|
+
'pt-BR': ptBR,
|
|
27
|
+
'pt-PT': ptPT,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const stringsFor = (locale: LocaleTypes): (typeof en)['colorPicker'] =>
|
|
31
|
+
localeFiles[locale].colorPicker;
|
|
32
|
+
|
|
33
|
+
const NON_ENGLISH_LOCALES = supportedLocales.filter(
|
|
34
|
+
(locale) => locale !== 'en-US',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// See RecaptchaDisclosure.vue.test.ts: the shared i18next singleton only takes
|
|
38
|
+
// the language from `setLocaleAsync` on its first call.
|
|
39
|
+
const useLocale = async (locale: string): Promise<void> => {
|
|
40
|
+
await setLocaleAsync(locale as LocaleTypes);
|
|
41
|
+
await i18next.changeLanguage(locale);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const buttons = (
|
|
45
|
+
wrapper: ReturnType<typeof mount>,
|
|
46
|
+
): ReturnType<ReturnType<typeof mount>['findAll']> =>
|
|
47
|
+
wrapper.findAll('.gradient-color-switch-button');
|
|
48
|
+
|
|
49
|
+
const mountSelector = (modelValue?: string): ReturnType<typeof mount> =>
|
|
50
|
+
mount(GradientTypeSelector, { props: { modelValue } });
|
|
51
|
+
|
|
52
|
+
describe('GradientTypeSelector', () => {
|
|
53
|
+
test.each(NON_ENGLISH_LOCALES)(
|
|
54
|
+
'gradient buttons and hints use the %s locale file',
|
|
55
|
+
async (locale) => {
|
|
56
|
+
await useLocale(locale);
|
|
57
|
+
|
|
58
|
+
const wrapper = mountSelector();
|
|
59
|
+
const [linear, radial] = buttons(wrapper);
|
|
60
|
+
|
|
61
|
+
expect(linear.text()).toBe(stringsFor(locale).gradientTypeLinear);
|
|
62
|
+
expect(radial.text()).toBe(stringsFor(locale).gradientTypeRadial);
|
|
63
|
+
expect(linear.attributes('title')).toBe(
|
|
64
|
+
stringsFor(locale).gradientTypeLinearTitle,
|
|
65
|
+
);
|
|
66
|
+
expect(radial.attributes('title')).toBe(
|
|
67
|
+
stringsFor(locale).gradientTypeRadialTitle,
|
|
68
|
+
);
|
|
69
|
+
[linear.text(), radial.text()].forEach((text) => {
|
|
70
|
+
expect(text).not.toMatch(/^colorPicker\./);
|
|
71
|
+
});
|
|
72
|
+
expect(linear.classes()).toContain('gradient-color-switch-button');
|
|
73
|
+
expect(radial.classes()).toContain('gradient-color-switch-button');
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
test('English gradient buttons and hints read word for word', async () => {
|
|
78
|
+
await useLocale('en-US');
|
|
79
|
+
|
|
80
|
+
const wrapper = mountSelector();
|
|
81
|
+
const [linear, radial] = buttons(wrapper);
|
|
82
|
+
|
|
83
|
+
expect(linear.text()).toBe('Linear');
|
|
84
|
+
expect(radial.text()).toBe('Radial');
|
|
85
|
+
expect(linear.attributes('title')).toBe('Linear Gradient Color');
|
|
86
|
+
expect(radial.attributes('title')).toBe('Radial Gradient Color');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// A key missing from one locale file renders as its key path on the site;
|
|
90
|
+
// the shared test singleton would hide it behind the en-US fallback.
|
|
91
|
+
test.each(supportedLocales)(
|
|
92
|
+
'every locale file defines the gradient-type keys: %s',
|
|
93
|
+
(locale) => {
|
|
94
|
+
(
|
|
95
|
+
[
|
|
96
|
+
'gradientTypeLinear',
|
|
97
|
+
'gradientTypeRadial',
|
|
98
|
+
'gradientTypeLinearTitle',
|
|
99
|
+
'gradientTypeRadialTitle',
|
|
100
|
+
] as const
|
|
101
|
+
).forEach((key) => {
|
|
102
|
+
const value = stringsFor(locale)[key];
|
|
103
|
+
|
|
104
|
+
expect(typeof value, `${locale} › ${key}`).toBe('string');
|
|
105
|
+
expect(value.trim(), `${locale} › ${key}`).not.toBe('');
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
test('clicking a gradient button emits the same value as today', async () => {
|
|
111
|
+
await useLocale('de-DE');
|
|
112
|
+
|
|
113
|
+
const wrapper = mountSelector('linear');
|
|
114
|
+
const [, radial] = buttons(wrapper);
|
|
115
|
+
|
|
116
|
+
await radial.trigger('click');
|
|
117
|
+
|
|
118
|
+
const [linear] = buttons(wrapper);
|
|
119
|
+
|
|
120
|
+
await linear.trigger('click');
|
|
121
|
+
|
|
122
|
+
expect(wrapper.emitted('update:modelValue')).toEqual([
|
|
123
|
+
['radial'],
|
|
124
|
+
['linear'],
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// gradientTypeRadial is "Radial" in every locale file, so a literal
|
|
129
|
+
// <span>Radial</span> would also pass the assertions above. Override the
|
|
130
|
+
// resource at runtime to prove the label is actually looked up.
|
|
131
|
+
test('the radial label is looked up, not hard-coded', async () => {
|
|
132
|
+
await useLocale('de-DE');
|
|
133
|
+
|
|
134
|
+
const original = stringsFor('de-DE').gradientTypeRadial;
|
|
135
|
+
|
|
136
|
+
i18next.addResource(
|
|
137
|
+
'de-DE',
|
|
138
|
+
'bp',
|
|
139
|
+
'colorPicker.gradientTypeRadial',
|
|
140
|
+
'probe-radial',
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const wrapper = mountSelector();
|
|
145
|
+
const [, radial] = buttons(wrapper);
|
|
146
|
+
|
|
147
|
+
expect(radial.text()).toBe('probe-radial');
|
|
148
|
+
} finally {
|
|
149
|
+
i18next.addResource(
|
|
150
|
+
'de-DE',
|
|
151
|
+
'bp',
|
|
152
|
+
'colorPicker.gradientTypeRadial',
|
|
153
|
+
original,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
class="tw-flex tw-border-2 tw-border-solid tw-border-secondary-500 tw-rounded"
|
|
5
5
|
>
|
|
6
6
|
<button
|
|
7
|
-
title="
|
|
7
|
+
:title="colorPickerTr('gradientTypeLinearTitle')"
|
|
8
8
|
class="gradient-color-switch-button"
|
|
9
9
|
:class="{
|
|
10
10
|
'gradient-color-switch-button_is-on': isLinear,
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
}"
|
|
13
13
|
@click.stop="onGradientTypeClick('linear')"
|
|
14
14
|
>
|
|
15
|
-
<span>
|
|
15
|
+
<span>{{ colorPickerTr('gradientTypeLinear') }}</span>
|
|
16
16
|
</button>
|
|
17
17
|
<button
|
|
18
|
-
title="
|
|
18
|
+
:title="colorPickerTr('gradientTypeRadialTitle')"
|
|
19
19
|
class="gradient-color-switch-button"
|
|
20
20
|
:class="{
|
|
21
21
|
'gradient-color-switch-button_is-on': isRadial,
|
|
@@ -23,16 +23,22 @@
|
|
|
23
23
|
}"
|
|
24
24
|
@click.stop="onGradientTypeClick('radial')"
|
|
25
25
|
>
|
|
26
|
-
<span>
|
|
26
|
+
<span>{{ colorPickerTr('gradientTypeRadial') }}</span>
|
|
27
27
|
</button>
|
|
28
28
|
</div>
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
31
|
<script>
|
|
32
32
|
import GradientTypeSelectorMixin from './GradientTypeSelector.mixin';
|
|
33
|
+
import { colorPickerTr } from '@src/composables/useTranslate';
|
|
33
34
|
|
|
34
35
|
export default {
|
|
35
36
|
mixins: [GradientTypeSelectorMixin],
|
|
37
|
+
setup() {
|
|
38
|
+
return {
|
|
39
|
+
colorPickerTr,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
36
42
|
};
|
|
37
43
|
</script>
|
|
38
44
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<header
|
|
3
3
|
data-component="navigation"
|
|
4
|
-
class="js-bp-header tw-h-24 lg:tw-h-16 tw-box-border lg:tw-py-4 lg:tw-px-5 tw-z-30 tw-fixed tw-w-full lg:tw-relative"
|
|
4
|
+
class="js-bp-header tw-h-24 lg:tw-h-16 tw-box-border lg:tw-py-4 lg:tw-px-5 tw-z-30 lg:tw-z-40 tw-fixed tw-w-full lg:tw-relative"
|
|
5
5
|
:class="{
|
|
6
6
|
'tw-bg-grayscale-800': !isAdminMaker,
|
|
7
7
|
}"
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
@publish="saveAndPublishBrandPage"
|
|
37
37
|
@preview="previewBrandPage"
|
|
38
38
|
@create-team-cards="onCreateTeamCards"
|
|
39
|
-
|
|
39
|
+
>
|
|
40
|
+
<template v-if="$slots.navigationActionsStart" #navigationActionsStart>
|
|
41
|
+
<slot name="navigationActionsStart" />
|
|
42
|
+
</template>
|
|
43
|
+
</ActionBarNavigation>
|
|
40
44
|
</div>
|
|
41
45
|
</header>
|
|
42
46
|
</template>
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Neue Farbe",
|
|
1333
1333
|
"defaultColors": "Standardfarben",
|
|
1334
1334
|
"gradientColors": "Verlaufsfarben",
|
|
1335
|
-
"selectThisColor": "Diese Farbe auswählen"
|
|
1335
|
+
"selectThisColor": "Diese Farbe auswählen",
|
|
1336
|
+
"colorModeSolid": "Volltonfarbe",
|
|
1337
|
+
"colorModeGradient": "Farbverlauf",
|
|
1338
|
+
"gradientTypeLinear": "Linear",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Linearer Farbverlauf",
|
|
1341
|
+
"gradientTypeRadialTitle": "Radialer Farbverlauf"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "Desktop",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Nuevo color",
|
|
1333
1333
|
"defaultColors": "Colores predeterminados",
|
|
1334
1334
|
"gradientColors": "Colores en degradado",
|
|
1335
|
-
"selectThisColor": "Selecciona este color"
|
|
1335
|
+
"selectThisColor": "Selecciona este color",
|
|
1336
|
+
"colorModeSolid": "Color sólido",
|
|
1337
|
+
"colorModeGradient": "Degradado",
|
|
1338
|
+
"gradientTypeLinear": "Lineal",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Degradado lineal",
|
|
1341
|
+
"gradientTypeRadialTitle": "Degradado radial"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "ESCRITORIO",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Nouvelle couleur",
|
|
1333
1333
|
"defaultColors": "Couleurs par défaut",
|
|
1334
1334
|
"gradientColors": "Dégradés de couleurs",
|
|
1335
|
-
"selectThisColor": "Sélectionner cette couleur"
|
|
1335
|
+
"selectThisColor": "Sélectionner cette couleur",
|
|
1336
|
+
"colorModeSolid": "Couleur unie",
|
|
1337
|
+
"colorModeGradient": "Dégradé",
|
|
1338
|
+
"gradientTypeLinear": "Linéaire",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Dégradé linéaire",
|
|
1341
|
+
"gradientTypeRadialTitle": "Dégradé radial"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "Ordinateur",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Nouvelle couleur",
|
|
1333
1333
|
"defaultColors": "Couleurs par défaut",
|
|
1334
1334
|
"gradientColors": "Dégradés de couleurs",
|
|
1335
|
-
"selectThisColor": "Sélectionner cette couleur"
|
|
1335
|
+
"selectThisColor": "Sélectionner cette couleur",
|
|
1336
|
+
"colorModeSolid": "Couleur unie",
|
|
1337
|
+
"colorModeGradient": "Dégradé",
|
|
1338
|
+
"gradientTypeLinear": "Linéaire",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Dégradé linéaire",
|
|
1341
|
+
"gradientTypeRadialTitle": "Dégradé radial"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "Ordinateur",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "New Color",
|
|
1333
1333
|
"defaultColors": "Default Colors",
|
|
1334
1334
|
"gradientColors": "Gradient Colors",
|
|
1335
|
-
"selectThisColor": "Select this color"
|
|
1335
|
+
"selectThisColor": "Select this color",
|
|
1336
|
+
"colorModeSolid": "Solid Color",
|
|
1337
|
+
"colorModeGradient": "Gradient Color",
|
|
1338
|
+
"gradientTypeLinear": "Linear",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Linear Gradient Color",
|
|
1341
|
+
"gradientTypeRadialTitle": "Radial Gradient Color"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "desktop",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Nova cor",
|
|
1333
1333
|
"defaultColors": "Cores padrão",
|
|
1334
1334
|
"gradientColors": "Gradientes de cores",
|
|
1335
|
-
"selectThisColor": "Selecione esta cor"
|
|
1335
|
+
"selectThisColor": "Selecione esta cor",
|
|
1336
|
+
"colorModeSolid": "Cor sólida",
|
|
1337
|
+
"colorModeGradient": "Gradiente",
|
|
1338
|
+
"gradientTypeLinear": "Linear",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Gradiente linear",
|
|
1341
|
+
"gradientTypeRadialTitle": "Gradiente radial"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "área de trabalho",
|
|
@@ -1332,7 +1332,13 @@
|
|
|
1332
1332
|
"newColor": "Nova cor",
|
|
1333
1333
|
"defaultColors": "Cores padrão",
|
|
1334
1334
|
"gradientColors": "Gradientes de cores",
|
|
1335
|
-
"selectThisColor": "Selecione esta cor"
|
|
1335
|
+
"selectThisColor": "Selecione esta cor",
|
|
1336
|
+
"colorModeSolid": "Cor sólida",
|
|
1337
|
+
"colorModeGradient": "Gradiente",
|
|
1338
|
+
"gradientTypeLinear": "Linear",
|
|
1339
|
+
"gradientTypeRadial": "Radial",
|
|
1340
|
+
"gradientTypeLinearTitle": "Gradiente linear",
|
|
1341
|
+
"gradientTypeRadialTitle": "Gradiente radial"
|
|
1336
1342
|
},
|
|
1337
1343
|
"common": {
|
|
1338
1344
|
"desktop": "computador",
|