mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 19:57:22 +08:00
chore(packages): move the packages to root
This commit is contained in:
167
core/src/components/toggle/readme.md
Normal file
167
core/src/components/toggle/readme.md
Normal file
@ -0,0 +1,167 @@
|
||||
# ion-toggle
|
||||
|
||||
Toggles change the state of a single option. Toggles can be switched on or off by pressing or swiping them. They can also be checked programmatically by setting the `checked` property.
|
||||
|
||||
|
||||
```html
|
||||
<!-- Default Toggle -->
|
||||
<ion-toggle></ion-toggle>
|
||||
|
||||
<!-- Disabled Toggle -->
|
||||
<ion-toggle disabled></ion-toggle>
|
||||
|
||||
<!-- Checked Toggle -->
|
||||
<ion-toggle checked></ion-toggle>
|
||||
|
||||
<!-- Toggle Colors -->
|
||||
<ion-toggle color="primary"></ion-toggle>
|
||||
<ion-toggle color="secondary"></ion-toggle>
|
||||
<ion-toggle color="danger"></ion-toggle>
|
||||
<ion-toggle color="light"></ion-toggle>
|
||||
<ion-toggle color="dark"></ion-toggle>
|
||||
|
||||
<!-- Toggles in a List -->
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label>Pepperoni</ion-label>
|
||||
<ion-toggle slot="end" value="pepperoni" checked></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Sausage</ion-label>
|
||||
<ion-toggle slot="end" value="sausage" disabled></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Mushrooms</ion-label>
|
||||
<ion-toggle slot="end" value="mushrooms"></ion-toggle>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
#### checked
|
||||
|
||||
boolean
|
||||
|
||||
If true, the toggle is selected. Defaults to `false`.
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
The color to use from your Sass `$colors` map.
|
||||
Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
|
||||
For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
Indicates that the user cannot interact with the control.
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
|
||||
|
||||
The mode determines which platform styles to use.
|
||||
Possible values are: `"ios"` or `"md"`.
|
||||
For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
|
||||
|
||||
#### name
|
||||
|
||||
string
|
||||
|
||||
The name of the control, which is submitted with the form data.
|
||||
|
||||
|
||||
#### value
|
||||
|
||||
string
|
||||
|
||||
the value of the toggle.
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### checked
|
||||
|
||||
boolean
|
||||
|
||||
If true, the toggle is selected. Defaults to `false`.
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
The color to use from your Sass `$colors` map.
|
||||
Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
|
||||
For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
Indicates that the user cannot interact with the control.
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
|
||||
|
||||
The mode determines which platform styles to use.
|
||||
Possible values are: `"ios"` or `"md"`.
|
||||
For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
|
||||
|
||||
#### name
|
||||
|
||||
string
|
||||
|
||||
The name of the control, which is submitted with the form data.
|
||||
|
||||
|
||||
#### value
|
||||
|
||||
string
|
||||
|
||||
the value of the toggle.
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
#### ionBlur
|
||||
|
||||
Emitted when the toggle loses focus.
|
||||
|
||||
|
||||
#### ionChange
|
||||
|
||||
Emitted when the value property has changed.
|
||||
|
||||
|
||||
#### ionFocus
|
||||
|
||||
Emitted when the toggle has focus.
|
||||
|
||||
|
||||
#### ionStyle
|
||||
|
||||
Emitted when the styles change.
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
19
core/src/components/toggle/test/basic/e2e.js
Normal file
19
core/src/components/toggle/test/basic/e2e.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const { By, until } = require('selenium-webdriver');
|
||||
const { register, Page, platforms } = require('../../../../../scripts/e2e');
|
||||
|
||||
class E2ETestPage extends Page {
|
||||
constructor(driver, platform) {
|
||||
super(driver, `http://localhost:3333/src/components/toggle/test/basic?ionicplatform=${platform}`);
|
||||
}
|
||||
}
|
||||
|
||||
platforms.forEach(platform => {
|
||||
describe('toggle/basic', () => {
|
||||
register('should init', driver => {
|
||||
const page = new E2ETestPage(driver, platform);
|
||||
return page.navigate('#content');
|
||||
});
|
||||
});
|
||||
});
|
100
core/src/components/toggle/test/basic/index.html
Normal file
100
core/src/components/toggle/test/basic/index.html
Normal file
@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Toggle - Basic</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-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Toggle - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content id="content">
|
||||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label>Apple</ion-label>
|
||||
<ion-toggle slot="start" name="apple" checked></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Banana</ion-label>
|
||||
<ion-toggle slot="start" name="banana" checked></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Cherry, disabled</ion-label>
|
||||
<ion-toggle slot="start" color="danger" name="cherry" disabled></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Grape, checked, disabled</ion-label>
|
||||
<ion-toggle slot="start" id="grapeChecked" name="grape" checked disabled></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Kiwi, (ionChange) Secondary color</ion-label>
|
||||
<ion-toggle slot="start" color="secondary" (ionChange)="kiwiChange($event)"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Strawberry, (ionChange) checked="true"</ion-label>
|
||||
<ion-toggle slot="start" color="light" (ionChange)="strawberryChange($event)" checked="true"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Checkbox right, checked, really long text that should ellipsis</ion-label>
|
||||
<ion-toggle slot="end" color="danger" checked></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Checkbox right side</ion-label>
|
||||
<ion-toggle slot="end" checked></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Button w/ right side default icon, really long text that should ellipsis</ion-label>
|
||||
<ion-icon name="information-circle" slot="end"></ion-icon>
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
|
||||
|
||||
<p aria-hidden="true" text-center>
|
||||
<ion-button onClick="toggleBoolean('grapeChecked', 'checked')" fill="outline" size="small">Grape Checked</ion-button>
|
||||
<ion-button onClick="toggleBoolean('grapeChecked', 'disabled')" fill="outline" size="small">Grape Disabled</ion-button>
|
||||
<ion-button onClick="printForm()" fill="outline" size="small">Print Form</ion-button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<ion-toggle id="standAloneChecked"></ion-toggle>
|
||||
Stand-alone toggle: <span id="standAloneCheckedSpan"></span>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
||||
<script>
|
||||
function printForm(ev) {
|
||||
console.log('TODO get working with forms');
|
||||
}
|
||||
|
||||
function toggleBoolean(id, prop) {
|
||||
var el = document.getElementById(id);
|
||||
|
||||
var isTrue = el[prop] ? false : true;
|
||||
el[prop] = isTrue;
|
||||
console.log('in toggleBoolean, setting', prop, 'to', isTrue);
|
||||
}
|
||||
</script>
|
||||
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
19
core/src/components/toggle/test/standalone/e2e.js
Normal file
19
core/src/components/toggle/test/standalone/e2e.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const { By, until } = require('selenium-webdriver');
|
||||
const { register, Page, platforms } = require('../../../../../scripts/e2e');
|
||||
|
||||
class E2ETestPage extends Page {
|
||||
constructor(driver, platform) {
|
||||
super(driver, `http://localhost:3333/src/components/toggle/test/standalone?ionicplatform=${platform}`);
|
||||
}
|
||||
}
|
||||
|
||||
platforms.forEach(platform => {
|
||||
describe('toggle/standalone', () => {
|
||||
register('should init', driver => {
|
||||
const page = new E2ETestPage(driver, platform);
|
||||
return page.navigate();
|
||||
});
|
||||
});
|
||||
});
|
30
core/src/components/toggle/test/standalone/index.html
Normal file
30
core/src/components/toggle/test/standalone/index.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Toggle - Standalone</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>
|
||||
<!-- Default -->
|
||||
<ion-toggle></ion-toggle>
|
||||
|
||||
<!-- Colors -->
|
||||
<ion-toggle checked color="primary"></ion-toggle>
|
||||
<ion-toggle checked color="secondary"></ion-toggle>
|
||||
<ion-toggle checked color="tertiary"></ion-toggle>
|
||||
<ion-toggle checked color="success"></ion-toggle>
|
||||
<ion-toggle checked color="warning"></ion-toggle>
|
||||
<ion-toggle checked color="danger"></ion-toggle>
|
||||
<ion-toggle checked color="light"></ion-toggle>
|
||||
<ion-toggle checked color="medium"></ion-toggle>
|
||||
<ion-toggle checked color="dark"></ion-toggle>
|
||||
|
||||
<!-- Disabled -->
|
||||
<ion-toggle checked disabled></ion-toggle>
|
||||
<ion-toggle checked disabled color="secondary"></ion-toggle>
|
||||
</body>
|
||||
</html>
|
169
core/src/components/toggle/toggle.ios.scss
Normal file
169
core/src/components/toggle/toggle.ios.scss
Normal file
@ -0,0 +1,169 @@
|
||||
@import "./toggle";
|
||||
@import "./toggle.ios.vars";
|
||||
|
||||
// iOS Toggle
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios {
|
||||
box-sizing: content-box;
|
||||
position: relative;
|
||||
|
||||
width: $toggle-ios-width;
|
||||
height: $toggle-ios-height;
|
||||
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Background Track: Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios .toggle-icon {
|
||||
@include border-radius($toggle-ios-border-radius);
|
||||
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: $toggle-ios-border-color-off;
|
||||
transition: background-color $toggle-ios-transition-duration;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Background Oval: Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios .toggle-icon::before {
|
||||
@include position($toggle-ios-border-width, $toggle-ios-border-width, $toggle-ios-border-width, $toggle-ios-border-width);
|
||||
@include border-radius($toggle-ios-border-radius);
|
||||
|
||||
position: absolute;
|
||||
|
||||
background-color: $toggle-ios-background-color-off;
|
||||
|
||||
content: "";
|
||||
transform: scale3d(1, 1, 1);
|
||||
transition: transform $toggle-ios-transition-duration;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Inner Knob: Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios .toggle-inner {
|
||||
@include position($toggle-ios-border-width, null, null, $toggle-ios-border-width);
|
||||
@include border-radius($toggle-ios-handle-border-radius);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: $toggle-ios-handle-width;
|
||||
height: $toggle-ios-handle-height;
|
||||
|
||||
background-color: $toggle-ios-handle-background-color;
|
||||
box-shadow: $toggle-ios-handle-box-shadow;
|
||||
|
||||
transition: transform $toggle-ios-transition-duration, width 120ms ease-in-out 80ms, left 110ms ease-in-out 80ms, right 110ms ease-in-out 80ms;
|
||||
|
||||
will-change: transform;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Background Track: Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-checked .toggle-icon {
|
||||
background-color: $toggle-ios-background-color-on;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Background Oval: Activated or Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-activated .toggle-icon::before,
|
||||
.toggle-ios.toggle-checked .toggle-icon::before {
|
||||
transform: scale3d(0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Inner Knob: Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-checked .toggle-inner {
|
||||
@include transform(translate3d($toggle-ios-width - $toggle-ios-handle-width - ($toggle-ios-border-width * 2), 0, 0));
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Background Oval: Activated and Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-activated.toggle-checked .toggle-inner::before {
|
||||
transform: scale3d(0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Inner Knob: Activated and Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-activated .toggle-inner {
|
||||
width: $toggle-ios-handle-width + 6;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Inner Knob: Activated and Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-activated.toggle-checked .toggle-inner {
|
||||
// when pressing down on the toggle and IS checked
|
||||
// make the knob wider and move it left a bit
|
||||
@include position-horizontal($toggle-ios-border-width - 6, null);
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle: Disabled
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-ios.toggle-disabled,
|
||||
.item-ios.item-toggle-disabled ion-label {
|
||||
opacity: $toggle-ios-disabled-opacity;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Within An Item
|
||||
// -----------------------------------------
|
||||
|
||||
.item-ios .toggle-ios[slot] {
|
||||
@include margin($toggle-ios-media-margin);
|
||||
@include padding($toggle-ios-item-end-padding-top, $toggle-ios-item-end-padding-end, $toggle-ios-item-end-padding-bottom, $toggle-ios-item-end-padding-start);
|
||||
}
|
||||
|
||||
.item-ios .toggle-ios[slot="start"] {
|
||||
@include padding($toggle-ios-item-start-padding-top, $toggle-ios-item-start-padding-end, $toggle-ios-item-start-padding-bottom, $toggle-ios-item-start-padding-start);
|
||||
}
|
||||
|
||||
|
||||
// iOS Toggle Color Mixin
|
||||
// --------------------------------------------------
|
||||
|
||||
@mixin ios-toggle-theme($color-name) {
|
||||
$color-base: ion-color($colors-ios, $color-name, base, ios);
|
||||
|
||||
.toggle-ios-#{$color-name}.toggle-checked .toggle-icon {
|
||||
background-color: $color-base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate iOS Toggle Colors
|
||||
// --------------------------------------------------
|
||||
|
||||
@each $color-name, $color-value in $colors-ios {
|
||||
@include ios-toggle-theme($color-name);
|
||||
}
|
75
core/src/components/toggle/toggle.ios.vars.scss
Normal file
75
core/src/components/toggle/toggle.ios.vars.scss
Normal file
@ -0,0 +1,75 @@
|
||||
@import "../../themes/ionic.globals.ios";
|
||||
|
||||
@import "../item/item.ios.vars";
|
||||
|
||||
// iOS Toggle
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Width of the toggle
|
||||
$toggle-ios-width: 51px !default;
|
||||
|
||||
/// @prop - Height of the toggle
|
||||
$toggle-ios-height: 32px !default;
|
||||
|
||||
/// @prop - Border width of the toggle
|
||||
$toggle-ios-border-width: 2px !default;
|
||||
|
||||
/// @prop - Border radius of the toggle
|
||||
$toggle-ios-border-radius: $toggle-ios-height / 2 !default;
|
||||
|
||||
/// @prop - Background color of the unchecked toggle
|
||||
$toggle-ios-background-color-off: $item-ios-background-color !default;
|
||||
|
||||
/// @prop - Border color of the unchecked toggle
|
||||
$toggle-ios-border-color-off: $background-ios-color-step-50 !default;
|
||||
|
||||
/// @prop - Background color of the checked toggle
|
||||
$toggle-ios-background-color-on: ion-color($colors-ios, primary, base, ios) !default;
|
||||
|
||||
/// @prop - Width of the toggle handle
|
||||
$toggle-ios-handle-width: $toggle-ios-height - ($toggle-ios-border-width * 2) !default;
|
||||
|
||||
/// @prop - Height of the toggle handle
|
||||
$toggle-ios-handle-height: $toggle-ios-handle-width !default;
|
||||
|
||||
/// @prop - Border radius of the toggle handle
|
||||
$toggle-ios-handle-border-radius: $toggle-ios-handle-height / 2 !default;
|
||||
|
||||
/// @prop - Box shadow of the toggle handle
|
||||
$toggle-ios-handle-box-shadow: 0 3px 12px rgba(0, 0, 0, .16), 0 3px 1px rgba(0, 0, 0, .1) !default;
|
||||
|
||||
/// @prop - Background color of the toggle handle
|
||||
$toggle-ios-handle-background-color: $toggle-ios-background-color-off !default;
|
||||
|
||||
/// @prop - Margin of the toggle handle
|
||||
$toggle-ios-media-margin: 0 !default;
|
||||
|
||||
/// @prop - Transition duration of the toggle icon
|
||||
$toggle-ios-transition-duration: 300ms !default;
|
||||
|
||||
/// @prop - Opacity of the disabled toggle
|
||||
$toggle-ios-disabled-opacity: .3 !default;
|
||||
|
||||
/// @prop - Padding top of the toggle positioned on the start in an item
|
||||
$toggle-ios-item-start-padding-top: 6px !default;
|
||||
|
||||
/// @prop - Padding end of the toggle positioned on the start in an item
|
||||
$toggle-ios-item-start-padding-end: 16px !default;
|
||||
|
||||
/// @prop - Padding bottom of the toggle positioned on the start in an item
|
||||
$toggle-ios-item-start-padding-bottom: 5px !default;
|
||||
|
||||
/// @prop - Padding start of the toggle positioned on the start in an item
|
||||
$toggle-ios-item-start-padding-start: 0 !default;
|
||||
|
||||
/// @prop - Padding top of the toggle positioned on the end in an item
|
||||
$toggle-ios-item-end-padding-top: 6px !default;
|
||||
|
||||
/// @prop - Padding end of the toggle positioned on the end in an item
|
||||
$toggle-ios-item-end-padding-end: ($item-ios-padding-end / 2) !default;
|
||||
|
||||
/// @prop - Padding bottom of the toggle positioned on the end in an item
|
||||
$toggle-ios-item-end-padding-bottom: 5px !default;
|
||||
|
||||
/// @prop - Padding start of the toggle positioned on the end in an item
|
||||
$toggle-ios-item-end-padding-start: $item-ios-padding-start !default;
|
140
core/src/components/toggle/toggle.md.scss
Normal file
140
core/src/components/toggle/toggle.md.scss
Normal file
@ -0,0 +1,140 @@
|
||||
@import "./toggle";
|
||||
@import "./toggle.md.vars";
|
||||
|
||||
// Material Design Toggle
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md {
|
||||
@include padding($toggle-md-padding-top, $toggle-md-padding-end, $toggle-md-padding-bottom, $toggle-md-padding-start);
|
||||
|
||||
box-sizing: content-box;
|
||||
|
||||
position: relative;
|
||||
|
||||
width: $toggle-md-track-width;
|
||||
height: $toggle-md-track-height;
|
||||
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle Background Track: Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md .toggle-icon {
|
||||
@include border-radius($toggle-md-track-height);
|
||||
|
||||
position: relative;
|
||||
display: block;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: $toggle-md-track-background-color-off;
|
||||
|
||||
transition: background-color $toggle-md-transition-duration;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle Inner Knob: Unchecked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md .toggle-inner {
|
||||
@include position(($toggle-md-handle-height - $toggle-md-track-height) / -2, null, null, 0);
|
||||
@include border-radius($toggle-md-handle-border-radius);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: $toggle-md-handle-width;
|
||||
height: $toggle-md-handle-height;
|
||||
|
||||
background-color: $toggle-md-handle-background-color-off;
|
||||
|
||||
box-shadow: $toggle-md-handle-box-shadow;
|
||||
|
||||
transition-duration: $toggle-md-transition-duration;
|
||||
transition-property: transform, background-color;
|
||||
|
||||
will-change: transform, background-color;
|
||||
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle Background Track: Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md.toggle-checked .toggle-icon {
|
||||
background-color: $toggle-md-track-background-color-on;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle Inner Knob: Checked
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md.toggle-checked .toggle-inner {
|
||||
@include transform(translate3d($toggle-md-track-width - $toggle-md-handle-width, 0, 0));
|
||||
|
||||
background-color: $toggle-md-handle-background-color-on;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle: Disabled
|
||||
// -----------------------------------------
|
||||
|
||||
.toggle-md.toggle-disabled,
|
||||
.item-md.item-toggle-disabled ion-label {
|
||||
opacity: $toggle-md-disabled-opacity;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toggle-md.toggle-disabled ion-radio {
|
||||
opacity: $toggle-md-disabled-opacity;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Toggle Within An Item
|
||||
// -----------------------------------------
|
||||
|
||||
.item-md .toggle-md[slot] {
|
||||
@include margin($toggle-md-media-margin-top, $toggle-md-media-margin-end, $toggle-md-media-margin-bottom, $toggle-md-media-margin-start);
|
||||
@include padding($toggle-md-item-end-padding-top, $toggle-md-item-end-padding-end, $toggle-md-item-end-padding-bottom, $toggle-md-item-end-padding-start);
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-md .toggle-md[slot="start"] {
|
||||
@include padding($toggle-md-item-start-padding-top, $toggle-md-item-start-padding-end, $toggle-md-item-start-padding-bottom, $toggle-md-item-start-padding-start);
|
||||
}
|
||||
|
||||
.item-md.item-toggle ion-label {
|
||||
@include margin-horizontal(0, null);
|
||||
}
|
||||
|
||||
|
||||
// Material Design Color Mixin
|
||||
// --------------------------------------------------
|
||||
|
||||
@mixin toggle-theme-md($color-name) {
|
||||
$color-base: ion-color($colors-md, $color-name, base, md);
|
||||
$color-tint: ion-color($colors-md, $color-name, tint, md);
|
||||
|
||||
.toggle-md-#{$color-name}.toggle-checked .toggle-icon {
|
||||
background-color: $color-tint;
|
||||
}
|
||||
|
||||
.toggle-md-#{$color-name}.toggle-checked .toggle-inner {
|
||||
background-color: $color-base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate Material Design Toggle Auxiliary Colors
|
||||
// --------------------------------------------------
|
||||
|
||||
@each $color-name, $color-value in $colors-md {
|
||||
@include toggle-theme-md($color-name);
|
||||
}
|
93
core/src/components/toggle/toggle.md.vars.scss
Normal file
93
core/src/components/toggle/toggle.md.vars.scss
Normal file
@ -0,0 +1,93 @@
|
||||
@import "../../themes/ionic.globals.md";
|
||||
|
||||
@import "../item/item.md.vars";
|
||||
|
||||
// Material Design Toggle
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Color of the active toggle
|
||||
$toggle-md-active-color: ion-color($colors-md, primary, base, md) !default;
|
||||
|
||||
/// @prop - Width of the toggle track
|
||||
$toggle-md-track-width: 36px !default;
|
||||
|
||||
/// @prop - Height of the toggle track
|
||||
$toggle-md-track-height: 14px !default;
|
||||
|
||||
/// @prop - Background color of the toggle track
|
||||
$toggle-md-track-background-color-off: $item-md-border-color !default;
|
||||
|
||||
/// @prop - Background color of the checked toggle track
|
||||
$toggle-md-track-background-color-on: ion-color-alpha($colors-md, primary, $alpha-md-medium, md) !default;
|
||||
|
||||
/// @prop - Width of the toggle handle
|
||||
$toggle-md-handle-width: 20px !default;
|
||||
|
||||
/// @prop - Height of the toggle handle
|
||||
$toggle-md-handle-height: 20px !default;
|
||||
|
||||
/// @prop - Border radius of the toggle handle
|
||||
$toggle-md-handle-border-radius: 50% !default;
|
||||
|
||||
/// @prop - Box shadow of the toggle handle
|
||||
$toggle-md-handle-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12) !default;
|
||||
|
||||
/// @prop - Background color of the toggle handle
|
||||
$toggle-md-handle-background-color-off: $background-md-color !default;
|
||||
|
||||
/// @prop - Background color of the checked toggle handle
|
||||
$toggle-md-handle-background-color-on: $toggle-md-active-color !default;
|
||||
|
||||
/// @prop - Margin top of the toggle
|
||||
$toggle-md-media-margin-top: 0 !default;
|
||||
|
||||
/// @prop - Margin end of the toggle
|
||||
$toggle-md-media-margin-end: $toggle-md-media-margin-top !default;
|
||||
|
||||
/// @prop - Margin bottom of the toggle
|
||||
$toggle-md-media-margin-bottom: $toggle-md-media-margin-top !default;
|
||||
|
||||
/// @prop - Margin start of the toggle
|
||||
$toggle-md-media-margin-start: $toggle-md-media-margin-end !default;
|
||||
|
||||
/// @prop - Transition duration of the toggle icon
|
||||
$toggle-md-transition-duration: 300ms !default;
|
||||
|
||||
/// @prop - Opacity of the disabled toggle
|
||||
$toggle-md-disabled-opacity: .3 !default;
|
||||
|
||||
/// @prop - Padding top of standalone toggle
|
||||
$toggle-md-padding-top: 12px !default;
|
||||
|
||||
/// @prop - Padding end of standalone toggle
|
||||
$toggle-md-padding-end: $toggle-md-padding-top !default;
|
||||
|
||||
/// @prop - Padding bottom of standalone toggle
|
||||
$toggle-md-padding-bottom: $toggle-md-padding-top !default;
|
||||
|
||||
/// @prop - Padding start of standalone toggle
|
||||
$toggle-md-padding-start: $toggle-md-padding-end !default;
|
||||
|
||||
/// @prop - Padding top of the toggle positioned on the start in an item
|
||||
$toggle-md-item-start-padding-top: 12px !default;
|
||||
|
||||
/// @prop - Padding end of the toggle positioned on the start in an item
|
||||
$toggle-md-item-start-padding-end: 18px !default;
|
||||
|
||||
/// @prop - Padding bottom of the toggle positioned on the start in an item
|
||||
$toggle-md-item-start-padding-bottom: 12px !default;
|
||||
|
||||
/// @prop - Padding start the toggle positioned on the start in an item
|
||||
$toggle-md-item-start-padding-start: 2px !default;
|
||||
|
||||
/// @prop - Padding top of the toggle positioned on the end in an item
|
||||
$toggle-md-item-end-padding-top: 12px !default;
|
||||
|
||||
/// @prop - Padding end of the toggle positioned on the end in an item
|
||||
$toggle-md-item-end-padding-end: ($item-md-padding-end / 2) !default;
|
||||
|
||||
/// @prop - Padding bottom of the toggle positioned on the end in an item
|
||||
$toggle-md-item-end-padding-bottom: 12px !default;
|
||||
|
||||
/// @prop - Padding start of the toggle positioned on the end in an item
|
||||
$toggle-md-item-end-padding-start: $item-md-padding-start !default;
|
74
core/src/components/toggle/toggle.scss
Normal file
74
core/src/components/toggle/toggle.scss
Normal file
@ -0,0 +1,74 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
// Toggle
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-toggle {
|
||||
display: inline-block;
|
||||
|
||||
contain: content;
|
||||
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
ion-toggle ion-gesture {
|
||||
display: block;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
.toggle-cover {
|
||||
@include position-horizontal(0, null);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
border: 0;
|
||||
outline: none;
|
||||
|
||||
font-family: inherit;
|
||||
font-style: inherit;
|
||||
font-variant: inherit;
|
||||
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ion-toggle input {
|
||||
@include position(0, null, null, 0);
|
||||
@include margin(0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
|
||||
pointer-events: none;
|
||||
// touch-action: pan-x;
|
||||
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
ion-toggle :focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.toggle-key input {
|
||||
border: 2px solid #5e9ed6;
|
||||
}
|
236
core/src/components/toggle/toggle.tsx
Normal file
236
core/src/components/toggle/toggle.tsx
Normal file
@ -0,0 +1,236 @@
|
||||
import { BlurEvent, CheckboxInput, CheckedInputChangeEvent, FocusEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||
import { Component, Event, EventEmitter, Prop, State, Watch } from '@stencil/core';
|
||||
import { GestureDetail } from '../../index';
|
||||
import { hapticSelection } from '../../utils/haptic';
|
||||
import { deferEvent } from '../../utils/helpers';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-toggle',
|
||||
styleUrls: {
|
||||
ios: 'toggle.ios.scss',
|
||||
md: 'toggle.md.scss'
|
||||
},
|
||||
host: {
|
||||
theme: 'toggle'
|
||||
}
|
||||
})
|
||||
export class Toggle implements CheckboxInput {
|
||||
|
||||
private didLoad: boolean;
|
||||
private gestureConfig: any;
|
||||
private inputId: string;
|
||||
private nativeInput: HTMLInputElement;
|
||||
private pivotX: number;
|
||||
|
||||
@State() activated = false;
|
||||
|
||||
@State() keyFocus: boolean;
|
||||
|
||||
/**
|
||||
* The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Prop() color: string;
|
||||
|
||||
/**
|
||||
* The mode determines which platform styles to use.
|
||||
* Possible values are: `"ios"` or `"md"`.
|
||||
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
*/
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
* The name of the control, which is submitted with the form data.
|
||||
*/
|
||||
@Prop({ mutable: true }) name: string;
|
||||
|
||||
/**
|
||||
* If true, the toggle is selected. Defaults to `false`.
|
||||
*/
|
||||
@Prop({ mutable: true }) checked = false;
|
||||
|
||||
/*
|
||||
* If true, the user cannot interact with the toggle. Default false.
|
||||
*/
|
||||
@Prop({ mutable: true }) disabled = false;
|
||||
|
||||
/**
|
||||
* the value of the toggle.
|
||||
*/
|
||||
@Prop() value = 'on';
|
||||
|
||||
/**
|
||||
* Emitted when the value property has changed.
|
||||
*/
|
||||
@Event() ionChange: EventEmitter<CheckedInputChangeEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the toggle has focus.
|
||||
*/
|
||||
@Event() ionFocus: EventEmitter<FocusEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the toggle loses focus.
|
||||
*/
|
||||
@Event() ionBlur: EventEmitter<BlurEvent>;
|
||||
|
||||
/**
|
||||
* Emitted when the styles change.
|
||||
*/
|
||||
@Event() ionStyle: EventEmitter<StyleEvent>;
|
||||
|
||||
|
||||
constructor() {
|
||||
this.gestureConfig = {
|
||||
'onStart': this.onDragStart.bind(this),
|
||||
'onMove': this.onDragMove.bind(this),
|
||||
'onEnd': this.onDragEnd.bind(this),
|
||||
'gestureName': 'toggle',
|
||||
'passive': false,
|
||||
'gesturePriority': 30,
|
||||
'type': 'pan',
|
||||
'direction': 'x',
|
||||
'threshold': 0,
|
||||
'attachTo': 'parent'
|
||||
};
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.ionStyle = deferEvent(this.ionStyle);
|
||||
this.inputId = `ion-tg-${toggleIds++}`;
|
||||
if (this.name === undefined) {
|
||||
this.name = this.inputId;
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.didLoad = true;
|
||||
|
||||
const parentItem = this.nativeInput.closest('ion-item');
|
||||
if (parentItem) {
|
||||
const itemLabel = parentItem.querySelector('ion-label');
|
||||
if (itemLabel) {
|
||||
itemLabel.id = this.inputId + '-lbl';
|
||||
this.nativeInput.setAttribute('aria-labelledby', itemLabel.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Watch('checked')
|
||||
checkedChanged(isChecked: boolean) {
|
||||
if (this.didLoad) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value
|
||||
});
|
||||
}
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@Watch('disabled')
|
||||
emitStyle() {
|
||||
this.ionStyle.emit({
|
||||
'toggle-disabled': this.disabled,
|
||||
'toggle-checked': this.checked,
|
||||
'toggle-activated': this.activated
|
||||
});
|
||||
}
|
||||
|
||||
private onDragStart(detail: GestureDetail) {
|
||||
this.pivotX = detail.currentX;
|
||||
this.activated = true;
|
||||
|
||||
// touch-action does not work in iOS
|
||||
detail.event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
private onDragMove(detail: GestureDetail) {
|
||||
const currentX = detail.currentX;
|
||||
if (shouldToggle(this.checked, currentX - this.pivotX, -15)) {
|
||||
this.checked = !this.checked;
|
||||
this.pivotX = currentX;
|
||||
hapticSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private onDragEnd(detail: GestureDetail) {
|
||||
const delta = detail.currentX - this.pivotX;
|
||||
if (shouldToggle(this.checked, delta, 4)) {
|
||||
this.checked = !this.checked;
|
||||
hapticSelection();
|
||||
}
|
||||
|
||||
this.activated = false;
|
||||
this.nativeInput.focus();
|
||||
}
|
||||
|
||||
onChange() {
|
||||
this.checked = !this.checked;
|
||||
}
|
||||
|
||||
onKeyUp() {
|
||||
this.keyFocus = true;
|
||||
}
|
||||
|
||||
onFocus() {
|
||||
this.ionFocus.emit();
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
this.keyFocus = false;
|
||||
this.ionBlur.emit();
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
'toggle-activated': this.activated,
|
||||
'toggle-checked': this.checked,
|
||||
'toggle-disabled': this.disabled,
|
||||
'toggle-key': this.keyFocus
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-gesture {...this.gestureConfig}
|
||||
disabled={this.disabled} tabIndex={-1}>
|
||||
<div class='toggle-icon'>
|
||||
<div class='toggle-inner'/>
|
||||
</div>
|
||||
<div class='toggle-cover'/>
|
||||
</ion-gesture>,
|
||||
<input
|
||||
type='checkbox'
|
||||
onChange={this.onChange.bind(this)}
|
||||
onFocus={this.onFocus.bind(this)}
|
||||
onBlur={this.onBlur.bind(this)}
|
||||
onKeyUp={this.onKeyUp.bind(this)}
|
||||
checked={this.checked}
|
||||
id={this.inputId}
|
||||
name={this.name}
|
||||
value={this.value}
|
||||
disabled={this.disabled}
|
||||
ref={r => this.nativeInput = (r as any)}/>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function shouldToggle(checked: boolean, deltaX: number, margin: number): boolean {
|
||||
const isRTL = document.dir === 'rtl';
|
||||
|
||||
if (checked) {
|
||||
return (!isRTL && (margin > deltaX)) ||
|
||||
(isRTL && (- margin < deltaX));
|
||||
} else {
|
||||
return (!isRTL && (- margin < deltaX)) ||
|
||||
(isRTL && (margin > deltaX));
|
||||
}
|
||||
}
|
||||
|
||||
let toggleIds = 0;
|
Reference in New Issue
Block a user