Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEXT-38863 - implement new text editor component #377

Merged
merged 9 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/wise-melons-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@shopware-ag/meteor-component-library": major
---

# Add new Text Editor component

This change introduces a new Text Editor component to the Meteor Component Library.

# Updated i18n configuration

We change the 'legacy' mode of i18n to 'false' in the Meteor Component Library configuration to use the new i18n composable.
1 change: 1 addition & 0 deletions packages/component-library/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import "@shopware-ag/meteor-tokens/administration/dark.css";

const i18n = createI18n({
// something vue-i18n options here ...
legacy: false,
jleifeld marked this conversation as resolved.
Show resolved Hide resolved
globalInjection: true,
locale: "en",
fallbackLocale: "en",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 24 additions & 3 deletions packages/component-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,46 @@
"test:storybook": "test-storybook"
},
"dependencies": {
"@codemirror/lang-html": "^6.4.9",
"@floating-ui/dom": "^1.4.3",
"@floating-ui/vue": "^1.1.5",
"@shopware-ag/meteor-icon-kit": "workspace:*",
"@shopware-ag/meteor-tokens": "workspace:*",
"@storybook/addon-a11y": "^8.4.5",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/vue": "^8.1.0",
"@tiptap/extension-bubble-menu": "^2.10.0",
"@tiptap/extension-bullet-list": "^2.10.0",
"@tiptap/extension-character-count": "^2.10.0",
"@tiptap/extension-color": "^2.9.1",
"@tiptap/extension-highlight": "^2.10.3",
"@tiptap/extension-link": "^2.10.0",
"@tiptap/extension-list-item": "^2.10.0",
"@tiptap/extension-ordered-list": "^2.10.0",
"@tiptap/extension-placeholder": "^2.10.4",
"@tiptap/extension-subscript": "^2.9.1",
"@tiptap/extension-superscript": "^2.9.1",
"@tiptap/extension-table": "^2.10.3",
"@tiptap/extension-table-cell": "^2.10.3",
"@tiptap/extension-table-header": "^2.10.3",
"@tiptap/extension-table-row": "^2.10.3",
"@tiptap/extension-text-align": "^2.9.1",
"@tiptap/extension-text-style": "^2.9.1",
"@tiptap/extension-underline": "^2.9.1",
"@tiptap/pm": "^2.9.1",
"@tiptap/starter-kit": "^2.9.1",
"@tiptap/vue-3": "^2.9.1",
"@vuepic/vue-datepicker": "^10.0.0",
"@vueuse/components": "^10.7.2",
"@vueuse/core": "^10.7.2",
"codemirror": "^6.0.1",
"date-fns": "^2.30.0",
"date-fns-tz": "^2.0.0",
"focus-trap": "^7.5.4",
"inter-ui": "^3.19.3",
"lodash-es": "^4.17.21",
"nanoid": "^5.0.7",
"vue-codemirror6": "^1.3.8",
"vue-i18n": "^9.9.1",
"vue-smooth-reflow": "^0.1.12"
},
Expand Down Expand Up @@ -109,8 +133,5 @@
"vite-plugin-svgstring": "^1.0.0",
"vitest": "^1.1.3",
"vue-tsc": "^2.0.21"
},
"peerDependencies": {
"vue": ">= 3.5.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ $mt-field-transition:
margin-bottom: var(--scale-size-12);
}

&.is--disabled {
cursor: not-allowed;
}

&__hint-wrapper {
display: flex;
justify-content: space-between;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ const isInsideTooltip = useIsInsideTooltip();
width: 100%;
display: flex;
justify-content: center;
align-items: center;
Haberkamp marked this conversation as resolved.
Show resolved Hide resolved
}

.mt-button--x-small {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { within, userEvent, fireEvent } from "@storybook/test";
import { expect } from "@storybook/test";

import meta, { type MtColorpickerMeta, type MtColorpickerStory } from "./mt-colorpicker.stories";
import { waitUntil } from "@/_internal/test-helper";
Haberkamp marked this conversation as resolved.
Show resolved Hide resolved

export default {
...meta,
Expand Down Expand Up @@ -56,6 +57,188 @@ export const VisualTestOpenColorpicker: MtColorpickerStory = {
},
};

export const VisualTestOpenColorpickerWithApplyMode: MtColorpickerStory = {
name: "Open colorpicker with apply mode",
args: {
modelValue: "rgba(72, 228, 37, 0.81)",
applyMode: true,
colorOutput: "rgb",
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const pickerToggle = canvas.getByLabelText("colorpicker-toggle");

await userEvent.click(pickerToggle);

// Look inside the popover
const popover = within(
document.getElementsByClassName("mt-floating-ui__content")[0] as HTMLElement,
);

const colorRange = popover.getByLabelText("colorpicker-color-range") as HTMLInputElement;
const alphaRange = popover.getByLabelText("colorpicker-alpha-range") as HTMLInputElement;
const hexInput = popover.getByLabelText("hex-value") as HTMLInputElement;
const redInput = popover.getByLabelText("red-value") as HTMLInputElement;
const greenInput = popover.getByLabelText("green-value") as HTMLInputElement;
const blueInput = popover.getByLabelText("blue-value") as HTMLInputElement;
const alphaInput = popover.getByLabelText("alpha-value") as HTMLInputElement;

expect(colorRange).toBeDefined();
expect(colorRange.value).toEqual("109");
expect(alphaRange).toBeDefined();
expect(alphaRange.value).toEqual("0.81");

expect(hexInput).toBeDefined();
expect(hexInput.value).toEqual("#48e425cf");
expect(redInput).toBeDefined();
expect(redInput.value).toEqual("72");
expect(greenInput).toBeDefined();
expect(greenInput.value).toEqual("228");
expect(blueInput).toBeDefined();
expect(blueInput.value).toEqual("37");
expect(alphaInput).toBeDefined();
expect(alphaInput.value).toEqual("81");

// Check for apply button
const applyButton = popover.getByLabelText("colorpicker-apply-color") as HTMLButtonElement;
expect(applyButton).toBeDefined();
},
};

export const TestOpenColorpickerWithApplyMode: MtColorpickerStory = {
jleifeld marked this conversation as resolved.
Show resolved Hide resolved
name: "Use colorpicker with apply mode",
args: {
modelValue: "rgba(72, 228, 37, 0.81)",
applyMode: true,
colorOutput: "rgb",
},
play: async ({ canvasElement, args }) => {
const canvas = within(canvasElement);

const pickerToggle = canvas.getByLabelText("colorpicker-toggle");

await userEvent.click(pickerToggle);

// Look inside the popover
const popover = within(
jleifeld marked this conversation as resolved.
Show resolved Hide resolved
document.getElementsByClassName("mt-floating-ui__content")[0] as HTMLElement,
);

const colorRange = popover.getByLabelText("colorpicker-color-range") as HTMLInputElement;
const alphaRange = popover.getByLabelText("colorpicker-alpha-range") as HTMLInputElement;
const hexInput = popover.getByLabelText("hex-value") as HTMLInputElement;
const redInput = popover.getByLabelText("red-value") as HTMLInputElement;
const greenInput = popover.getByLabelText("green-value") as HTMLInputElement;
const blueInput = popover.getByLabelText("blue-value") as HTMLInputElement;
const alphaInput = popover.getByLabelText("alpha-value") as HTMLInputElement;

expect(colorRange).toBeDefined();
expect(colorRange.value).toEqual("109");
expect(alphaRange).toBeDefined();
expect(alphaRange.value).toEqual("0.81");

expect(hexInput).toBeDefined();
expect(hexInput.value).toEqual("#48e425cf");
expect(redInput).toBeDefined();
expect(redInput.value).toEqual("72");
expect(greenInput).toBeDefined();
expect(greenInput.value).toEqual("228");
expect(blueInput).toBeDefined();
expect(blueInput.value).toEqual("37");
expect(alphaInput).toBeDefined();
expect(alphaInput.value).toEqual("81");

// Check for apply button
const applyButton = popover.getByLabelText("colorpicker-apply-color") as HTMLButtonElement;
expect(applyButton).toBeDefined();

// Change colors
fireEvent.input(colorRange, { target: { value: 300 } });
fireEvent.input(alphaRange, { target: { value: 0.5 } });

// Apply changes
await userEvent.click(applyButton);

// Wait until the popover is closed
await waitUntil(() => {
return document.getElementsByClassName("mt-floating-ui__content").length === 0;
});

// Check if the color is applied
expect(args.updateModelValue).toHaveBeenCalledWith("rgba(228, 37, 228, 0.5)");
},
};

export const ResetsColorInApplyMode: MtColorpickerStory = {
name: "Resets color in apply mode when closed without applying",
args: {
modelValue: "rgba(72, 228, 37, 0.81)",
applyMode: true,
colorOutput: "rgb",
},
play: async ({ canvasElement, args }) => {
const canvas = within(canvasElement);

const pickerToggle = canvas.getByLabelText("colorpicker-toggle");

await userEvent.click(pickerToggle);

// Look inside the popover
const popover = within(
document.getElementsByClassName("mt-floating-ui__content")[0] as HTMLElement,
);

const colorRange = popover.getByLabelText("colorpicker-color-range") as HTMLInputElement;
const alphaRange = popover.getByLabelText("colorpicker-alpha-range") as HTMLInputElement;
const hexInput = popover.getByLabelText("hex-value") as HTMLInputElement;
const redInput = popover.getByLabelText("red-value") as HTMLInputElement;
const greenInput = popover.getByLabelText("green-value") as HTMLInputElement;
const blueInput = popover.getByLabelText("blue-value") as HTMLInputElement;
const alphaInput = popover.getByLabelText("alpha-value") as HTMLInputElement;

expect(colorRange).toBeDefined();
expect(colorRange.value).toEqual("109");
expect(alphaRange).toBeDefined();
expect(alphaRange.value).toEqual("0.81");

expect(hexInput).toBeDefined();
expect(hexInput.value).toEqual("#48e425cf");
expect(redInput).toBeDefined();
expect(redInput.value).toEqual("72");
expect(greenInput).toBeDefined();
expect(greenInput.value).toEqual("228");
expect(blueInput).toBeDefined();
expect(blueInput.value).toEqual("37");
expect(alphaInput).toBeDefined();
expect(alphaInput.value).toEqual("81");

// Check for apply button
const applyButton = popover.getByLabelText("colorpicker-apply-color") as HTMLButtonElement;
expect(applyButton).toBeDefined();

// Change colors
fireEvent.input(colorRange, { target: { value: 300 } });
fireEvent.input(alphaRange, { target: { value: 0.5 } });

const colorpickerInputField = canvas.getByLabelText(
"colorpicker-color-value",
) as HTMLInputElement;

// Close popover without applying
await userEvent.click(colorpickerInputField);

// Wait until the popover is closed
await waitUntil(() => {
return document.getElementsByClassName("mt-floating-ui__content").length === 0;
});

// Check if the color is resetted
expect(args.updateModelValue).not.toHaveBeenCalled();
expect(colorpickerInputField.value).toEqual("rgba(72, 228, 37, 0.81)");
},
};

export const VisualTestChangeColorpickerColor: MtColorpickerStory = {
name: "Change colorpicker color",
args: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import MtColorpicker from "./mt-colorpicker.vue";
import type { StoryObj } from "@storybook/vue3";
import type { SlottedMeta } from "@/_internal/story-helper";
import { ref } from "vue";
import { fn } from "@storybook/test";

export type MtColorpickerMeta = SlottedMeta<typeof MtColorpicker, "default">;
export type MtColorpickerMeta = SlottedMeta<typeof MtColorpicker, "default" | "updateModelValue">;

export default {
title: "Components/Form/mt-colorpicker",
component: MtColorpicker,
render: (args) => ({
components: { MtColorpicker },
template: '<mt-colorpicker v-bind="args"></mt-colorpicker>',
template: `<mt-colorpicker
v-bind="args"
:modelValue="currentModelValue"
@update:modelValue="onUpdateModelValue"
></mt-colorpicker>`,
setup: () => {
const currentModelValue = ref(args.modelValue);
const onUpdateModelValue = (value: string) => {
currentModelValue.value = value;
args.updateModelValue(value);
};

return {
args,
currentModelValue,
onUpdateModelValue,
};
},
}),
Expand All @@ -30,6 +44,8 @@ export default {
isInherited: false,
isInheritanceField: false,
disableInheritanceToggle: false,
compact: false,
updateModelValue: fn(),
},
} as MtColorpickerMeta;

Expand Down
Loading
Loading