mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
feature(show-when): initial implementation of show-when
This commit is contained in:
65
packages/core/src/components/show-when/readme.md
Normal file
65
packages/core/src/components/show-when/readme.md
Normal file
@ -0,0 +1,65 @@
|
||||
# ion-show-when
|
||||
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
#### mediaQuery
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### or
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### platform
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### size
|
||||
|
||||
string
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### media-query
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### or
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### platform
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### size
|
||||
|
||||
string
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
7
packages/core/src/components/show-when/show-when.scss
Normal file
7
packages/core/src/components/show-when/show-when.scss
Normal file
@ -0,0 +1,7 @@
|
||||
ion-show-when.show-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ion-show-when.hide-content {
|
||||
display: none !important;
|
||||
}
|
46
packages/core/src/components/show-when/show-when.tsx
Normal file
46
packages/core/src/components/show-when/show-when.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { Component, Element, Prop } from '@stencil/core';
|
||||
import { Config, PlatformConfig } from '../../index';
|
||||
|
||||
import {
|
||||
DisplayWhen,
|
||||
componentWillLoadImpl,
|
||||
} from '../../utils/show-hide-when-utils';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-show-when',
|
||||
styleUrl: './show-when.scss'
|
||||
})
|
||||
export class ShowWhen implements DisplayWhen {
|
||||
|
||||
@Element() element: HTMLElement;
|
||||
@Prop({ context: 'config' }) config: Config;
|
||||
@Prop({ context: 'platforms' }) calculatedPlatforms: PlatformConfig[];
|
||||
|
||||
@Prop() mediaQuery: string = null;
|
||||
@Prop() size: string = null;
|
||||
@Prop() mode: string = null;
|
||||
@Prop() platform: string = null;
|
||||
@Prop() or = false;
|
||||
|
||||
passesTest = false;
|
||||
|
||||
componentWillLoad() {
|
||||
return componentWillLoadImpl(this);
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
'show-content': this.passesTest,
|
||||
'hide-content': !this.passesTest
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
96
packages/core/src/components/show-when/test/basic/index.html
Normal file
96
packages/core/src/components/show-when/test/basic/index.html
Normal file
@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Show When - Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<script src="/dist/ionic.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Show when - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
|
||||
<h2>Mode Tests</h2>
|
||||
<ion-show-when mode="md, ios">
|
||||
<div>Shows on MD, iOS</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when mode="md">
|
||||
<div>Shows on MD only</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when mode="ios">
|
||||
<div>Shows on iOS only</div>
|
||||
</ion-show-when>
|
||||
|
||||
<h2>Platform Tests</h2>
|
||||
|
||||
<ion-show-when platform="android,ios">
|
||||
<div>Render on Android and iOS</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when platform="ios">
|
||||
<div>Only render on iOS</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when platform="android">
|
||||
<div>Only render on Android</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when platform="ipad">
|
||||
<div>Only render on ipad</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when platform="phablet">
|
||||
<div>Only render on phablet</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when platform="iphone">
|
||||
<div>Only render on phone</div>
|
||||
</ion-show-when>
|
||||
|
||||
<h2>Size Tests</h2>
|
||||
<ion-show-when size="xs">
|
||||
<div>Only render on xs</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when size="sm">
|
||||
<div>Only render on sm</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when size="md">
|
||||
<div>Only render on md</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when size="lg">
|
||||
<div>Only render on lg</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when size="xl">
|
||||
<div>Only render on xl</div>
|
||||
</ion-show-when>
|
||||
|
||||
<ion-show-when size="xs, m">
|
||||
<div>Only render on XS or m</div>
|
||||
</ion-show-when>
|
||||
|
||||
</ion-content>
|
||||
|
||||
</ion-page>
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
95
packages/core/src/utils/show-hide-when-utils.ts
Normal file
95
packages/core/src/utils/show-hide-when-utils.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { Config, PlatformConfig } from '../index';
|
||||
|
||||
export function componentWillLoadImpl(displayWhen: DisplayWhen) {
|
||||
displayWhen.passesTest = getTestResult(displayWhen);
|
||||
}
|
||||
|
||||
export function isPlatformMatch(platforms: string[], multiPlatformString: string) {
|
||||
const userProvidedPlatforms = multiPlatformString.replace(/\s/g, '').split(',');
|
||||
for (const userProvidedPlatform of userProvidedPlatforms) {
|
||||
for (const platform of platforms) {
|
||||
if (userProvidedPlatform === platform) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isModeMatch(config: Config, multiModeString: string) {
|
||||
// you can only ever be in one mode, so if an entry from the list matches, return true
|
||||
const modes = multiModeString.replace(/\s/g, '').split(',');
|
||||
for (const mode of modes) {
|
||||
if (config.get('mode') === mode) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export function isMediaQueryMatch(mediaQuery: string) {
|
||||
return window.matchMedia(mediaQuery).matches;
|
||||
}
|
||||
|
||||
export function isSizeMatch(multiSizeString: string) {
|
||||
const sizes = multiSizeString.replace(/\s/g, '').split(',');
|
||||
|
||||
const booleans = sizes.map(size => {
|
||||
const mediaQuery = sizeToMediaQueryMap.get(size);
|
||||
if (!mediaQuery) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return window.matchMedia(mediaQuery).matches;
|
||||
});
|
||||
return booleans.reduce((prev, current) => prev || current);
|
||||
}
|
||||
|
||||
export function getTestResult(displayWhen: DisplayWhen) {
|
||||
const resultsToConsider: boolean[] = [];
|
||||
if (displayWhen.mediaQuery) {
|
||||
resultsToConsider.push(isMediaQueryMatch(displayWhen.mediaQuery));
|
||||
}
|
||||
if (displayWhen.size) {
|
||||
resultsToConsider.push(isSizeMatch(displayWhen.size));
|
||||
}
|
||||
if (displayWhen.mode) {
|
||||
resultsToConsider.push(isModeMatch(displayWhen.config, displayWhen.mode));
|
||||
}
|
||||
if (displayWhen.platform) {
|
||||
const platformNames = displayWhen.calculatedPlatforms.map(platformConfig => platformConfig.name);
|
||||
resultsToConsider.push(isPlatformMatch(platformNames, displayWhen.platform));
|
||||
}
|
||||
|
||||
if (!resultsToConsider.length) {
|
||||
return true;
|
||||
}
|
||||
if (resultsToConsider.length === 1) {
|
||||
return resultsToConsider[0];
|
||||
}
|
||||
return resultsToConsider.reduce((prev: boolean, current: boolean) => {
|
||||
if (displayWhen.or) {
|
||||
return prev || current;
|
||||
}
|
||||
return prev && current;
|
||||
});
|
||||
}
|
||||
|
||||
const sizeToMediaQueryMap = new Map<string, string>();
|
||||
sizeToMediaQueryMap.set('xs', '(min-width: 0px)');
|
||||
sizeToMediaQueryMap.set('sm', '(min-width: 576px)');
|
||||
sizeToMediaQueryMap.set('md', '(min-width: 768px)');
|
||||
sizeToMediaQueryMap.set('lg', '(min-width: 992px)');
|
||||
sizeToMediaQueryMap.set('xl', '(min-width: 1200px)');
|
||||
|
||||
export interface DisplayWhen {
|
||||
calculatedPlatforms: PlatformConfig[];
|
||||
config: Config;
|
||||
mediaQuery: string;
|
||||
mode: string;
|
||||
or: boolean;
|
||||
passesTest: boolean;
|
||||
platform: string;
|
||||
size: string;
|
||||
}
|
Reference in New Issue
Block a user