mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 23:58:13 +08:00
feat(split-pane): adds split-pane (part 1)
This commit is contained in:
42
package-lock.json
generated
42
package-lock.json
generated
@ -4,6 +4,16 @@
|
|||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"JSONStream": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz",
|
||||||
|
"integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"jsonparse": "1.3.1",
|
||||||
|
"through": "2.3.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz",
|
||||||
@ -1107,8 +1117,8 @@
|
|||||||
"integrity": "sha1-4ye1MZThp61dxjR57pCZpSsCSGU=",
|
"integrity": "sha1-4ye1MZThp61dxjR57pCZpSsCSGU=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-text-path": "1.0.1",
|
|
||||||
"JSONStream": "1.3.1",
|
"JSONStream": "1.3.1",
|
||||||
|
"is-text-path": "1.0.1",
|
||||||
"lodash": "4.17.4",
|
"lodash": "4.17.4",
|
||||||
"meow": "3.7.0",
|
"meow": "3.7.0",
|
||||||
"split2": "2.1.1",
|
"split2": "2.1.1",
|
||||||
@ -1137,8 +1147,8 @@
|
|||||||
"integrity": "sha512-8od6g684Fhi5Vpp4ABRv/RBsW1AY6wSHbJHEK6FGTv+8jvAAnlABniZu/FVmX9TcirkHepaEsa1QGkRvbg0CKw==",
|
"integrity": "sha512-8od6g684Fhi5Vpp4ABRv/RBsW1AY6wSHbJHEK6FGTv+8jvAAnlABniZu/FVmX9TcirkHepaEsa1QGkRvbg0CKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-text-path": "1.0.1",
|
|
||||||
"JSONStream": "1.3.1",
|
"JSONStream": "1.3.1",
|
||||||
|
"is-text-path": "1.0.1",
|
||||||
"lodash": "4.17.4",
|
"lodash": "4.17.4",
|
||||||
"meow": "3.7.0",
|
"meow": "3.7.0",
|
||||||
"split2": "2.1.1",
|
"split2": "2.1.1",
|
||||||
@ -2881,16 +2891,6 @@
|
|||||||
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
|
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"JSONStream": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz",
|
|
||||||
"integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"jsonparse": "1.3.1",
|
|
||||||
"through": "2.3.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jsprim": {
|
"jsprim": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||||
@ -4659,15 +4659,6 @@
|
|||||||
"any-observable": "0.2.0"
|
"any-observable": "0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "5.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-length": {
|
"string-length": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
|
||||||
@ -4688,6 +4679,15 @@
|
|||||||
"strip-ansi": "3.0.1"
|
"strip-ansi": "3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "5.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"stringstream": {
|
"stringstream": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<ion-app>
|
<ion-app>
|
||||||
<ion-menu side="left">
|
<ion-menu side="left">
|
||||||
|
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar color="secondary">
|
<ion-toolbar color="secondary">
|
||||||
<ion-title>Left Menu</ion-title>
|
<ion-title>Left Menu</ion-title>
|
||||||
@ -18,61 +19,19 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
|
|
||||||
<ion-list>
|
<ion-list>
|
||||||
|
<ion-item>Open Right Menu</ion-item>
|
||||||
<ion-item>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
Open Right Menu
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
</ion-item>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
<ion-item menuClose="left" class="e2eCloseLeftMenu" detail-none>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
Close Menu
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
</ion-item>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
<ion-item menuClose="left" detail-none>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
Close Menu
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
</ion-item>
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item menuClose="left" detail-none>
|
|
||||||
Close Menu
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
@ -84,35 +43,31 @@
|
|||||||
|
|
||||||
</ion-menu>
|
</ion-menu>
|
||||||
|
|
||||||
<ion-menu side="right" >
|
<ion-menu side="right">
|
||||||
|
<ion-header>
|
||||||
<ion-header id="id">
|
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-title>Hola</ion-title>
|
<ion-title>Hola</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
|
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content padding>
|
<ion-content padding>
|
||||||
hola macho
|
hola macho
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
</ion-menu>
|
</ion-menu>
|
||||||
|
|
||||||
<ion-page main class="show-page">
|
<ion-page main class="show-page">
|
||||||
|
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-title>Menu Basic Test</ion-title>
|
<ion-title>Ionic CDN demo</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content padding>
|
<ion-content padding>
|
||||||
<ion-button onclick="openLeft()">
|
<ion-button onclick="openLeft()">Open left menu</ion-button>
|
||||||
Open left menu
|
<ion-button onclick="openRight()">Open right menu</ion-button>
|
||||||
</ion-button>
|
|
||||||
<ion-button onclick="openRight()">
|
|
||||||
Open right menu
|
|
||||||
</ion-button>
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
</ion-page>
|
</ion-page>
|
||||||
|
|
||||||
</ion-app>
|
</ion-app>
|
||||||
@ -130,5 +85,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
28
packages/core/src/components/split-pane/split-pane.ios.scss
Normal file
28
packages/core/src/components/split-pane/split-pane.ios.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
@import "../../themes/ionic.globals.ios";
|
||||||
|
@import "./split-pane";
|
||||||
|
|
||||||
|
// Split Pane
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Minimum width of the split-pane's side pane
|
||||||
|
$split-pane-ios-side-min-width: $split-pane-side-min-width !default;
|
||||||
|
|
||||||
|
/// @prop - Maximum width of the split-pane's side pane
|
||||||
|
$split-pane-ios-side-max-width: $split-pane-side-max-width !default;
|
||||||
|
|
||||||
|
/// @prop - Border style of the side pane
|
||||||
|
$split-pane-ios-border: $hairlines-width solid $list-ios-border-color !default;
|
||||||
|
|
||||||
|
.split-pane-ios.split-pane-visible >.split-pane-side {
|
||||||
|
min-width: $split-pane-ios-side-min-width;
|
||||||
|
max-width: $split-pane-ios-side-max-width;
|
||||||
|
|
||||||
|
border-right: $split-pane-ios-border;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-ios.split-pane-visible > .split-pane-side[side=right] {
|
||||||
|
border-right: 0;
|
||||||
|
border-left: $split-pane-ios-border;
|
||||||
|
}
|
||||||
28
packages/core/src/components/split-pane/split-pane.md.scss
Normal file
28
packages/core/src/components/split-pane/split-pane.md.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
@import "../../themes/ionic.globals.md";
|
||||||
|
@import "./split-pane";
|
||||||
|
|
||||||
|
// Split Pane
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Minimum width of the split-pane's side pane
|
||||||
|
$split-pane-md-side-min-width: $split-pane-side-min-width !default;
|
||||||
|
|
||||||
|
/// @prop - Maximum width of the split-pane's side pane
|
||||||
|
$split-pane-md-side-max-width: $split-pane-side-max-width !default;
|
||||||
|
|
||||||
|
/// @prop - Border style of the side pane
|
||||||
|
$split-pane-md-border: 1px solid $list-md-border-color !default;
|
||||||
|
|
||||||
|
.split-pane-md.split-pane-visible >.split-pane-side {
|
||||||
|
min-width: $split-pane-md-side-min-width;
|
||||||
|
max-width: $split-pane-md-side-max-width;
|
||||||
|
|
||||||
|
border-right: $split-pane-md-border;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-md.split-pane-visible > .split-pane-side[side=right] {
|
||||||
|
border-right: 0;
|
||||||
|
border-left: $split-pane-md-border;
|
||||||
|
}
|
||||||
106
packages/core/src/components/split-pane/split-pane.scss
Normal file
106
packages/core/src/components/split-pane/split-pane.scss
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
@import "../../themes/ionic.globals";
|
||||||
|
|
||||||
|
// Split Pane
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$split-pane-side-min-width: 270px !default;
|
||||||
|
$split-pane-side-max-width: 28% !default;
|
||||||
|
|
||||||
|
.split-pane {
|
||||||
|
@include position(0, 0, 0, 0);
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
contain: strict;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-side:not(ion-menu) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side,
|
||||||
|
.split-pane-visible >.split-pane-main {
|
||||||
|
@include position(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// scss-lint:disable ImportantRule
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-main,
|
||||||
|
.split-pane-visible >ion-nav.split-pane-side,
|
||||||
|
.split-pane-visible >ion-tabs.split-pane-side,
|
||||||
|
.split-pane-visible >ion-menu.menu-enabled {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >ion-split-pane.split-pane-side,
|
||||||
|
.split-pane-visible >ion-split-pane.split-pane-main {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >ion-menu.menu-enabled {
|
||||||
|
>.menu-inner {
|
||||||
|
@include position-horizontal(0, 0);
|
||||||
|
|
||||||
|
// scss-lint:disable ImportantRule
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
box-shadow: none !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
>.ion-backdrop {
|
||||||
|
// scss-lint:disable ImportantRule
|
||||||
|
display: hidden !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side[side=start] {
|
||||||
|
@include multi-dir() {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side[side=end] {
|
||||||
|
@include multi-dir() {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side[side=left] {
|
||||||
|
@include ltr() {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include rtl() {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-visible >.split-pane-side[side=right] {
|
||||||
|
@include ltr() {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include rtl() {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
276
packages/core/src/components/split-pane/split-pane.tsx
Normal file
276
packages/core/src/components/split-pane/split-pane.tsx
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import { Component, State, Element, Event, EventEmitter, Prop, Method, PropDidChange } from '@stencil/core';
|
||||||
|
// import { assert } from '../../utils/helpers';
|
||||||
|
|
||||||
|
const SPLIT_PANE_MAIN = 'split-pane-main';
|
||||||
|
const SPLIT_PANE_SIDE = 'split-pane-side';
|
||||||
|
const QUERY: { [key: string]: string } = {
|
||||||
|
'xs': '(min-width: 0px)',
|
||||||
|
'sm': '(min-width: 576px)',
|
||||||
|
'md': '(min-width: 768px)',
|
||||||
|
'lg': '(min-width: 992px)',
|
||||||
|
'xl': '(min-width: 1200px)',
|
||||||
|
'never': ''
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name SplitPane
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* SplitPane is a component that makes it possible to create multi-view layout.
|
||||||
|
* Similar to iPad apps, SplitPane allows UI elements, like Menus, to be
|
||||||
|
* displayed as the viewport increases.
|
||||||
|
*
|
||||||
|
* If the devices screen size is below a certain size, the SplitPane will
|
||||||
|
* collapse and the menu will become hidden again. This is especially useful when
|
||||||
|
* creating an app that will be served over a browser or deployed through the app
|
||||||
|
* store to phones and tablets.
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* To use SplitPane, simply add the component around your root component.
|
||||||
|
* In this example, we'll be using a sidemenu layout, similar to what is
|
||||||
|
* provided from the sidemenu starter template.
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <ion-split-pane>
|
||||||
|
* <!-- our side menu -->
|
||||||
|
* <ion-menu>
|
||||||
|
* <ion-header>
|
||||||
|
* <ion-toolbar>
|
||||||
|
* <ion-title>Menu</ion-title>
|
||||||
|
* </ion-toolbar>
|
||||||
|
* </ion-header>
|
||||||
|
* </ion-menu>
|
||||||
|
*
|
||||||
|
* <!-- the main content -->
|
||||||
|
* <ion-nav [root]="root" main></ion-nav>
|
||||||
|
* </ion-split-pane>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Here, SplitPane will look for the element with the `main` attribute and make
|
||||||
|
* that the central component on larger screens. The `main` component can be any
|
||||||
|
* Ionic component (`ion-nav` or `ion-tabs`) except `ion-menu`.
|
||||||
|
*
|
||||||
|
* ### Setting breakpoints
|
||||||
|
*
|
||||||
|
* By default, SplitPane will expand when the screen is larger than 768px.
|
||||||
|
* If you want to customize this, use the `when` input. The `when` input can
|
||||||
|
* accept any valid media query, as it uses `matchMedia()` underneath.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <ion-split-pane when="(min-width: 475px)">
|
||||||
|
*
|
||||||
|
* <!-- our side menu -->
|
||||||
|
* <ion-menu>
|
||||||
|
* ....
|
||||||
|
* </ion-menu>
|
||||||
|
*
|
||||||
|
* <!-- the main content -->
|
||||||
|
* <ion-nav [root]="root" main></ion-nav>
|
||||||
|
* </ion-split-pane>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* SplitPane also provides some predefined media queries that can be used.
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <!-- could be "xs", "sm", "md", "lg", or "xl" -->
|
||||||
|
* <ion-split-pane when="lg">
|
||||||
|
* ...
|
||||||
|
* </ion-split-pane>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* | Size | Value | Description |
|
||||||
|
* |------|-----------------------|-----------------------------------------------------------------------|
|
||||||
|
* | `xs` | `(min-width: 0px)` | Show the split-pane when the min-width is 0px (meaning, always) |
|
||||||
|
* | `sm` | `(min-width: 576px)` | Show the split-pane when the min-width is 576px |
|
||||||
|
* | `md` | `(min-width: 768px)` | Show the split-pane when the min-width is 768px (default break point) |
|
||||||
|
* | `lg` | `(min-width: 992px)` | Show the split-pane when the min-width is 992px |
|
||||||
|
* | `xl` | `(min-width: 1200px)` | Show the split-pane when the min-width is 1200px |
|
||||||
|
*
|
||||||
|
* You can also pass in boolean values that will trigger SplitPane when the value
|
||||||
|
* or expression evaluates to true.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <ion-split-pane [when]="isLarge">
|
||||||
|
* ...
|
||||||
|
* </ion-split-pane>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* class MyClass {
|
||||||
|
* public isLarge = false;
|
||||||
|
* constructor(){}
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Or
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <ion-split-pane [when]="shouldShow()">
|
||||||
|
* ...
|
||||||
|
* </ion-split-pane>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* class MyClass {
|
||||||
|
* constructor(){}
|
||||||
|
* shouldShow(){
|
||||||
|
* if(conditionA){
|
||||||
|
* return true
|
||||||
|
* } else {
|
||||||
|
* return false
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
tag: 'ion-split-pane',
|
||||||
|
styleUrls: {
|
||||||
|
ios: 'split-pane.ios.scss',
|
||||||
|
md: 'split-pane.md.scss',
|
||||||
|
wp: 'split-pane.wp.scss'
|
||||||
|
},
|
||||||
|
host: {
|
||||||
|
theme: 'split-pane'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class SplitPane {
|
||||||
|
|
||||||
|
private rmL: any;
|
||||||
|
@Element() private ele: HTMLElement;
|
||||||
|
@State() private visible: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {boolean} If `false`, the split-pane is disabled, ie. the side pane will
|
||||||
|
* never be displayed. Default `true`.
|
||||||
|
*/
|
||||||
|
@Prop() enabled: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {string | boolean} When the split-pane should be shown.
|
||||||
|
* Can be a CSS media query expression, or a shortcut expression.
|
||||||
|
* Can also be a boolean expression.
|
||||||
|
*/
|
||||||
|
@Prop() when: string | boolean = QUERY['md'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @output {any} Expression to be called when the split-pane visibility has changed
|
||||||
|
*/
|
||||||
|
@Event() ionChange: EventEmitter;
|
||||||
|
|
||||||
|
ionViewDidLoad() {
|
||||||
|
this._styleChildren();
|
||||||
|
this._updateQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
ionViewDidUnload() {
|
||||||
|
this.rmL && this.rmL();
|
||||||
|
this.rmL = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _styleChildren() {
|
||||||
|
const children = this.ele.children;
|
||||||
|
const nu = this.ele.childElementCount;
|
||||||
|
let foundMain = false;
|
||||||
|
for (var i = 0; i < nu; i++) {
|
||||||
|
var child = children[i] as HTMLElement;
|
||||||
|
var isMain = child.hasAttribute('main');
|
||||||
|
if (isMain) {
|
||||||
|
if (foundMain) {
|
||||||
|
// console.warn('split pane can not have more than one main node');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foundMain = true;
|
||||||
|
}
|
||||||
|
setPaneClass(child, isMain);
|
||||||
|
}
|
||||||
|
// if (!foundMain) {
|
||||||
|
// console.warn('split pane could not found any main node');
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@PropDidChange('when')
|
||||||
|
_updateQuery() {
|
||||||
|
this.rmL && this.rmL();
|
||||||
|
this.rmL = null;
|
||||||
|
|
||||||
|
// Check if the split-pane is disabled
|
||||||
|
if (!this.enabled) {
|
||||||
|
this._setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When query is a boolean
|
||||||
|
const query = this.when;
|
||||||
|
if (typeof query === 'boolean') {
|
||||||
|
this._setVisible(query);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When query is a string, let's find first if it is a shortcut
|
||||||
|
const defaultQuery = QUERY[query];
|
||||||
|
const mediaQuery = (defaultQuery)
|
||||||
|
? defaultQuery
|
||||||
|
: query;
|
||||||
|
|
||||||
|
// Media query is empty or null, we hide it
|
||||||
|
if (!mediaQuery || mediaQuery.length === 0) {
|
||||||
|
this._setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen on media query
|
||||||
|
const callback = (q: MediaQueryList) => this._setVisible(q.matches);
|
||||||
|
const mediaList = window.matchMedia(mediaQuery);
|
||||||
|
mediaList.addListener(callback);
|
||||||
|
this.rmL = () => mediaList.removeListener(callback);
|
||||||
|
this._setVisible(mediaList.matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setVisible(visible: boolean) {
|
||||||
|
if (this.visible !== visible) {
|
||||||
|
this.visible = visible;
|
||||||
|
this.ionChange.emit(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
@Method()
|
||||||
|
isVisible(): boolean {
|
||||||
|
return this.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostData() {
|
||||||
|
return {
|
||||||
|
class: {
|
||||||
|
'split-pane-visible': this.visible
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <slot></slot>;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPaneClass(ele: HTMLElement, isMain: boolean) {
|
||||||
|
let toAdd;
|
||||||
|
let toRemove;
|
||||||
|
if (isMain) {
|
||||||
|
toAdd = SPLIT_PANE_MAIN;
|
||||||
|
toRemove = SPLIT_PANE_SIDE;
|
||||||
|
} else {
|
||||||
|
toAdd = SPLIT_PANE_SIDE;
|
||||||
|
toRemove = SPLIT_PANE_MAIN;
|
||||||
|
}
|
||||||
|
const classList = ele.classList;
|
||||||
|
classList.add(toAdd);
|
||||||
|
classList.remove(toRemove);
|
||||||
|
}
|
||||||
28
packages/core/src/components/split-pane/split-pane.wp.scss
Normal file
28
packages/core/src/components/split-pane/split-pane.wp.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
@import "../../themes/ionic.globals.wp";
|
||||||
|
@import "./split-pane";
|
||||||
|
|
||||||
|
// Split Pane
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Minimum width of the split-pane's side pane
|
||||||
|
$split-pane-wp-side-min-width: $split-pane-side-min-width !default;
|
||||||
|
|
||||||
|
/// @prop - Maximum width of the split-pane's side pane
|
||||||
|
$split-pane-wp-side-max-width: $split-pane-side-max-width !default;
|
||||||
|
|
||||||
|
/// @prop - Border style of the side pane
|
||||||
|
$split-pane-wp-border: 1px solid $list-wp-border-color !default;
|
||||||
|
|
||||||
|
.split-pane-wp.split-pane-visible >.split-pane-side {
|
||||||
|
min-width: $split-pane-wp-side-min-width;
|
||||||
|
max-width: $split-pane-wp-side-max-width;
|
||||||
|
|
||||||
|
border-right: $split-pane-wp-border;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-pane-wp.split-pane-visible > .split-pane-side[side=right] {
|
||||||
|
border-right: 0;
|
||||||
|
border-left: $split-pane-wp-border;
|
||||||
|
}
|
||||||
79
packages/core/src/components/split-pane/test/basic.html
Normal file
79
packages/core/src/components/split-pane/test/basic.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html dir="ltr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Ionic Item Sliding</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<script src="/dist/ionic.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-split-pane>
|
||||||
|
|
||||||
|
<ion-menu side="left">
|
||||||
|
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar color="secondary">
|
||||||
|
<ion-title>Left Menu</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item>Open Right Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
<ion-item detail-none>Close Menu</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-footer>
|
||||||
|
<ion-toolbar color="secondary">
|
||||||
|
<ion-title>Footer</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-footer>
|
||||||
|
|
||||||
|
</ion-menu>
|
||||||
|
|
||||||
|
<ion-page main class="show-page">
|
||||||
|
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Ionic CDN demo</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content padding>
|
||||||
|
<ion-button onclick="openLeft()">Open left menu</ion-button>
|
||||||
|
<ion-button onclick="openRight()">Open right menu</ion-button>
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
</ion-page>
|
||||||
|
</ion-split-pane>
|
||||||
|
|
||||||
|
</ion-app>
|
||||||
|
<ion-menu-controller></ion-menu-controller>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const menu = document.querySelector('ion-menu-controller');
|
||||||
|
function openLeft() {
|
||||||
|
console.log('Open left menu');
|
||||||
|
menu.open('left');
|
||||||
|
}
|
||||||
|
function openRight() {
|
||||||
|
console.log('Open right menu');
|
||||||
|
menu.open('right');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user