mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
fix(datetime): time picker uses new iOS 15 style (#23996)
resolves #23768
This commit is contained in:
@ -139,57 +139,12 @@
|
||||
@include padding($datetime-ios-padding / 2, $datetime-ios-padding, $datetime-ios-padding, $datetime-ios-padding);
|
||||
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:host .datetime-time .time-header {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:host .time-base {
|
||||
@include border-radius($datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius);
|
||||
@include margin(0, $datetime-ios-padding / 2, 0, 0);
|
||||
|
||||
width: $datetime-ios-time-width;
|
||||
height: $datetime-ios-time-height;
|
||||
}
|
||||
|
||||
:host .time-column {
|
||||
@include border-radius($datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius);
|
||||
}
|
||||
|
||||
:host .time-item {
|
||||
line-height: $datetime-ios-time-height;
|
||||
}
|
||||
|
||||
// Month and Year Picker
|
||||
// -----------------------------------
|
||||
|
||||
:host .datetime-year-body .datetime-picker-col {
|
||||
@include padding(0, $datetime-ios-padding, 0, $datetime-ios-padding);
|
||||
}
|
||||
|
||||
:host .datetime-picker-before {
|
||||
background: linear-gradient(to bottom, var(--background, var(--ion-background-color, #fff)) 20%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0.8) 100%);
|
||||
}
|
||||
|
||||
:host .datetime-picker-after {
|
||||
background: linear-gradient(to top, var(--background, var(--ion-background-color, #fff)) 30%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0.8) 100%);
|
||||
}
|
||||
|
||||
:host .datetime-picker-highlight {
|
||||
@include border-radius($datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius, $datetime-ios-time-border-radius);
|
||||
@include position(50%, 0, 0, 0);
|
||||
@include margin(0, auto, 0, auto);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: calc(100% - #{$datetime-ios-padding * 2});
|
||||
height: 34px;
|
||||
|
||||
transform: translateY(-50%);
|
||||
|
||||
background: var(--ion-color-step-150, #eeeeef);
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
// Footer
|
||||
// -----------------------------------
|
||||
:host .datetime-buttons {
|
||||
|
@ -117,57 +117,8 @@
|
||||
color: #{$text-color-step-350};
|
||||
}
|
||||
|
||||
:host .time-base {
|
||||
@include border-radius($datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius);
|
||||
@include margin(0, $datetime-md-padding / 2, 0, 0);
|
||||
|
||||
width: $datetime-md-time-width;
|
||||
height: $datetime-md-time-height;
|
||||
}
|
||||
|
||||
:host .time-column {
|
||||
@include border-radius($datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius);
|
||||
}
|
||||
|
||||
:host .time-item {
|
||||
line-height: $datetime-md-time-height;
|
||||
}
|
||||
|
||||
:host .time-ampm ion-segment {
|
||||
@include border-radius($datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius, $datetime-md-time-border-radius);
|
||||
|
||||
border: 1px solid rgba($text-color-rgb, 0.1);
|
||||
}
|
||||
|
||||
:host .time-ampm ion-segment-button {
|
||||
--indicator-height: 0px;
|
||||
--background-checked: #{current-color(base, 0.1)};
|
||||
|
||||
min-height: $datetime-md-time-height + 2;
|
||||
}
|
||||
|
||||
:host .time-ampm ion-segment-button.segment-button-checked {
|
||||
background: var(--background-checked);
|
||||
}
|
||||
|
||||
// Month and Year
|
||||
// -----------------------------------
|
||||
:host .datetime-picker-col {
|
||||
@include border-radius($datetime-md-wheel-border-radius, $datetime-md-wheel-border-radius, $datetime-md-wheel-border-radius, $datetime-md-wheel-border-radius);
|
||||
@include padding(null, $datetime-md-wheel-padding, null, $datetime-md-wheel-padding);
|
||||
}
|
||||
|
||||
:host .picker-col-item {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
:host .datetime-picker-before {
|
||||
background: linear-gradient(to bottom, var(--background, var(--ion-background-color, #fff)) 20%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0) 90%);
|
||||
}
|
||||
|
||||
:host .datetime-picker-after {
|
||||
background: linear-gradient(to top, var(--background, var(--ion-background-color, #fff)) 30%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0) 90%);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some margin when only selecting month/year
|
||||
@ -194,7 +145,3 @@
|
||||
:host .datetime-view-buttons ion-button {
|
||||
color: $text-color-step-200;
|
||||
}
|
||||
|
||||
:host .picker-col-item-active {
|
||||
color: current-color(base);
|
||||
}
|
||||
|
@ -15,18 +15,3 @@ $datetime-md-header-padding: 20px !default;
|
||||
|
||||
/// @prop - Padding for content
|
||||
$datetime-md-padding: 16px !default;
|
||||
|
||||
/// @prop - Height of the time picker
|
||||
$datetime-md-time-height: 28px !default;
|
||||
|
||||
/// @prop - Width of the time picker
|
||||
$datetime-md-time-width: 68px !default;
|
||||
|
||||
/// @prop - Border radius of the time picker
|
||||
$datetime-md-time-border-radius: 4px !default;
|
||||
|
||||
/// @prop - Border radius of the month and year wheel
|
||||
$datetime-md-wheel-border-radius: 8px !default;
|
||||
|
||||
/// @prop - Padding of the month and year wheel
|
||||
$datetime-md-wheel-padding: 8px !default;
|
||||
|
@ -35,7 +35,6 @@
|
||||
}
|
||||
|
||||
:host .calendar-body,
|
||||
:host .time-column,
|
||||
:host .datetime-year {
|
||||
opacity: 0;
|
||||
}
|
||||
@ -45,8 +44,7 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:host(.datetime-ready) .calendar-body,
|
||||
:host(.datetime-ready) .time-column {
|
||||
:host(.datetime-ready) .calendar-body {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -289,93 +287,12 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
:host .time-base {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border: 2px solid transparent;
|
||||
|
||||
background: rgba($text-color-rgb, 0.065);
|
||||
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
|
||||
text-align: center;
|
||||
|
||||
overflow-y: hidden;
|
||||
:host(.datetime-presentation-time) .datetime-time {
|
||||
@include padding(0);
|
||||
}
|
||||
|
||||
:host .time-base.time-base-active {
|
||||
border: 2px solid current-color(base);
|
||||
}
|
||||
|
||||
:host .time-wrapper {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:host .time-column {
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
|
||||
outline: none;
|
||||
scroll-snap-type: y mandatory;
|
||||
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@media (any-hover: hover) {
|
||||
:host .time-column:focus {
|
||||
outline: none;
|
||||
|
||||
background: current-color(base, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
:host .time-column.time-column-active {
|
||||
background: transparent;
|
||||
color: current-color(base);
|
||||
}
|
||||
|
||||
:host .time-base.time-base-active .time-column:not(.time-column-active),
|
||||
:host .time-base.time-base-active .time-separator {
|
||||
pointer-events: none;
|
||||
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
:host .time-column::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host .time-column-hours .time-item {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
:host .time-column-minutes .time-item {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
:host .time-item {
|
||||
scroll-snap-align: center;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:host .time-separator {
|
||||
height: 100%;
|
||||
:host ion-popover {
|
||||
--height: 200px;
|
||||
}
|
||||
|
||||
:host .time-header {
|
||||
@ -385,15 +302,27 @@
|
||||
}
|
||||
|
||||
:host .time-body {
|
||||
@include border-radius(8px);
|
||||
@include padding(6px, 12px, 6px, 12px);
|
||||
|
||||
display: flex;
|
||||
|
||||
border: none;
|
||||
|
||||
background: var(--ion-color-step-300, #edeef0);
|
||||
|
||||
color: $text-color;
|
||||
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
:host .time-ampm {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
:host .time-ampm ion-segment-button {
|
||||
min-width: 50px;
|
||||
:host .time-body-active {
|
||||
color: current-color(base);
|
||||
}
|
||||
|
||||
:host(.in-item) {
|
||||
@ -405,119 +334,3 @@
|
||||
:host(.show-month-and-year) .calendar-action-buttons ion-item {
|
||||
--color: #{current-color(base)};
|
||||
}
|
||||
|
||||
:host .datetime-year-body .datetime-picker-col {
|
||||
@include margin(0, 10px, 0, 10px);
|
||||
}
|
||||
|
||||
:host .datetime-picker-before {
|
||||
@include position(0, null, null, 0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
|
||||
height: 82px;
|
||||
|
||||
background: linear-gradient(to bottom, var(--background, var(--ion-background-color, #fff)) 20%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0.7) 100%);
|
||||
|
||||
z-index: 10;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:host .datetime-picker-after {
|
||||
@include position(116px, null, null, 0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
|
||||
height: 115px;
|
||||
|
||||
background: linear-gradient(to top, var(--background, var(--ion-background-color, #fff)) 30%, rgba(var(--background-rgb, var(--ion-background-color-rgb, 255, 255, 255)), 0.7) 100%);
|
||||
|
||||
z-index: 10;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:host .datetime-year-body {
|
||||
display: flex;
|
||||
|
||||
position: relative;
|
||||
|
||||
align-items: center;
|
||||
|
||||
justify-content: center;
|
||||
|
||||
font-size: 22px;
|
||||
|
||||
/**
|
||||
* This is required otherwise the
|
||||
* highlight will appear behind
|
||||
* the datetime.
|
||||
*/
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
:host .datetime-picker-col {
|
||||
scroll-snap-type: y mandatory;
|
||||
|
||||
/**
|
||||
* Need to explicitly set overflow-x: hidden
|
||||
* for older implementations of scroll snapping.
|
||||
*/
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
// Hide scrollbars on Firefox
|
||||
scrollbar-width: none;
|
||||
|
||||
height: 200px;
|
||||
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@media (any-hover: hover) {
|
||||
:host .datetime-picker-col:focus {
|
||||
background: current-color(base, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide scrollbars on Chrome and Safari
|
||||
*/
|
||||
:host .datetime-picker-col::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host .picker-col-item {
|
||||
height: 38px;
|
||||
|
||||
line-height: 38px;
|
||||
|
||||
scroll-snap-align: center;
|
||||
}
|
||||
|
||||
:host .picker-col-item-empty {
|
||||
scroll-snap-align: none;
|
||||
}
|
||||
|
||||
:host .datetime-year-body .datetime-picker-col:first-of-type {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
:host .datetime-year-body .datetime-picker-col:last-of-type {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding :last-of-type is needed here so that
|
||||
* we can achieve higher specificity than the
|
||||
* previous selectors and avoid using !important.
|
||||
*/
|
||||
:host(.datetime-presentation-year) .datetime-picker-col:last-of-type,
|
||||
:host(.datetime-presentation-month) .datetime-picker-col:last-of-type {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -10,8 +10,9 @@ import {
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color, DatetimeChangeEventDetail, DatetimeParts, Mode, StyleEventDetail } from '../../interface';
|
||||
import { startFocusVisible } from '../../utils/focus-visible';
|
||||
import { getElementRoot, raf, renderHiddenInput } from '../../utils/helpers';
|
||||
import { getElementRoot, renderHiddenInput } from '../../utils/helpers';
|
||||
import { createColorClasses } from '../../utils/theme';
|
||||
import { PickerColumnItem } from '../picker-column-internal/picker-column-internal-interfaces';
|
||||
|
||||
import {
|
||||
generateMonths,
|
||||
@ -25,6 +26,7 @@ import {
|
||||
import {
|
||||
addTimePadding,
|
||||
getFormattedHour,
|
||||
getFormattedTime,
|
||||
getMonthAndDay,
|
||||
getMonthAndYear
|
||||
} from './utils/format';
|
||||
@ -75,11 +77,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private inputId = `ion-dt-${datetimeIds++}`;
|
||||
private calendarBodyRef?: HTMLElement;
|
||||
private timeBaseRef?: HTMLElement;
|
||||
private timeHourRef?: HTMLElement;
|
||||
private timeMinuteRef?: HTMLElement;
|
||||
private monthRef?: HTMLElement;
|
||||
private yearRef?: HTMLElement;
|
||||
private popoverRef?: HTMLIonPopoverElement;
|
||||
private clearFocusVisible?: () => void;
|
||||
private overlayIsPresenting = false;
|
||||
|
||||
@ -91,8 +89,6 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private destroyCalendarIO?: () => void;
|
||||
private destroyKeyboardMO?: () => void;
|
||||
private destroyTimeScroll?: () => void;
|
||||
private destroyMonthAndYearScroll?: () => void;
|
||||
|
||||
private minParts?: any;
|
||||
private maxParts?: any;
|
||||
@ -122,6 +118,7 @@ export class Datetime implements ComponentInterface {
|
||||
@Element() el!: HTMLIonDatetimeElement;
|
||||
|
||||
@State() isPresented = false;
|
||||
@State() isTimePopoverOpen = false;
|
||||
|
||||
/**
|
||||
* The color to use from your application's color palette.
|
||||
@ -807,7 +804,7 @@ export class Datetime implements ComponentInterface {
|
||||
* if the datetime has been hidden/presented by a modal or popover.
|
||||
*/
|
||||
private destroyListeners = () => {
|
||||
const { destroyCalendarIO, destroyKeyboardMO, destroyTimeScroll, destroyMonthAndYearScroll } = this;
|
||||
const { destroyCalendarIO, destroyKeyboardMO } = this;
|
||||
|
||||
if (destroyCalendarIO !== undefined) {
|
||||
destroyCalendarIO();
|
||||
@ -816,14 +813,6 @@ export class Datetime implements ComponentInterface {
|
||||
if (destroyKeyboardMO !== undefined) {
|
||||
destroyKeyboardMO();
|
||||
}
|
||||
|
||||
if (destroyTimeScroll !== undefined) {
|
||||
destroyTimeScroll();
|
||||
}
|
||||
|
||||
if (destroyMonthAndYearScroll !== undefined) {
|
||||
destroyMonthAndYearScroll();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
@ -841,9 +830,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
this.initializeCalendarIOListeners();
|
||||
this.initializeKeyboardListeners();
|
||||
this.initializeTimeScrollListener();
|
||||
this.initializeOverlayListener();
|
||||
this.initializeMonthAndYearScrollListeners();
|
||||
|
||||
/**
|
||||
* TODO: Datetime needs a frame to ensure that it
|
||||
@ -911,253 +898,6 @@ export class Datetime implements ComponentInterface {
|
||||
});
|
||||
}
|
||||
|
||||
private initializeMonthAndYearScrollListeners = () => {
|
||||
const { monthRef, yearRef, workingParts } = this;
|
||||
const { year, month } = workingParts;
|
||||
|
||||
/**
|
||||
* Scroll initial month and year into view.
|
||||
* scrollIntoView() will scroll entire page
|
||||
* if element is not in viewport. Use scrollTop instead.
|
||||
*/
|
||||
let activeYearEl = yearRef?.querySelector(`.picker-col-item[data-value="${year}"]`) as HTMLElement | null;
|
||||
if (activeYearEl) {
|
||||
yearRef!.scrollTop = activeYearEl.offsetTop - (activeYearEl.clientHeight * 2);
|
||||
activeYearEl.classList.add(PICKER_COL_ACTIVE);
|
||||
}
|
||||
|
||||
let activeMonthEl = monthRef?.querySelector(`.picker-col-item[data-value="${month}"]`) as HTMLElement | null;
|
||||
if (activeMonthEl) {
|
||||
monthRef!.scrollTop = activeMonthEl.offsetTop - (activeMonthEl.clientHeight * 2);
|
||||
activeMonthEl.classList.add(PICKER_COL_ACTIVE)
|
||||
}
|
||||
|
||||
let timeout: any;
|
||||
const scrollCallback = (colType: string) => {
|
||||
raf(() => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = undefined;
|
||||
}
|
||||
|
||||
const activeCol = colType === 'month' ? monthRef : yearRef;
|
||||
if (!activeCol) { return; }
|
||||
|
||||
const bbox = activeCol.getBoundingClientRect();
|
||||
/**
|
||||
* Select item in the center of the column
|
||||
* which is the month/year that we want to select
|
||||
*/
|
||||
const centerX = bbox.x + (bbox.width / 2);
|
||||
const centerY = bbox.y + (bbox.height / 2);
|
||||
|
||||
const activeElement = this.el!.shadowRoot!.elementFromPoint(centerX, centerY) as HTMLElement;
|
||||
const prevActiveEl = colType === 'month' ? activeMonthEl : activeYearEl;
|
||||
if (prevActiveEl !== null) {
|
||||
prevActiveEl.classList.remove(PICKER_COL_ACTIVE);
|
||||
}
|
||||
|
||||
if (colType === 'month') {
|
||||
activeMonthEl = activeElement;
|
||||
} else if (colType === 'year') {
|
||||
activeYearEl = activeElement;
|
||||
}
|
||||
|
||||
activeElement.classList.add(PICKER_COL_ACTIVE);
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
const dataValue = activeElement.getAttribute('data-value');
|
||||
|
||||
/**
|
||||
* If no value it is
|
||||
* possible we hit one of the
|
||||
* empty padding columns.
|
||||
*/
|
||||
if (dataValue === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = parseInt(dataValue, 10);
|
||||
const { presentation } = this;
|
||||
if (colType === 'month') {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
month: value
|
||||
});
|
||||
|
||||
/**
|
||||
* If developers are only selecting month/month-year
|
||||
* then we need to call ionChange as they will
|
||||
* not be selecting dates too.
|
||||
*/
|
||||
if (presentation === 'month' || presentation === 'month-year') {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
month: value
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
year: value
|
||||
});
|
||||
if (presentation === 'year' || presentation === 'month-year') {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
year: value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the year changed, it is possible that
|
||||
* the allowed month values have changed and the scroll
|
||||
* position got reset
|
||||
*/
|
||||
raf(() => {
|
||||
const { month: workingMonth, year: workingYear } = this.workingParts;
|
||||
const monthEl = monthRef?.querySelector(`.picker-col-item[data-value='${workingMonth}']`);
|
||||
const yearEl = yearRef?.querySelector(`.picker-col-item[data-value='${workingYear}']`);
|
||||
|
||||
if (monthEl && monthRef) {
|
||||
this.centerPickerItemInView(monthEl as HTMLElement, monthRef, 'auto');
|
||||
}
|
||||
|
||||
if (yearEl && yearRef) {
|
||||
this.centerPickerItemInView(yearEl as HTMLElement, yearRef, 'auto');
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Add scroll listeners to the month and year containers.
|
||||
* Wrap this in an raf so that the scroll callback
|
||||
* does not fire when we do our initial scrollIntoView above.
|
||||
*/
|
||||
raf(() => {
|
||||
const monthScroll = () => scrollCallback('month');
|
||||
const yearScroll = () => scrollCallback('year');
|
||||
monthRef?.addEventListener('scroll', monthScroll);
|
||||
yearRef?.addEventListener('scroll', yearScroll);
|
||||
|
||||
this.destroyMonthAndYearScroll = () => {
|
||||
monthRef?.removeEventListener('scroll', monthScroll);
|
||||
yearRef?.removeEventListener('scroll', yearScroll);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private initializeTimeScrollListener = () => {
|
||||
const { timeBaseRef, timeHourRef, timeMinuteRef } = this;
|
||||
if (!timeBaseRef || !timeHourRef || !timeMinuteRef) { return; }
|
||||
|
||||
const { hour, minute } = this.workingParts;
|
||||
|
||||
/**
|
||||
* Scroll initial hour and minute into view.
|
||||
* scrollIntoView() will scroll entire page
|
||||
* if element is not in viewport. Use scrollTop instead.
|
||||
*/
|
||||
raf(() => {
|
||||
const initialHour = timeHourRef.querySelector(`.time-item[data-value="${hour}"]`) as HTMLElement | null;
|
||||
if (initialHour) {
|
||||
timeHourRef.scrollTop = initialHour.offsetTop;
|
||||
}
|
||||
const initialMinute = timeMinuteRef.querySelector(`.time-item[data-value="${minute}"]`) as HTMLElement | null;
|
||||
if (initialMinute) {
|
||||
timeMinuteRef.scrollTop = initialMinute.offsetTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight the container and
|
||||
* appropriate column when scrolling.
|
||||
*/
|
||||
let timeout: any;
|
||||
const scrollCallback = (colType: string) => {
|
||||
raf(() => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = undefined;
|
||||
}
|
||||
|
||||
const activeCol = colType === 'hour' ? timeHourRef : timeMinuteRef;
|
||||
const otherCol = colType === 'hour' ? timeMinuteRef : timeHourRef;
|
||||
|
||||
timeBaseRef.classList.add('time-base-active');
|
||||
activeCol.classList.add('time-column-active');
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
timeBaseRef.classList.remove('time-base-active');
|
||||
activeCol.classList.remove('time-column-active');
|
||||
otherCol.classList.remove('time-column-active');
|
||||
|
||||
const bbox = activeCol.getBoundingClientRect();
|
||||
|
||||
/**
|
||||
* Do not use floating point
|
||||
* here as some browsers may clamp
|
||||
* or round down.
|
||||
*/
|
||||
const x = Math.ceil(bbox.x + 1);
|
||||
const y = Math.ceil(bbox.y + 1);
|
||||
const activeElement = this.el!.shadowRoot!.elementFromPoint(x, y)!;
|
||||
const value = parseInt(activeElement.getAttribute('data-value')!, 10);
|
||||
|
||||
/**
|
||||
* When scrolling to a month that is out of
|
||||
* bounds, the hour/minute column values may
|
||||
* be updated, triggering a scroll callback.
|
||||
* Check to make sure there is a valid
|
||||
* hour/minute element so we do not emit NaN.
|
||||
*/
|
||||
if (Number.isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (colType === 'hour') {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
hour: value
|
||||
});
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
hour: value
|
||||
});
|
||||
} else {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
minute: value
|
||||
});
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
minute: value
|
||||
});
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add scroll listeners to the hour and minute containers.
|
||||
* Wrap this in an raf so that the scroll callback
|
||||
* does not fire when we do our initial scrollIntoView above.
|
||||
*/
|
||||
raf(() => {
|
||||
const hourScroll = () => scrollCallback('hour');
|
||||
const minuteScroll = () => scrollCallback('minute');
|
||||
|
||||
timeHourRef.addEventListener('scroll', hourScroll);
|
||||
timeMinuteRef.addEventListener('scroll', minuteScroll);
|
||||
|
||||
this.destroyTimeScroll = () => {
|
||||
timeHourRef.removeEventListener('scroll', hourScroll);
|
||||
timeMinuteRef.removeEventListener('scroll', minuteScroll);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private processValue = (value?: string | null) => {
|
||||
const valueToProcess = value || getToday();
|
||||
const { month, day, year, hour, minute, tzOffset } = parseDate(valueToProcess);
|
||||
@ -1281,61 +1021,70 @@ export class Datetime implements ComponentInterface {
|
||||
this.showMonthAndYear = !this.showMonthAndYear;
|
||||
}
|
||||
|
||||
private centerPickerItemInView(target: HTMLElement, container: HTMLElement, behavior: ScrollBehavior = 'smooth') {
|
||||
container.scroll({
|
||||
// (Vertical offset from parent) - (three empty picker rows) + (half the height of the target to ensure the scroll triggers)
|
||||
top: target.offsetTop - (3 * target.clientHeight) + (target.clientHeight / 2),
|
||||
left: 0,
|
||||
behavior
|
||||
});
|
||||
}
|
||||
|
||||
private renderYearView() {
|
||||
const { presentation } = this;
|
||||
const { presentation, workingParts } = this;
|
||||
const calendarYears = getCalendarYears(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues);
|
||||
const showMonth = presentation !== 'year';
|
||||
const showYear = presentation !== 'month';
|
||||
|
||||
const months = getPickerMonths(this.locale, workingParts, this.minParts, this.maxParts, this.parsedMonthValues);
|
||||
const years = calendarYears.map(year => {
|
||||
return {
|
||||
text: `${year}`,
|
||||
value: year
|
||||
}
|
||||
})
|
||||
return (
|
||||
<div class="datetime-year">
|
||||
<div class="datetime-year-body">
|
||||
<div class="datetime-picker-before"></div>
|
||||
<div class="datetime-picker-after"></div>
|
||||
<div class="datetime-picker-highlight"></div>
|
||||
{showMonth && <div class="datetime-picker-col month-col" ref={el => this.monthRef = el} tabindex="0">
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
{getPickerMonths(this.locale, this.workingParts, this.minParts, this.maxParts, this.parsedMonthValues).map(month => {
|
||||
return (
|
||||
<div
|
||||
class="picker-col-item"
|
||||
data-value={month.value}
|
||||
onClick={(ev: Event) => this.centerPickerItemInView(ev.target as HTMLElement, this.monthRef as HTMLElement)}
|
||||
>{month.text}</div>
|
||||
)
|
||||
})}
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
</div>}
|
||||
{showYear && <div class="datetime-picker-col year-col" ref={el => this.yearRef = el} tabindex="0">
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
{calendarYears.map(year => {
|
||||
return (
|
||||
<div
|
||||
class="picker-col-item"
|
||||
data-value={year}
|
||||
onClick={(ev: Event) => this.centerPickerItemInView(ev.target as HTMLElement, this.yearRef as HTMLElement)}
|
||||
>{year}</div>
|
||||
)
|
||||
})}
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
<div class="picker-col-item picker-col-item-empty"> </div>
|
||||
</div>}
|
||||
<ion-picker-internal>
|
||||
{
|
||||
showMonth &&
|
||||
<ion-picker-column-internal
|
||||
color={this.color}
|
||||
items={months}
|
||||
value={workingParts.month}
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
month: ev.detail.value
|
||||
});
|
||||
|
||||
if (presentation === 'month' || presentation === 'month-year') {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
month: ev.detail.value
|
||||
});
|
||||
}
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
}
|
||||
{
|
||||
showYear &&
|
||||
<ion-picker-column-internal
|
||||
color={this.color}
|
||||
items={years}
|
||||
value={workingParts.year}
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
year: ev.detail.value
|
||||
});
|
||||
|
||||
if (presentation === 'year' || presentation === 'month-year') {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
year: ev.detail.value
|
||||
});
|
||||
}
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
}
|
||||
</ion-picker-internal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -1457,6 +1206,125 @@ export class Datetime implements ComponentInterface {
|
||||
);
|
||||
}
|
||||
|
||||
private renderTimePicker(
|
||||
hoursItems: PickerColumnItem[],
|
||||
minutesItems: PickerColumnItem[],
|
||||
ampmItems: PickerColumnItem[],
|
||||
use24Hour: boolean
|
||||
) {
|
||||
const { color, workingParts } = this;
|
||||
return (
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal
|
||||
color={color}
|
||||
value={workingParts.hour}
|
||||
items={hoursItems}
|
||||
numericInput
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
hour: ev.detail.value
|
||||
});
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
hour: ev.detail.value
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
<ion-picker-column-internal
|
||||
color={color}
|
||||
value={workingParts.minute}
|
||||
items={minutesItems}
|
||||
numericInput
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
minute: ev.detail.value
|
||||
});
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
minute: ev.detail.value
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
{ !use24Hour && <ion-picker-column-internal
|
||||
color={color}
|
||||
value={workingParts.ampm}
|
||||
items={ampmItems}
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
const hour = calculateHourFromAMPM(this.workingParts, ev.detail.value);
|
||||
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
ampm: ev.detail.value,
|
||||
hour
|
||||
});
|
||||
|
||||
this.setActiveParts({
|
||||
...this.workingParts,
|
||||
ampm: ev.detail.value,
|
||||
hour
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal> }
|
||||
</ion-picker-internal>
|
||||
)
|
||||
}
|
||||
|
||||
private renderTimeOverlay(
|
||||
hoursItems: PickerColumnItem[],
|
||||
minutesItems: PickerColumnItem[],
|
||||
ampmItems: PickerColumnItem[],
|
||||
use24Hour: boolean
|
||||
) {
|
||||
return [
|
||||
<div class="time-header">
|
||||
{this.renderTimeLabel()}
|
||||
</div>,
|
||||
<button
|
||||
class={{
|
||||
'time-body': true,
|
||||
'time-body-active': this.isTimePopoverOpen
|
||||
}}
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
onClick={async ev => {
|
||||
const { popoverRef } = this;
|
||||
|
||||
if (popoverRef) {
|
||||
|
||||
this.isTimePopoverOpen = true;
|
||||
popoverRef.present(ev);
|
||||
|
||||
await popoverRef.onWillDismiss();
|
||||
|
||||
this.isTimePopoverOpen = false;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getFormattedTime(this.workingParts, use24Hour)}
|
||||
</button>,
|
||||
<ion-popover
|
||||
alignment="center"
|
||||
translucent
|
||||
overlayIndex={1}
|
||||
arrow={false}
|
||||
style={{
|
||||
'--offset-y': '-10px'
|
||||
}}
|
||||
ref={el => this.popoverRef = el}
|
||||
>
|
||||
{this.renderTimePicker(hoursItems, minutesItems, ampmItems, use24Hour)}
|
||||
</ion-popover>
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Render time picker inside of datetime.
|
||||
* Do not pass color prop to segment on
|
||||
@ -1464,87 +1332,44 @@ export class Datetime implements ComponentInterface {
|
||||
* should take on the color prop, but iOS
|
||||
* should just be the default segment.
|
||||
*/
|
||||
private renderTime(mode: Mode) {
|
||||
const { hourCycle } = this;
|
||||
const use24Hour = is24Hour(this.locale, hourCycle);
|
||||
const { ampm } = this.workingParts;
|
||||
private renderTime() {
|
||||
const { workingParts, presentation } = this;
|
||||
const timeOnlyPresentation = presentation === 'time';
|
||||
const use24Hour = is24Hour(this.locale, this.hourCycle);
|
||||
const { hours, minutes, am, pm } = generateTime(this.workingParts, use24Hour ? 'h23' : 'h12', this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues);
|
||||
return (
|
||||
<div class="datetime-time">
|
||||
<div class="time-header">
|
||||
{this.renderTimeLabel()}
|
||||
</div>
|
||||
<div class="time-body">
|
||||
<div class="time-base" ref={el => this.timeBaseRef = el}>
|
||||
<div class="time-wrapper">
|
||||
<div
|
||||
class="ion-focusable time-column time-column-hours"
|
||||
aria-label="Hours"
|
||||
role="slider"
|
||||
ref={el => this.timeHourRef = el}
|
||||
tabindex="0"
|
||||
>
|
||||
{ hours.map(hour => {
|
||||
return (
|
||||
<div
|
||||
class="time-item"
|
||||
data-value={getInternalHourValue(hour, use24Hour, ampm)}
|
||||
>{getFormattedHour(hour, use24Hour)}</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div class="time-separator">:</div>
|
||||
<div
|
||||
class="ion-focusable time-column time-column-minutes"
|
||||
aria-label="Minutes"
|
||||
role="slider"
|
||||
ref={el => this.timeMinuteRef = el}
|
||||
tabindex="0"
|
||||
>
|
||||
{ minutes.map(minute => {
|
||||
return (
|
||||
<div
|
||||
class="time-item"
|
||||
data-value={minute}
|
||||
>{addTimePadding(minute)}</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{ !use24Hour && <div class="time-ampm">
|
||||
<ion-segment
|
||||
color={mode === 'md' ? this.color : undefined}
|
||||
value={this.workingParts.ampm}
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
|
||||
/**
|
||||
* Since datetime uses 24-hour time internally
|
||||
* we need to update the working hour here as well
|
||||
* if the user is using a 12-hour time format.
|
||||
*/
|
||||
const { value } = ev.detail;
|
||||
const hour = calculateHourFromAMPM(this.workingParts, value);
|
||||
|
||||
this.setWorkingParts({
|
||||
...this.workingParts,
|
||||
ampm: value,
|
||||
hour
|
||||
const hoursItems = hours.map(hour => {
|
||||
return {
|
||||
text: getFormattedHour(hour, use24Hour),
|
||||
value: getInternalHourValue(hour, use24Hour, workingParts.ampm)
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Do not let this event bubble up
|
||||
* otherwise developers listening for ionChange
|
||||
* on the datetime will see this event.
|
||||
*/
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<ion-segment-button disabled={!am} value="am">AM</ion-segment-button>
|
||||
<ion-segment-button disabled={!pm} value="pm">PM</ion-segment-button>
|
||||
</ion-segment>
|
||||
</div> }
|
||||
</div>
|
||||
const minutesItems = minutes.map(minute => {
|
||||
return {
|
||||
text: addTimePadding(minute),
|
||||
value: minute
|
||||
}
|
||||
});
|
||||
|
||||
const ampmItems = [];
|
||||
if (am) {
|
||||
ampmItems.push({
|
||||
text: 'AM',
|
||||
value: 'am'
|
||||
})
|
||||
}
|
||||
|
||||
if (pm) {
|
||||
ampmItems.push({
|
||||
text: 'PM',
|
||||
value: 'pm'
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="datetime-time">
|
||||
{timeOnlyPresentation ? this.renderTimePicker(hoursItems, minutesItems, ampmItems, use24Hour) : this.renderTimeOverlay(hoursItems, minutesItems, ampmItems, use24Hour)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1573,20 +1398,20 @@ export class Datetime implements ComponentInterface {
|
||||
this.renderCalendarViewHeader(mode),
|
||||
this.renderCalendar(mode),
|
||||
this.renderYearView(),
|
||||
this.renderTime(mode),
|
||||
this.renderTime(),
|
||||
this.renderFooter()
|
||||
]
|
||||
case 'time-date':
|
||||
return [
|
||||
this.renderCalendarViewHeader(mode),
|
||||
this.renderTime(mode),
|
||||
this.renderTime(),
|
||||
this.renderCalendar(mode),
|
||||
this.renderYearView(),
|
||||
this.renderFooter()
|
||||
]
|
||||
case 'time':
|
||||
return [
|
||||
this.renderTime(mode),
|
||||
this.renderTime(),
|
||||
this.renderFooter()
|
||||
]
|
||||
case 'month':
|
||||
@ -1638,4 +1463,3 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
let datetimeIds = 0;
|
||||
const PICKER_COL_ACTIVE = 'picker-col-item-active';
|
||||
|
@ -183,6 +183,17 @@ dates in JavaScript.
|
||||
| `Shift` + `PageUp` | Changes the grid of dates to the previous year. |
|
||||
| `Shift` + `PageDown` | Changes the grid of dates to the next year. |
|
||||
|
||||
#### Time, Month, and Year Wheels
|
||||
|
||||
When using the time wheel picker, you can use the number keys to select hour and minute values when the columns are focused.
|
||||
|
||||
| Key | Function |
|
||||
| ------------------ | ------------------------------------------------------------ |
|
||||
| `ArrowUp` | Scroll to the previous item. |
|
||||
| `ArrowDown` | Scroll to the next item. |
|
||||
| `Home` | Scroll to the first item. |
|
||||
| `End` | Scroll to the last item. |
|
||||
|
||||
## Interfaces
|
||||
|
||||
### DatetimeChangeEventDetail
|
||||
@ -776,27 +787,29 @@ Type: `Promise<void>`
|
||||
|
||||
- [ion-buttons](../buttons)
|
||||
- [ion-button](../button)
|
||||
- ion-picker-internal
|
||||
- ion-picker-column-internal
|
||||
- [ion-item](../item)
|
||||
- [ion-label](../label)
|
||||
- ion-icon
|
||||
- [ion-segment](../segment)
|
||||
- [ion-segment-button](../segment-button)
|
||||
- [ion-popover](../popover)
|
||||
|
||||
### Graph
|
||||
```mermaid
|
||||
graph TD;
|
||||
ion-datetime --> ion-buttons
|
||||
ion-datetime --> ion-button
|
||||
ion-datetime --> ion-picker-internal
|
||||
ion-datetime --> ion-picker-column-internal
|
||||
ion-datetime --> ion-item
|
||||
ion-datetime --> ion-label
|
||||
ion-datetime --> ion-icon
|
||||
ion-datetime --> ion-segment
|
||||
ion-datetime --> ion-segment-button
|
||||
ion-datetime --> ion-popover
|
||||
ion-button --> ion-ripple-effect
|
||||
ion-item --> ion-icon
|
||||
ion-item --> ion-ripple-effect
|
||||
ion-item --> ion-note
|
||||
ion-segment-button --> ion-ripple-effect
|
||||
ion-popover --> ion-backdrop
|
||||
style ion-datetime fill:#f9f,stroke:#333,stroke-width:4px
|
||||
```
|
||||
|
||||
|
@ -401,7 +401,9 @@
|
||||
const modalElement = Object.assign(document.createElement('ion-modal'), {
|
||||
component: element
|
||||
});
|
||||
document.body.appendChild(modalElement);
|
||||
|
||||
const app = document.querySelector('ion-app');
|
||||
app.appendChild(modalElement);
|
||||
return modalElement;
|
||||
}
|
||||
</script>
|
||||
|
@ -57,6 +57,15 @@
|
||||
value="2021-06-20"
|
||||
></ion-datetime>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>AM/PM Min/Max</h2>
|
||||
<ion-datetime
|
||||
presentation="time"
|
||||
min="09:30"
|
||||
max="14:50"
|
||||
value="10:30"
|
||||
></ion-datetime>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
|
@ -89,6 +89,7 @@
|
||||
presentation="year"
|
||||
></ion-datetime>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
@ -1,5 +1,28 @@
|
||||
import { DatetimeParts } from '../datetime-interface';
|
||||
|
||||
const get12HourTime = (hour: number) => {
|
||||
return hour % 12 || 12;
|
||||
}
|
||||
|
||||
const getFormattedAMPM = (ampm?: string) => {
|
||||
if (ampm === undefined) { return ''; }
|
||||
|
||||
return ampm.toUpperCase();
|
||||
}
|
||||
|
||||
export const getFormattedTime = (refParts: DatetimeParts, use24Hour: boolean): string => {
|
||||
if (refParts.hour === undefined || refParts.minute === undefined) { return 'Invalid Time'; }
|
||||
|
||||
const hour = use24Hour ? getFormattedHour(refParts.hour, use24Hour) : get12HourTime(refParts.hour);
|
||||
const minute = addTimePadding(refParts.minute);
|
||||
|
||||
if (use24Hour) {
|
||||
return `${hour}:${minute}`
|
||||
}
|
||||
|
||||
return `${hour}:${minute} ${getFormattedAMPM(refParts.ampm)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds padding to a time value so
|
||||
* that it is always 2 digits.
|
||||
|
@ -111,7 +111,6 @@
|
||||
column.addEventListener('ionChange', (ev) => {
|
||||
console.log('Column change', ev.detail);
|
||||
});
|
||||
|
||||
const setPickerColumn = (selector, items, value) => {
|
||||
const picker = document.querySelector(selector);
|
||||
|
||||
|
@ -633,6 +633,10 @@ Type: `Promise<void>`
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Used by
|
||||
|
||||
- [ion-datetime](../datetime)
|
||||
|
||||
### Depends on
|
||||
|
||||
- [ion-backdrop](../backdrop)
|
||||
@ -641,6 +645,7 @@ Type: `Promise<void>`
|
||||
```mermaid
|
||||
graph TD;
|
||||
ion-popover --> ion-backdrop
|
||||
ion-datetime --> ion-popover
|
||||
style ion-popover fill:#f9f,stroke:#333,stroke-width:4px
|
||||
```
|
||||
|
||||
|
@ -852,10 +852,6 @@ export default defineComponent({
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Used by
|
||||
|
||||
- [ion-datetime](../datetime)
|
||||
|
||||
### Depends on
|
||||
|
||||
- [ion-ripple-effect](../ripple-effect)
|
||||
@ -864,7 +860,6 @@ export default defineComponent({
|
||||
```mermaid
|
||||
graph TD;
|
||||
ion-segment-button --> ion-ripple-effect
|
||||
ion-datetime --> ion-segment-button
|
||||
style ion-segment-button fill:#f9f,stroke:#333,stroke-width:4px
|
||||
```
|
||||
|
||||
|
@ -626,19 +626,6 @@ export default defineComponent({
|
||||
| `--background` | Background of the segment button |
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Used by
|
||||
|
||||
- [ion-datetime](../datetime)
|
||||
|
||||
### Graph
|
||||
```mermaid
|
||||
graph TD;
|
||||
ion-datetime --> ion-segment
|
||||
style ion-segment fill:#f9f,stroke:#333,stroke-width:4px
|
||||
```
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
||||
|
Reference in New Issue
Block a user