diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 43448fdae43b7d..2330a35e338cc6 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -147,6 +147,7 @@ export { default as useBlockDisplayInformation } from './use-block-display-infor export { default as __unstableIframe } from './iframe'; export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursive-renders'; export { default as __experimentalBlockPatternsList } from './block-patterns-list'; +export { default as __experimentalPublishDateTimePicker } from './publish-date-time-picker'; /* * State Related Components diff --git a/packages/block-editor/src/components/publish-date-time-picker/README.md b/packages/block-editor/src/components/publish-date-time-picker/README.md new file mode 100644 index 00000000000000..98ff682eb79422 --- /dev/null +++ b/packages/block-editor/src/components/publish-date-time-picker/README.md @@ -0,0 +1,52 @@ +# `PublishDateTimePicker` + +`` is a component used to select the date and time that +a post will be published. It wraps the `` component found in +`@wordpress/components` and adds additional post-specific controls. + +See [the documentation for DateTimePicker](/packages/components/src/date-time) +for more information. + +## Usage + +```jsx +import { Dropdown, Button } from '@wordpress/components'; +import { __experimentalPublishDateTimePicker as PublishDateTimePicker } from '@wordpress/block-editor'; +import { useState } from '@wordpress/element'; + +const MyDateTimePicker = () => { + const [ date, setDate ] = useState( new Date() ); + + return ( + ( + + ) } + renderContent={ ( { onClose } ) => ( + setDate( newDate ) } + onClose={ onClose } + /> + ) } + /> + ); +}; +``` + +## Props + +`PublishDateTimePicker` supports all of the props that +[`DateTimePicker`](/packages/components/src/date-time#Props) supports, plus: + +### onClose + +Called when the user presses the close button. + +- Type: `Function` +- Required: Yes diff --git a/packages/block-editor/src/components/publish-date-time-picker/index.js b/packages/block-editor/src/components/publish-date-time-picker/index.js new file mode 100644 index 00000000000000..7244ed3a5c35f4 --- /dev/null +++ b/packages/block-editor/src/components/publish-date-time-picker/index.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { + DateTimePicker, + __experimentalHStack as HStack, + __experimentalSpacer as Spacer, + Button, +} from '@wordpress/components'; +import { closeSmall } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import { forwardRef } from '@wordpress/element'; + +function PublishDateTimePicker( + { onClose, onChange, ...additionalProps }, + ref +) { + return ( +
+ { /* TODO: This header is essentially the same as the one in . DRY it up. */ } + +

+ { __( 'Publish' ) } +

+ + +
+ ); +} + +export default forwardRef( PublishDateTimePicker ); diff --git a/packages/block-editor/src/components/publish-date-time-picker/style.scss b/packages/block-editor/src/components/publish-date-time-picker/style.scss new file mode 100644 index 00000000000000..517700e2ca5c25 --- /dev/null +++ b/packages/block-editor/src/components/publish-date-time-picker/style.scss @@ -0,0 +1,20 @@ +.block-editor-publish-date-time-picker__header { + margin-bottom: 1em; +} + +.block-editor-publish-date-time-picker__heading { + font-size: $default-font-size; + margin: 0; +} + +.block-editor-publish-date-time-picker__reset { + height: $icon-size; + margin: 0; + text-decoration: underline; +} + +[class].block-editor-publish-date-time-picker__close { + height: $icon-size; + min-width: $icon-size; + padding: 0; +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 5f036b4d9b264d..56ae7fb6c24d17 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -42,6 +42,7 @@ @import "./components/media-placeholder/style.scss"; @import "./components/multi-selection-inspector/style.scss"; @import "./components/plain-text/style.scss"; +@import "./components/publish-date-time-picker/style.scss"; @import "./components/responsive-block-control/style.scss"; @import "./components/rich-text/style.scss"; @import "./components/skip-to-selected-block/style.scss"; diff --git a/packages/block-library/src/post-date/edit.js b/packages/block-library/src/post-date/edit.js index da33f65418116c..dd7bd46852f7ec 100644 --- a/packages/block-library/src/post-date/edit.js +++ b/packages/block-library/src/post-date/edit.js @@ -18,13 +18,13 @@ import { InspectorControls, useBlockProps, __experimentalDateFormatPicker as DateFormatPicker, + __experimentalPublishDateTimePicker as PublishDateTimePicker, } from '@wordpress/block-editor'; import { Dropdown, ToolbarGroup, ToolbarButton, ToggleControl, - DateTimePicker, PanelBody, } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; @@ -101,13 +101,14 @@ export default function PostDateEdit( { ( - ( + ) } renderToggle={ ( { isOpen, onToggle } ) => { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index f0d806fe71411d..b538beecb144dd 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -11,6 +11,8 @@ - `SelectControl`: Add `__nextHasNoMarginBottom` prop for opting into the new margin-free styles ([#41269](https://github.com/WordPress/gutenberg/pull/41269)). - `ColorPicker`: Strip leading hash character from hex values pasted into input. ([#41223](https://github.com/WordPress/gutenberg/pull/41223)) - `ColorPicker`: Display detailed color inputs by default. ([#41222](https://github.com/WordPress/gutenberg/pull/41222)) +- Updated design for the `DateTimePicker`, `DatePicker` and `TimePicker` components ([#41097](https://github.com/WordPress/gutenberg/pull/41097)). +- `DateTimePicker`: Add `__nextRemoveHelpButton` and `__nextRemoveResetButton` for opting into new behaviour where there is no Help and Reset button ([#41097](https://github.com/WordPress/gutenberg/pull/41097)). ### Internal diff --git a/packages/components/src/date-time/README.md b/packages/components/src/date-time/README.md index 6c2cddd62841ad..6784af6c15ceb0 100644 --- a/packages/components/src/date-time/README.md +++ b/packages/components/src/date-time/README.md @@ -26,6 +26,8 @@ const MyDateTimePicker = () => { currentDate={ date } onChange={ ( newDate ) => setDate( newDate ) } is12Hour={ true } + __nextRemoveHelpButton + __nextRemoveResetButton /> ); }; @@ -74,3 +76,17 @@ List of events to show in the date picker. Each event will appear as a dot on th - Type: `Array` - Required: No + +### `__nextRemoveHelpButton`: `boolean` + +Start opting in to not displaying a Help button which will become the default in a future version. + +- Required: No +- Default: `false` + +### `__nextRemoveResetButton`: `boolean` + +Start opting in to not displaying a Reset button which will become the default in a future version. + +- Required: No +- Default: `false` diff --git a/packages/components/src/date-time/date-time/index.tsx b/packages/components/src/date-time/date-time/index.tsx new file mode 100644 index 00000000000000..0f9997403c3631 --- /dev/null +++ b/packages/components/src/date-time/date-time/index.tsx @@ -0,0 +1,217 @@ +/** + * External dependencies + */ +import { noop } from 'lodash'; +import type { ForwardedRef } from 'react'; + +/** + * WordPress dependencies + */ +import { useState, forwardRef } from '@wordpress/element'; +import { __, _x } from '@wordpress/i18n'; +import deprecated from '@wordpress/deprecated'; + +/** + * Internal dependencies + */ +import Button from '../../button'; +import { default as DatePicker } from '../date'; +import { default as TimePicker } from '../time'; +import type { DateTimePickerProps } from '../types'; +import { CalendarHelp } from './styles'; +import { HStack } from '../../h-stack'; +import { Heading } from '../../heading'; +import { Spacer } from '../../spacer'; + +export { DatePicker, TimePicker }; + +function UnforwardedDateTimePicker( + { + currentDate, + is12Hour, + isInvalidDate, + onMonthPreviewed = noop, + onChange, + events, + __nextRemoveHelpButton = false, + __nextRemoveResetButton = false, + }: DateTimePickerProps, + ref: ForwardedRef< any > +) { + if ( ! __nextRemoveHelpButton ) { + deprecated( 'Help button in wp.components.DateTimePicker', { + since: '13.4', + version: '14.6', // Six months of plugin releases. + hint: + 'Set the `__nextRemoveHelpButton` prop to `true` to remove this warning and opt in to the new behaviour, which will become the default in a future version.', + } ); + } + if ( ! __nextRemoveResetButton ) { + deprecated( 'Reset button in wp.components.DateTimePicker', { + since: '13.4', + version: '14.6', // Six months of plugin releases. + hint: + 'Set the `__nextRemoveResetButton` prop to `true` to remove this warning and opt in to the new behaviour, which will become the default in a future version.', + } ); + } + + const [ calendarHelpIsVisible, setCalendarHelpIsVisible ] = useState( + false + ); + + function onClickDescriptionToggle() { + setCalendarHelpIsVisible( ! calendarHelpIsVisible ); + } + + return ( +
+ { ! calendarHelpIsVisible && ( + <> + + + + ) } + { calendarHelpIsVisible && ( + + { __( 'Click to Select' ) } +
    +
  • + { __( + 'Click the right or left arrows to select other months in the past or the future.' + ) } +
  • +
  • { __( 'Click the desired day to select it.' ) }
  • +
+ + { __( 'Navigating with a keyboard' ) } + +
    +
  • + + ↵ + + { + ' ' /* JSX removes whitespace, but a space is required for screen readers. */ + } + { __( 'Select the date in focus.' ) } +
  • +
  • + + ←/→ + + { + ' ' /* JSX removes whitespace, but a space is required for screen readers. */ + } + { __( + 'Move backward (left) or forward (right) by one day.' + ) } +
  • +
  • + + ↑/↓ + + { + ' ' /* JSX removes whitespace, but a space is required for screen readers. */ + } + { __( + 'Move backward (up) or forward (down) by one week.' + ) } +
  • +
  • + + { __( 'PgUp/PgDn' ) } + + { + ' ' /* JSX removes whitespace, but a space is required for screen readers. */ + } + { __( + 'Move backward (PgUp) or forward (PgDn) by one month.' + ) } +
  • +
  • + + { /* Translators: Home/End reffer to the 'Home' and 'End' buttons on the keyboard.*/ } + { __( 'Home/End' ) } + + { + ' ' /* JSX removes whitespace, but a space is required for screen readers. */ + } + { __( + 'Go to the first (Home) or last (End) day of a week.' + ) } +
  • +
+
+ ) } + { ( ! __nextRemoveResetButton || ! __nextRemoveHelpButton ) && ( + + { ! __nextRemoveResetButton && + ! calendarHelpIsVisible && + currentDate && ( + + ) } + + { ! __nextRemoveHelpButton && ( + + ) } + + ) } +
+ ); +} + +/** + * DateTimePicker is a React component that renders a calendar and clock for + * date and time selection. The calendar and clock components can be accessed + * individually using the `DatePicker` and `TimePicker` components respectively. + * + * ```jsx + * import { DateTimePicker } from '@wordpress/components'; + * import { useState } from '@wordpress/element'; + * + * const MyDateTimePicker = () => { + * const [ date, setDate ] = useState( new Date() ); + * + * return ( + * setDate( newDate ) } + * is12Hour + * /> + * ); + * }; + * ``` + */ +export const DateTimePicker = forwardRef( UnforwardedDateTimePicker ); + +export default DateTimePicker; diff --git a/packages/components/src/date-time/date-time/styles.ts b/packages/components/src/date-time/date-time/styles.ts new file mode 100644 index 00000000000000..8c5693213eabbe --- /dev/null +++ b/packages/components/src/date-time/date-time/styles.ts @@ -0,0 +1,8 @@ +/** + * External dependencies + */ +import styled from '@emotion/styled'; + +export const CalendarHelp = styled.div` + min-width: 260px; +`; diff --git a/packages/components/src/date-time/datepicker.scss b/packages/components/src/date-time/date/datepicker.scss similarity index 100% rename from packages/components/src/date-time/datepicker.scss rename to packages/components/src/date-time/date/datepicker.scss diff --git a/packages/components/src/date-time/date.tsx b/packages/components/src/date-time/date/index.tsx similarity index 82% rename from packages/components/src/date-time/date.tsx rename to packages/components/src/date-time/date/index.tsx index 4c3a1fe748d826..0e583c6c5e150a 100644 --- a/packages/components/src/date-time/date.tsx +++ b/packages/components/src/date-time/date/index.tsx @@ -2,10 +2,11 @@ * External dependencies */ import moment from 'moment'; -import classnames from 'classnames'; import type { Moment } from 'moment'; import { noop } from 'lodash'; - +// Needed to initialise the default datepicker styles. +// See: https://github.com/airbnb/react-dates#initialize +import 'react-dates/initialize'; // `react-dates` doesn't tree-shake correctly, so we import from the individual // component here. import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerSingleDateController'; @@ -15,12 +16,14 @@ import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerS */ import { useEffect, useRef } from '@wordpress/element'; import { isRTL, _n, sprintf } from '@wordpress/i18n'; +import { arrowLeft, arrowRight } from '@wordpress/icons'; /** * Internal dependencies */ import { getMomentDate } from './utils'; -import type { DatePickerDayProps, DatePickerProps } from './types'; +import type { DatePickerDayProps, DatePickerProps } from '../types'; +import { Day, NavPrevButton, NavNextButton } from './styles'; const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; const ARIAL_LABEL_TIME_FORMAT = 'dddd, LL'; @@ -64,14 +67,14 @@ function DatePickerDay( { day, events = [] }: DatePickerDayProps ) { }, [ events.length ] ); return ( -
{ day.format( 'D' ) } -
+ ); } @@ -102,6 +105,7 @@ export function DatePicker( { onMonthPreviewed, }: DatePickerProps ) { const nodeRef = useRef< HTMLDivElement >( null ); + const onMonthPreviewedHandler = ( newMonthDate: Moment ) => { onMonthPreviewed?.( newMonthDate.toISOString() ); keepFocusInside(); @@ -175,6 +179,7 @@ export function DatePicker( { date={ momentDate } initialVisibleMonth={ null } daySize={ 30 } + horizontalMonthPadding={ 0 } focused hideKeyboardShortcutsPanel // This is a hack to force the calendar to update on month or year change @@ -200,6 +205,28 @@ export function DatePicker( { events={ getEventsPerDay( day ) } /> ) } + renderMonthElement={ ( { month } ) => ( + <> + { month.format( 'MMMM' ) }{ ' ' } + { month.format( 'YYYY' ) } + + ) } + renderNavPrevButton={ ( { ariaLabel, ...props } ) => ( + + ) } + renderNavNextButton={ ( { ariaLabel, ...props } ) => ( + + ) } onFocusChange={ noop } /> diff --git a/packages/components/src/date-time/date/style.scss b/packages/components/src/date-time/date/style.scss new file mode 100644 index 00000000000000..26b41d089a86a1 --- /dev/null +++ b/packages/components/src/date-time/date/style.scss @@ -0,0 +1,75 @@ +@import "./datepicker.scss"; + +// Styles that overrides the calendar styling provided by react-dates go here. +// Everything else goes in styles.ts. + +.components-datetime__date { + // + // Margin overrides + // + + // Remove the left and right margin from the calendar by setting all the + // containers' widths to 100%. This means that the slide left / slide right + // animation won't work but we don't want that, anyway. + + .CalendarMonthGrid__horizontal, + .DayPicker_weekHeader_li { + transform: none !important; // Override inline style. + width: 100% !important; // Override inline style. + } + + .CalendarMonthGrid_month__horizontal, + .CalendarMonth_table, + .DayPicker_weekHeader { + width: 100%; + } + + .DayPicker_weekHeaders__horizontal { + margin: 0; + } + + .DayPicker_weekHeader_ul { + display: flex; + } + + // + // Theming + // + + .DayPicker_weekHeader { + top: 50px; + } + + .CalendarMonth_caption { + font-size: $default-font-size; + } + + .CalendarMonth_table { + border-collapse: separate; + border-spacing: 2px; + } + + .CalendarDay { + border: none; + font-size: $default-font-size; + border-radius: $radius-round; + + &:focus { + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 #{ $border-width-focus + $border-width } $white; + outline: 2px solid transparent; // Shown in Windows 10 high contrast mode. + } + } + + .CalendarDay__selected { + background: var(--wp-admin-theme-color); + border: 2px solid transparent; // This indicates selection in Windows 10 high contrast mode. + + &:hover { + background: var(--wp-admin-theme-color-darker-20); + } + + &:focus { + box-shadow: inset 0 0 0 $border-width $white; + } + } +} diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts new file mode 100644 index 00000000000000..e80229a3050b4c --- /dev/null +++ b/packages/components/src/date-time/date/styles.ts @@ -0,0 +1,55 @@ +/** + * External dependencies + */ +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +/** + * Internal dependencies + */ +import Button from '../../button'; +import { COLORS } from '../../utils'; +import { VStack } from '../../v-stack'; + +// Styles that overrides the calendar styling provided by react-dates go in +// style.scss. Everything else goes here. + +export const Day = styled( VStack )< { hasEvents: boolean } >` + height: 100%; + position: relative; + + ${ ( props ) => + props.hasEvents && + ` + ::before { + background: var(--wp-admin-theme-color); + border-radius: 2px; + bottom: 0; + content: " "; + height: 4px; + left: 50%; + margin-left: -2px; + position: absolute; + width: 4px; + + .CalendarDay__selected & { + background: ${ COLORS.white }; + } + } + ` } +`; + +const baseNavButton = css` + position: absolute; + top: 15px; +`; + +export const NavPrevButton = styled( Button )` + ${ baseNavButton } + left: 0; +`; + +export const NavNextButton = styled( Button )` + ${ baseNavButton } + right: 0; +`; diff --git a/packages/components/src/date-time/test/date.tsx b/packages/components/src/date-time/date/test/index.tsx similarity index 98% rename from packages/components/src/date-time/test/date.tsx rename to packages/components/src/date-time/date/test/index.tsx index a0065e3f04a8fd..57e8f12335cfab 100644 --- a/packages/components/src/date-time/test/date.tsx +++ b/packages/components/src/date-time/date/test/index.tsx @@ -9,7 +9,7 @@ import 'react-dates/initialize'; /** * Internal dependencies */ -import DatePicker from '../date'; +import DatePicker from '..'; describe( 'DatePicker', () => { it( 'should highlight the current date', () => { diff --git a/packages/components/src/date-time/test/utils.ts b/packages/components/src/date-time/date/test/utils.ts similarity index 100% rename from packages/components/src/date-time/test/utils.ts rename to packages/components/src/date-time/date/test/utils.ts diff --git a/packages/components/src/date-time/utils.ts b/packages/components/src/date-time/date/utils.ts similarity index 100% rename from packages/components/src/date-time/utils.ts rename to packages/components/src/date-time/date/utils.ts diff --git a/packages/components/src/date-time/index.ts b/packages/components/src/date-time/index.ts new file mode 100644 index 00000000000000..a103bac0d30efb --- /dev/null +++ b/packages/components/src/date-time/index.ts @@ -0,0 +1,9 @@ +/** + * Internal dependencies + */ +import { default as DatePicker } from './date'; +import { default as TimePicker } from './time'; +import { default as DateTimePicker } from './date-time'; + +export { DatePicker, TimePicker }; +export default DateTimePicker; diff --git a/packages/components/src/date-time/index.tsx b/packages/components/src/date-time/index.tsx deleted file mode 100644 index 85d9bdaf218e41..00000000000000 --- a/packages/components/src/date-time/index.tsx +++ /dev/null @@ -1,196 +0,0 @@ -/** - * External dependencies - */ -// Needed to initialise the default datepicker styles. -// See: https://github.com/airbnb/react-dates#initialize -import 'react-dates/initialize'; -import { noop } from 'lodash'; -import type { ForwardedRef } from 'react'; - -/** - * WordPress dependencies - */ -import { useState, forwardRef } from '@wordpress/element'; -import { __, _x } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import Button from '../button'; -import { default as DatePicker } from './date'; -import { default as TimePicker } from './time'; -import type { DateTimePickerProps } from './types'; - -export { DatePicker, TimePicker }; - -function UnforwardedDateTimePicker( - { - currentDate, - is12Hour, - isInvalidDate, - onMonthPreviewed = noop, - onChange, - events, - }: DateTimePickerProps, - ref: ForwardedRef< any > -) { - const [ calendarHelpIsVisible, setCalendarHelpIsVisible ] = useState( - false - ); - - function onClickDescriptionToggle() { - setCalendarHelpIsVisible( ! calendarHelpIsVisible ); - } - - return ( -
- { ! calendarHelpIsVisible && ( - <> - - - - ) } - { calendarHelpIsVisible && ( - <> -
-

{ __( 'Click to Select' ) }

-
    -
  • - { __( - 'Click the right or left arrows to select other months in the past or the future.' - ) } -
  • -
  • - { __( 'Click the desired day to select it.' ) } -
  • -
-

{ __( 'Navigating with a keyboard' ) }

-
    -
  • - - ↵ - - { - ' ' /* JSX removes whitespace, but a space is required for screen readers. */ - } - - { __( 'Select the date in focus.' ) } - -
  • -
  • - - ←/→ - - { - ' ' /* JSX removes whitespace, but a space is required for screen readers. */ - } - { __( - 'Move backward (left) or forward (right) by one day.' - ) } -
  • -
  • - - ↑/↓ - - { - ' ' /* JSX removes whitespace, but a space is required for screen readers. */ - } - { __( - 'Move backward (up) or forward (down) by one week.' - ) } -
  • -
  • - - { __( 'PgUp/PgDn' ) } - - { - ' ' /* JSX removes whitespace, but a space is required for screen readers. */ - } - { __( - 'Move backward (PgUp) or forward (PgDn) by one month.' - ) } -
  • -
  • - - { /* Translators: Home/End reffer to the 'Home' and 'End' buttons on the keyboard.*/ } - { __( 'Home/End' ) } - - { - ' ' /* JSX removes whitespace, but a space is required for screen readers. */ - } - { __( - 'Go to the first (Home) or last (End) day of a week.' - ) } -
  • -
-
- - ) } -
- { ! calendarHelpIsVisible && currentDate && ( - - ) } - -
-
- ); -} - -/** - * DateTimePicker is a React component that renders a calendar and clock for - * date and time selection. The calendar and clock components can be accessed - * individually using the `DatePicker` and `TimePicker` components respectively. - * - * ```jsx - * import { DateTimePicker } from '@wordpress/components'; - * import { useState } from '@wordpress/element'; - * - * const MyDateTimePicker = () => { - * const [ date, setDate ] = useState( new Date() ); - * - * return ( - * setDate( newDate ) } - * is12Hour - * /> - * ); - * }; - * ``` - */ -export const DateTimePicker = forwardRef( UnforwardedDateTimePicker ); - -export default DateTimePicker; diff --git a/packages/components/src/date-time/stories/index.tsx b/packages/components/src/date-time/stories/date-time.tsx similarity index 97% rename from packages/components/src/date-time/stories/index.tsx rename to packages/components/src/date-time/stories/date-time.tsx index fb126edb81f4e4..bea4028e7fb567 100644 --- a/packages/components/src/date-time/stories/index.tsx +++ b/packages/components/src/date-time/stories/date-time.tsx @@ -11,7 +11,7 @@ import { useState, useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import DateTimePicker from '..'; +import DateTimePicker from '../date-time'; import { daysFromNow, isWeekend } from './utils'; const meta: ComponentMeta< typeof DateTimePicker > = { diff --git a/packages/components/src/date-time/style.scss b/packages/components/src/date-time/style.scss index 636f7851218798..9e059d0d5be6d3 100644 --- a/packages/components/src/date-time/style.scss +++ b/packages/components/src/date-time/style.scss @@ -1,262 +1 @@ -@import "./datepicker"; - -.components-datetime { - // This padding is leveraged when the component is used alone, - // usually inside popovers. - padding: $grid-unit-20; - - // This rule removes the padding when used inside a panel. - .components-panel__body & { - padding: 0; - } - - .components-datetime__calendar-help { - padding: $grid-unit-20; - min-width: 260px; - - h4 { - margin: 0; - } - } - - .components-datetime__buttons { - display: flex; - justify-content: space-between; - } - - .components-datetime__date-help-toggle { - display: block; - margin-left: auto; - } - - fieldset { - border: 0; - padding: 0; - margin: 0; - } - - select, - input { - @include input-style__neutral(); - } - - // Override inherited conflicting styles to be consistent. - select, - input[type="number"], - .components-button { - height: 30px; - margin-top: 0; - margin-bottom: 0; - } - - .components-button:focus { - z-index: z-index(".components-button {:focus or .is-primary}"); - } -} - -.components-datetime__date { - min-height: 236px; - border-top: 1px solid $gray-300; - - // Override external DatePicker styles. - .DayPickerNavigation_leftButton__horizontalDefault { - /*!rtl:begin:ignore*/ - left: 13px; - /*!rtl:end:ignore*/ - } - - .CalendarMonth_caption { - font-size: $default-font-size; - } - - // Seperate borders so that border respect border radius - .CalendarMonth_table { - border-collapse: separate; - border-spacing: 2px; - } - - .CalendarDay { - font-size: $default-font-size; - border: none; - border-radius: $radius-round; - text-align: center; - - &:focus { - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color), inset 0 0 0 #{ $border-width-focus + $border-width } $white; - outline: 2px solid transparent; // Shown in Windows 10 high contrast mode. - } - } - - .CalendarDay__selected { - background: var(--wp-admin-theme-color); - border: 2px solid transparent; // This indicates selection in Windows 10 high contrast mode. - - &:hover { - background: var(--wp-admin-theme-color-darker-20); - } - - &:focus { - box-shadow: inset 0 0 0 $border-width $white; - } - } - - .DayPickerNavigation_button__horizontalDefault { - padding: 2px 8px; - top: 20px; - - &:focus { - @include input-style__focus(); - } - } - - .DayPicker_weekHeader { - top: 50px; - .DayPicker_weekHeader_ul { - margin: 1px; - padding-left: 0; - padding-right: 0; - } - } - - &.is-description-visible .DayPicker { - visibility: hidden; - } -} - -.components-datetime__date .CalendarDay .components-datetime__date__day { - height: 100%; - display: flex; - justify-content: center; - align-content: center; - flex-direction: column; - position: relative; - - &.has-events::before { - content: " "; - width: 4px; - height: 4px; - border-radius: 2px; - position: absolute; - left: 50%; - margin-left: -2px; - bottom: 0; - background-color: $white; - } -} - -.components-datetime__date .CalendarDay:not(.CalendarDay__selected) .components-datetime__date__day.has-events::before { - background: var(--wp-admin-theme-color); -} - -.components-datetime__time { - padding-bottom: $grid-unit-20; - - fieldset { - position: relative; - margin-bottom: 0.5em; - } - - fieldset + fieldset { - margin-bottom: 0; - } - - .components-datetime__time-field-am-pm fieldset { - margin-top: 0; - } - - .components-datetime__time-wrapper { - display: flex; - - .components-datetime__time-separator { - display: inline-block; - padding: 0 3px 0 0; - } - - .components-datetime__time-field { - - &-time { - /*rtl:ignore*/ - direction: ltr; - } - - select { - margin-right: $grid-unit-05; - - &:focus { - position: relative; - z-index: 1; - } - } - - input[type="number"] { - padding: 2px; - margin-right: $grid-unit-05; - text-align: center; - -moz-appearance: textfield; - - &:focus { - position: relative; - z-index: 1; - } - - &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - } - } - } - - // Makes the month appear before the day if time format uses AM/PM - // We are assuming MM-DD-YYY correlates with AM/PM - &.is-12-hour { - .components-datetime__time-field-day input { - margin: 0 -$grid-unit-05 0 0 !important; - border-radius: $radius-block-ui 0 0 $radius-block-ui !important; - } - .components-datetime__time-field-year input { - border-radius: 0 $radius-block-ui $radius-block-ui 0 !important; - } - } -} - -.components-datetime__timezone { - line-height: 30px; - margin-left: $grid-unit-05; - text-decoration: underline dotted; -} - -.components-datetime__time-legend { - font-weight: 600; - margin-top: 0.5em; - - &.invisible { - position: absolute; - top: -999em; - left: -999em; - } -} - -.components-datetime__time-field-integer-field { - font-family: inherit; -} - -.components-datetime__time-field-hours-input, -.components-datetime__time-field-minutes-input, -.components-datetime__time-field-day-input { - width: 35px; -} - -.components-datetime__time-field-year-input { - width: 55px; -} - -.components-datetime__time-field-month-select { - max-width: 145px; -} - -// Hack to center the datepicker component within the popover. -// It sets its own styles so centering is tricky. -.components-popover .components-datetime__date { - padding-left: $grid-unit-05; -} +@import "./date/style.scss"; diff --git a/packages/components/src/date-time/time.tsx b/packages/components/src/date-time/time.tsx deleted file mode 100644 index 9d0c1cfa4c394f..00000000000000 --- a/packages/components/src/date-time/time.tsx +++ /dev/null @@ -1,321 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import { isInteger } from 'lodash'; -import moment from 'moment'; -import type { FocusEvent } from 'react'; -import type { Moment } from 'moment'; - -/** - * WordPress dependencies - */ -import { - createElement, - useState, - useMemo, - useEffect, -} from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import Button from '../button'; -import ButtonGroup from '../button-group'; -import TimeZone from './timezone'; -import type { WordPressComponentProps } from '../ui/context'; -import type { UpdateOnBlurAsIntegerFieldProps, TimePickerProps } from './types'; - -const TIMEZONELESS_FORMAT = 'YYYY-MM-DDTHH:mm:ss'; - -function from12hTo24h( hours: number, isPm: boolean ) { - return isPm ? ( ( hours % 12 ) + 12 ) % 24 : hours % 12; -} - -/** - * A shared component to parse, validate, and handle remounting of the - * underlying form field element like and