mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
feat(editor): Make workflows, credentials, executions and new canvas usable on mobile and touch devices (#12372)
This commit is contained in:
@@ -34,7 +34,11 @@ const classes = computed(() => ({
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="$slots.append" data-test-id="card-append" :class="$style.append">
|
||||
<div
|
||||
v-if="$slots.append"
|
||||
data-test-id="card-append"
|
||||
:class="[$style.append, 'n8n-card-append']"
|
||||
>
|
||||
<slot name="append" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,7 +49,7 @@ const classes = computed(() => ({
|
||||
border-radius: var(--border-radius-large);
|
||||
border: var(--border-base);
|
||||
background-color: var(--color-background-xlight);
|
||||
padding: var(--spacing-s);
|
||||
padding: var(--card--padding, var(--spacing-s));
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
@@ -101,5 +105,6 @@ const classes = computed(() => ({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: default;
|
||||
width: var(--card--append--width, unset);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -75,6 +75,38 @@ describe('useDeviceSupport()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMobileDevice', () => {
|
||||
it('should be true for iOS user agent', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'iphone' });
|
||||
const { isMobileDevice } = useDeviceSupport();
|
||||
expect(isMobileDevice).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be true for Android user agent', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'android' });
|
||||
const { isMobileDevice } = useDeviceSupport();
|
||||
expect(isMobileDevice).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be false for non-mobile user agent', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'windows' });
|
||||
const { isMobileDevice } = useDeviceSupport();
|
||||
expect(isMobileDevice).toEqual(false);
|
||||
});
|
||||
|
||||
it('should be true for iPad user agent', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'ipad' });
|
||||
const { isMobileDevice } = useDeviceSupport();
|
||||
expect(isMobileDevice).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be true for iPod user agent', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'ipod' });
|
||||
const { isMobileDevice } = useDeviceSupport();
|
||||
expect(isMobileDevice).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCtrlKeyPressed()', () => {
|
||||
it('should return true for metaKey press on macOS', () => {
|
||||
Object.defineProperty(navigator, 'userAgent', { value: 'macintosh' });
|
||||
|
||||
@@ -12,12 +12,16 @@ export function useDeviceSupport() {
|
||||
!window.matchMedia('(any-pointer: fine)').matches,
|
||||
);
|
||||
const userAgent = ref(navigator.userAgent.toLowerCase());
|
||||
const isMacOs = ref(
|
||||
userAgent.value.includes('macintosh') ||
|
||||
|
||||
const isIOs = ref(
|
||||
userAgent.value.includes('iphone') ||
|
||||
userAgent.value.includes('ipad') ||
|
||||
userAgent.value.includes('iphone') ||
|
||||
userAgent.value.includes('ipod'),
|
||||
);
|
||||
const isAndroidOs = ref(userAgent.value.includes('android'));
|
||||
const isMacOs = ref(userAgent.value.includes('macintosh') || isIOs.value);
|
||||
const isMobileDevice = ref(isIOs.value || isAndroidOs.value);
|
||||
|
||||
const controlKeyCode = ref(isMacOs.value ? 'Meta' : 'Control');
|
||||
|
||||
function isCtrlKeyPressed(e: MouseEvent | KeyboardEvent): boolean {
|
||||
@@ -30,7 +34,10 @@ export function useDeviceSupport() {
|
||||
return {
|
||||
userAgent: userAgent.value,
|
||||
isTouchDevice: isTouchDevice.value,
|
||||
isAndroidOs: isAndroidOs.value,
|
||||
isIOs: isIOs.value,
|
||||
isMacOs: isMacOs.value,
|
||||
isMobileDevice: isMobileDevice.value,
|
||||
controlKeyCode: controlKeyCode.value,
|
||||
isCtrlKeyPressed,
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
@use './base.scss';
|
||||
@use './pagination.scss';
|
||||
@use './dialog.scss';
|
||||
@use './display.scss';
|
||||
// @use "./autocomplete.scss";
|
||||
@use './dropdown.scss';
|
||||
@use './dropdown-menu.scss';
|
||||
|
||||
20
packages/design-system/src/css/mixins/_breakpoints.scss
Normal file
20
packages/design-system/src/css/mixins/_breakpoints.scss
Normal file
@@ -0,0 +1,20 @@
|
||||
@use '../common/var';
|
||||
|
||||
@mixin breakpoint($name) {
|
||||
@if map-has-key(var.$breakpoints-spec, $name) {
|
||||
$query: map-get(var.$breakpoints-spec, $name);
|
||||
$media-query: '';
|
||||
|
||||
@each $key, $value in $query {
|
||||
$media-query: '#{$media-query} and (#{$key}: #{$value})';
|
||||
}
|
||||
|
||||
$media-query: unquote(str-slice($media-query, 6)); // Remove the initial ' and '
|
||||
|
||||
@media screen and #{$media-query} {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
@error "No breakpoint named `#{$name}` found in `$breakpoints-spec`.";
|
||||
}
|
||||
}
|
||||
6
packages/design-system/src/css/mixins/index.scss
Normal file
6
packages/design-system/src/css/mixins/index.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
@forward 'breakpoints';
|
||||
@forward 'button';
|
||||
@forward 'config';
|
||||
@forward 'function';
|
||||
@forward 'mixins';
|
||||
@forward 'utils';
|
||||
Reference in New Issue
Block a user