@gnome-ui/react-native 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +310 -0
- package/dist/components/Calendar/Calendar.d.ts +95 -0
- package/dist/components/Calendar/CalendarBase.d.ts +83 -0
- package/dist/components/Calendar/calendarUtils.d.ts +66 -0
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/CalendarRange/CalendarRange.d.ts +75 -0
- package/dist/components/CalendarRange/index.d.ts +2 -0
- package/dist/components/CalendarRange/rangeUtils.d.ts +31 -0
- package/dist/components/DatePicker/DatePicker.d.ts +75 -0
- package/dist/components/DatePicker/index.d.ts +2 -0
- package/dist/components/LinkedGroup/LinkedGroup.d.ts +50 -0
- package/dist/components/LinkedGroup/index.d.ts +2 -0
- package/dist/components/NavigationSplitView/NavigationSplitView.d.ts +69 -0
- package/dist/components/NavigationSplitView/index.d.ts +2 -0
- package/dist/components/RatingStars/RatingStars.d.ts +48 -0
- package/dist/components/RatingStars/index.d.ts +2 -0
- package/dist/components/TimePicker/TimeFields.d.ts +36 -0
- package/dist/components/TimePicker/TimePicker.d.ts +55 -0
- package/dist/components/TimePicker/index.d.ts +2 -0
- package/dist/components/TimePicker/timeUtils.d.ts +36 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +2346 -1535
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for `CalendarRange`. Kept dependency-free and side-effect-free,
|
|
3
|
+
* mirroring the `calendarUtils.ts` split `Calendar` already uses. Ported
|
|
4
|
+
* verbatim from `@gnome-ui/react`'s own `rangeUtils.ts` — zero DOM
|
|
5
|
+
* dependency there already.
|
|
6
|
+
*/
|
|
7
|
+
/** A range under construction — either end may still be missing. */
|
|
8
|
+
export interface DateRange {
|
|
9
|
+
start: Date | null;
|
|
10
|
+
end: Date | null;
|
|
11
|
+
}
|
|
12
|
+
/** A finished range: both ends have a value. The only shape `onChange` emits. */
|
|
13
|
+
export interface SelectedDateRange {
|
|
14
|
+
start: Date;
|
|
15
|
+
end: Date;
|
|
16
|
+
}
|
|
17
|
+
/** The empty range, as a fresh object so callers never share one. */
|
|
18
|
+
export declare const emptyRange: () => DateRange;
|
|
19
|
+
/** Both dates as a range, oldest first — so picking backwards still works. */
|
|
20
|
+
export declare const orderRange: (a: Date, b: Date) => SelectedDateRange;
|
|
21
|
+
/**
|
|
22
|
+
* Length of the range in days, counting both ends (so a single day is `1`).
|
|
23
|
+
* Rounded, because a DST change makes a "day" 23 or 25 hours long.
|
|
24
|
+
*/
|
|
25
|
+
export declare const rangeLength: (range: SelectedDateRange) => number;
|
|
26
|
+
/** `true` when `date` falls on or between both ends. */
|
|
27
|
+
export declare const isWithinRange: (date: Date, range: SelectedDateRange) => boolean;
|
|
28
|
+
/** `true` when the range satisfies the `minRange`/`maxRange` day limits. */
|
|
29
|
+
export declare const isRangeAllowed: (range: SelectedDateRange, minRange?: number, maxRange?: number) => boolean;
|
|
30
|
+
/** `true` when both ends have a value — the condition for emitting a change. */
|
|
31
|
+
export declare const isRangeComplete: (range: DateRange) => range is SelectedDateRange;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { WeekStart } from '../Calendar/calendarUtils';
|
|
3
|
+
import { PopoverPlacement } from '../Popover';
|
|
4
|
+
export interface DatePickerProps {
|
|
5
|
+
/** Controlled selected date. Pass `null` for "no selection". */
|
|
6
|
+
value?: Date | null;
|
|
7
|
+
/** Initial selected date when uncontrolled. Defaults to `null`. */
|
|
8
|
+
defaultValue?: Date | null;
|
|
9
|
+
/** Called when the user picks a date (or, with `showTime`, edits a time column). */
|
|
10
|
+
onChange?: (date: Date) => void;
|
|
11
|
+
/** Earliest selectable date (inclusive). */
|
|
12
|
+
min?: Date;
|
|
13
|
+
/** Latest selectable date (inclusive). */
|
|
14
|
+
max?: Date;
|
|
15
|
+
/** First day of the week: `0` (Sunday) … `6` (Saturday). Defaults to `1` (Monday). */
|
|
16
|
+
weekStartsOn?: WeekStart;
|
|
17
|
+
/**
|
|
18
|
+
* Add hour/minute columns under the calendar, making the emitted `Date` a
|
|
19
|
+
* point in time rather than a civil date. Picking a day then keeps the
|
|
20
|
+
* popover open — the selection is only finished by the Done button.
|
|
21
|
+
*/
|
|
22
|
+
showTime?: boolean;
|
|
23
|
+
/** 12- or 24-hour columns when `showTime` is on. Defaults to `24`. */
|
|
24
|
+
hourCycle?: 12 | 24;
|
|
25
|
+
/** Minute increment for the time spinner. Defaults to `1`. */
|
|
26
|
+
minuteStep?: number;
|
|
27
|
+
/** Label on the button that closes a `showTime` popover. Defaults to `'Done'`. */
|
|
28
|
+
doneLabel?: string;
|
|
29
|
+
/** Text shown in the trigger while no date is selected. */
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/** Visible label rendered above the trigger. */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** Accessible name for the trigger when no visible `label` is provided. */
|
|
34
|
+
accessibilityLabel?: string;
|
|
35
|
+
/** Show an ISO week-number column in the calendar. */
|
|
36
|
+
showWeekNumbers?: boolean;
|
|
37
|
+
/** Disable the control. */
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
/** Preferred popover placement relative to the trigger. Defaults to `'bottom'`. */
|
|
40
|
+
placement?: PopoverPlacement;
|
|
41
|
+
style?: StyleProp<ViewStyle>;
|
|
42
|
+
testID?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A `Popover`-anchored `Calendar` behind a text-entry-styled trigger —
|
|
46
|
+
* mirrors the `GtkCalendar` + `GtkPopover` composition GNOME apps use for
|
|
47
|
+
* date entry.
|
|
48
|
+
*
|
|
49
|
+
* Rebuilt on this package's own already-shipped `Popover` (Tier 5) and
|
|
50
|
+
* `Calendar` (Tier 20) rather than reinventing either: the trigger is a
|
|
51
|
+
* `Pressable` styled like `Dropdown`'s own text-entry-look trigger (same
|
|
52
|
+
* bordered row, dimmed placeholder, trailing icon), and the panel is
|
|
53
|
+
* `Calendar` plus an optional `showTime` footer, composed exactly the way
|
|
54
|
+
* `Popover`'s own doc comment expects a rich-content consumer to use it —
|
|
55
|
+
* no new position-computation code, per this package's standing pitfall
|
|
56
|
+
* about not reinventing `Popover`/`Dropdown`'s already-shipped trigger-rect
|
|
57
|
+
* + panel-size positioning.
|
|
58
|
+
*
|
|
59
|
+
* **The web version's entire keyboard layer drops** — no `ArrowDown`-opens,
|
|
60
|
+
* no `Enter`/`Space` on the trigger — the same touch-first convention this
|
|
61
|
+
* whole package follows; `Calendar`'s own `autoFocus` prop was already
|
|
62
|
+
* dropped when `Calendar` was ported (no keyboard focus concept without a
|
|
63
|
+
* keyboard), so it isn't wired here either. `locale`/`formatOptions` are
|
|
64
|
+
* dropped in favor of `GnomeProvider`'s app-wide `useDateTimeFormatter`,
|
|
65
|
+
* following `Calendar`'s own just-shipped convention rather than
|
|
66
|
+
* reintroducing a locale prop pair.
|
|
67
|
+
*
|
|
68
|
+
* Picking a day keeps the popover open when `showTime` is on (only the Done
|
|
69
|
+
* button closes it, so the time columns stay reachable) and closes it
|
|
70
|
+
* immediately otherwise — ported as-is from the web version's
|
|
71
|
+
* `handleSelect`, plain state logic with no web-only API involved.
|
|
72
|
+
*
|
|
73
|
+
* @see https://gnome.pages.gitlab.gnome.org/gtk/gtk4/class.Calendar.html
|
|
74
|
+
*/
|
|
75
|
+
export declare const DatePicker: ({ value: controlledValue, defaultValue, onChange, min, max, weekStartsOn, showTime, hourCycle, minuteStep, doneLabel, placeholder, label, accessibilityLabel, showWeekNumbers, disabled, placement, style, testID, }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, View, ViewStyle } from 'react-native';
|
|
3
|
+
export interface LinkedGroupProps {
|
|
4
|
+
/**
|
|
5
|
+
* Each child must accept and merge a `style` prop the way every
|
|
6
|
+
* `@gnome-ui/react-native` component already does (`style` last in its
|
|
7
|
+
* own internal style array) — see the component doc for why.
|
|
8
|
+
*/
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
/** Stack children vertically instead of horizontally. */
|
|
11
|
+
vertical?: boolean;
|
|
12
|
+
style?: StyleProp<ViewStyle>;
|
|
13
|
+
testID?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders children as a single visually-connected unit with no gap and
|
|
17
|
+
* merged borders — the canonical GNOME pattern for button groups and
|
|
18
|
+
* segmented inputs. Mirrors `@gnome-ui/react`'s `LinkedGroup`, itself
|
|
19
|
+
* mirroring the libadwaita `.linked` style class.
|
|
20
|
+
*
|
|
21
|
+
* The web version reaches every child's border-radius via a CSS
|
|
22
|
+
* `> *` universal child selector — RN has no equivalent way for a parent
|
|
23
|
+
* `View` to reach into an arbitrary child's own internally-computed
|
|
24
|
+
* styles. Reimagined instead as the same `cloneElement`-onto-children
|
|
25
|
+
* technique `Popover`/`Tooltip` already use on their own trigger:
|
|
26
|
+
* each child gets a computed corner-radius/negative-margin override
|
|
27
|
+
* merged onto whatever `style` it already has, using the same
|
|
28
|
+
* "zero the shared inner corners, keep `theme.radiusMd` on the outer
|
|
29
|
+
* ones, overlap by 1 dp to collapse the shared border" recipe
|
|
30
|
+
* `SplitButton` already proved for its own two-piece connected border —
|
|
31
|
+
* generalized here from a fixed two children to an arbitrary list. This
|
|
32
|
+
* only works because every component in this package already merges a
|
|
33
|
+
* passed-in `style` prop last, the same assumption `Popover`'s own
|
|
34
|
+
* trigger-cloning already depends on.
|
|
35
|
+
*
|
|
36
|
+
* The web CSS also raises a hovered/focused child's `z-index` so its own
|
|
37
|
+
* border isn't visually covered by the next sibling's overlapping edge —
|
|
38
|
+
* dropped here: RN is touch-first (no `:hover`), and no component in this
|
|
39
|
+
* package currently renders an escaping focus ring that overlap could
|
|
40
|
+
* clip, so there's nothing yet for the z-index bump to protect.
|
|
41
|
+
*
|
|
42
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1-latest/style-classes.html#linked-style-class
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* <LinkedGroup>
|
|
46
|
+
* <Button variant="flat">Bold</Button>
|
|
47
|
+
* <Button variant="flat">Italic</Button>
|
|
48
|
+
* </LinkedGroup>
|
|
49
|
+
*/
|
|
50
|
+
export declare const LinkedGroup: import('react').ForwardRefExoticComponent<LinkedGroupProps & import('react').RefAttributes<View>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
export interface NavigationSplitViewProps {
|
|
4
|
+
/**
|
|
5
|
+
* The sidebar / list pane (left side on wide screens).
|
|
6
|
+
* On narrow screens this is the "list" view shown when `showContent` is false.
|
|
7
|
+
*/
|
|
8
|
+
sidebar: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* The detail / content pane (right side on wide screens).
|
|
11
|
+
* On narrow screens this is the "detail" view shown when `showContent` is true.
|
|
12
|
+
*/
|
|
13
|
+
content: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Controls which pane is visible on narrow screens (≤ 400 dp).
|
|
16
|
+
* - `false` (default) — show the sidebar list.
|
|
17
|
+
* - `true` — show the content detail.
|
|
18
|
+
*
|
|
19
|
+
* Has no effect on wide screens where both panes are visible simultaneously.
|
|
20
|
+
*/
|
|
21
|
+
showContent?: boolean;
|
|
22
|
+
/** Minimum sidebar width in dp. Defaults to `180`. */
|
|
23
|
+
minSidebarWidth?: number;
|
|
24
|
+
/** Maximum sidebar width in dp. Defaults to `280`. */
|
|
25
|
+
maxSidebarWidth?: number;
|
|
26
|
+
/** Fraction of total width given to the sidebar (0–1). Defaults to `0.25`. */
|
|
27
|
+
sidebarWidthFraction?: number;
|
|
28
|
+
style?: StyleProp<ViewStyle>;
|
|
29
|
+
testID?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Two-pane sidebar + content layout following the Adwaita
|
|
33
|
+
* `AdwNavigationSplitView` pattern — mirrors `@gnome-ui/react`'s
|
|
34
|
+
* `NavigationSplitView`.
|
|
35
|
+
*
|
|
36
|
+
* On **wide** screens (`useBreakpoint().isNarrow === false`, > 400 dp) both
|
|
37
|
+
* panes are visible side-by-side, separated by a `Separator`. On **narrow**
|
|
38
|
+
* screens only one pane is shown at a time; `showContent` switches between
|
|
39
|
+
* the sidebar list and the detail view.
|
|
40
|
+
*
|
|
41
|
+
* The web version's `clamp(min, fraction * 100%, max)` sidebar width has no
|
|
42
|
+
* RN equivalent (`StyleSheet` values aren't CSS `calc`/`clamp` expressions),
|
|
43
|
+
* so the container measures its own width via `onLayout` and the same clamp
|
|
44
|
+
* is computed in JS — `0` until the first layout pass resolves, the same
|
|
45
|
+
* one-frame imprecision this package already accepts elsewhere (e.g.
|
|
46
|
+
* `ProgressBar`'s `trackWidth`-dependent math).
|
|
47
|
+
*
|
|
48
|
+
* Narrow-mode pane switching is animated (`translateX`, matching the web
|
|
49
|
+
* CSS's own `transition: transform`), so — unlike `TabPanel`'s simpler
|
|
50
|
+
* `display: 'none'` swap — both panes stay laid out and absolutely
|
|
51
|
+
* positioned rather than being removed from flow, using the same measured
|
|
52
|
+
* container width for the slide distance (RN `transform` has no
|
|
53
|
+
* percentage-of-self units, so this can't be a bare `-100%`/`100%` the way
|
|
54
|
+
* the web version's CSS is). One shared `Animated.Value` drives both
|
|
55
|
+
* panes' opposite-direction translation, the same "skip the animation on
|
|
56
|
+
* initial mount, only animate subsequent prop changes" guard `Switch`/
|
|
57
|
+
* `StepIndicator` already established for a controlled boolean prop.
|
|
58
|
+
*
|
|
59
|
+
* The web's `inert` attribute (removes the hidden pane from both the a11y
|
|
60
|
+
* tree and the tab order while it stays mounted off-screen) has no single
|
|
61
|
+
* RN equivalent — reproduced with `accessibilityElementsHidden` +
|
|
62
|
+
* `importantForAccessibility="no-hide-descendants"` (the whole-subtree a11y
|
|
63
|
+
* exclusion, not just the single-element `"no"` `PathBar`'s decorative
|
|
64
|
+
* separator uses) plus `pointerEvents="none"` so the off-screen pane can't
|
|
65
|
+
* intercept touches meant for the visible one.
|
|
66
|
+
*
|
|
67
|
+
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.NavigationSplitView.html
|
|
68
|
+
*/
|
|
69
|
+
export declare const NavigationSplitView: ({ sidebar, content, showContent, minSidebarWidth, maxSidebarWidth, sidebarWidthFraction, style, testID, }: NavigationSplitViewProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { IconSize } from '../Icon';
|
|
3
|
+
export interface RatingStarsProps {
|
|
4
|
+
/** Current rating, between `0` and `max`. */
|
|
5
|
+
value: number;
|
|
6
|
+
/** Number of stars. Defaults to `5`. */
|
|
7
|
+
max?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Called when the user picks a rating. Omit to render a read-only
|
|
10
|
+
* display (e.g. an average rating) instead of an interactive input.
|
|
11
|
+
*/
|
|
12
|
+
onChange?: (value: number) => void;
|
|
13
|
+
/** Star size. Defaults to `"md"`. */
|
|
14
|
+
size?: IconSize;
|
|
15
|
+
/** Renders as read-only even when `onChange` is provided. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** Accessible label. Defaults to `"Rating"` (interactive) or a generated `"N out of M stars"` (read-only). */
|
|
18
|
+
accessibilityLabel?: string;
|
|
19
|
+
style?: StyleProp<ViewStyle>;
|
|
20
|
+
testID?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Star rating display and input. Mirrors `@gnome-ui/react`'s `RatingStars`.
|
|
24
|
+
*
|
|
25
|
+
* Renders `role="radiogroup"` of `role="radio"` stars when `onChange` is
|
|
26
|
+
* provided, or a static `role="img"` when it isn't — e.g. for showing an
|
|
27
|
+
* average/read-only rating.
|
|
28
|
+
*
|
|
29
|
+
* The web version's `role="radiogroup"` layer also owns an `onKeyDown`
|
|
30
|
+
* handler for arrow-key roving-tabindex navigation and a mouse-hover
|
|
31
|
+
* preview that doesn't commit until clicked; neither has a touch
|
|
32
|
+
* counterpart, so both drop — same standing convention `ToggleGroup`
|
|
33
|
+
* already established for this package (its own doc comment covers the
|
|
34
|
+
* reasoning). What's left, tapping a star to commit that rating, is a
|
|
35
|
+
* strict subset of the web interaction, not an approximation of it.
|
|
36
|
+
*
|
|
37
|
+
* Each star's fill color is `tintColor={theme.warningBgColor}` rather than
|
|
38
|
+
* `Icon`'s own fixed `color="yellow"` (→ `theme.yellow4`, a different hex):
|
|
39
|
+
* the source CSS reads `var(--gnome-warning-bg-color, #f6d32d)` directly
|
|
40
|
+
* with no `color-mix()` darkening step, so the semantic warning token
|
|
41
|
+
* itself — already tracking dark mode and every contrast level — is the
|
|
42
|
+
* exact match, not an approximation through the fixed palette. Stars carry
|
|
43
|
+
* no `label` on `Icon` (decorative — `iconAccessibilityProps` already hides
|
|
44
|
+
* an unlabeled icon from the tree); the accessible name lives on the
|
|
45
|
+
* container (read-only) or each `Pressable` (interactive) instead, mirroring
|
|
46
|
+
* `ToggleGroupItem`'s icon-only items.
|
|
47
|
+
*/
|
|
48
|
+
export declare const RatingStars: ({ value, max, onChange, size, disabled, accessibilityLabel, style, testID, }: RatingStarsProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { TimeValue } from './timeUtils';
|
|
3
|
+
export interface TimeFieldsProps {
|
|
4
|
+
/** The time the columns show. Always concrete — callers supply the fallback. */
|
|
5
|
+
value: TimeValue;
|
|
6
|
+
/** Called with the whole time whenever any column moves. */
|
|
7
|
+
onChange: (value: TimeValue) => void;
|
|
8
|
+
/** 12- or 24-hour presentation. Defaults to `24`. */
|
|
9
|
+
hourCycle?: 12 | 24;
|
|
10
|
+
/** Minute increment for the spinner. Defaults to `1`. */
|
|
11
|
+
minuteStep?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Prefix for each column's accessible label — `"Start"` gives
|
|
14
|
+
* "Start hours". Needed when a panel carries more than one set of columns.
|
|
15
|
+
*/
|
|
16
|
+
labelPrefix?: string;
|
|
17
|
+
style?: StyleProp<ViewStyle>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The hour/minute (and AM/PM) `SpinButton` columns — the panel half of
|
|
21
|
+
* `TimePicker`, split out so `DatePicker`'s `showTime` footer can reuse the
|
|
22
|
+
* same 12/24-hour bookkeeping without re-implementing it.
|
|
23
|
+
*
|
|
24
|
+
* Ported from `@gnome-ui/react`'s `TimePicker/TimeFields.tsx`: mirrors its
|
|
25
|
+
* prop API and `to12`/`to24` bookkeeping exactly, rebuilt on this package's
|
|
26
|
+
* own `SpinButton` (already shipped in Tier 5, with a matching `wrap`
|
|
27
|
+
* boolean and `format: (n: number) => string` callback — confirmed by
|
|
28
|
+
* reading `SpinButton.tsx` before wiring this up, no new prop needed for the
|
|
29
|
+
* AM/PM column's "numeric spinner whose `format` maps 0/1 to text" trick).
|
|
30
|
+
*
|
|
31
|
+
* **Not exported from the package**: `TimePicker` is this module's public
|
|
32
|
+
* face; `DatePicker`'s `showTime` footer imports it directly via
|
|
33
|
+
* `@/components/TimePicker/TimeFields`, the same cross-folder internal
|
|
34
|
+
* import `Calendar/calendarUtils.ts`'s `WeekStart` already established.
|
|
35
|
+
*/
|
|
36
|
+
export declare const TimeFields: ({ value, onChange, hourCycle, minuteStep, labelPrefix, style, }: TimeFieldsProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { PopoverPlacement } from '../Popover';
|
|
3
|
+
import { TimeValue } from './timeUtils';
|
|
4
|
+
export type { TimeValue } from './timeUtils';
|
|
5
|
+
export interface TimePickerProps {
|
|
6
|
+
/** Controlled selected time. Pass `null` for "no selection". */
|
|
7
|
+
value?: TimeValue | null;
|
|
8
|
+
/** Initial selected time when uncontrolled. Defaults to `null`. */
|
|
9
|
+
defaultValue?: TimeValue | null;
|
|
10
|
+
/** Called when the user changes the time. */
|
|
11
|
+
onChange?: (value: TimeValue) => void;
|
|
12
|
+
/** 12- or 24-hour presentation. Defaults to `24`. */
|
|
13
|
+
hourCycle?: 12 | 24;
|
|
14
|
+
/** Minute increment for the spinner. Defaults to `1`. */
|
|
15
|
+
minuteStep?: number;
|
|
16
|
+
/** Text shown in the trigger while no time is selected. */
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
/** Visible label rendered above the trigger. */
|
|
19
|
+
label?: string;
|
|
20
|
+
/** Accessible name for the trigger when no visible `label` is provided. */
|
|
21
|
+
accessibilityLabel?: string;
|
|
22
|
+
/** Disable the control. */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/** Preferred popover placement relative to the trigger. Defaults to `'bottom'`. */
|
|
25
|
+
placement?: PopoverPlacement;
|
|
26
|
+
style?: StyleProp<ViewStyle>;
|
|
27
|
+
testID?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hour/minute selection built from paired `SpinButton`s inside a `Popover`,
|
|
31
|
+
* behind an entry-styled trigger — mirrors the `GtkSpinButton` + `GtkPopover`
|
|
32
|
+
* composition GNOME apps use for time entry, with 12- and 24-hour support.
|
|
33
|
+
*
|
|
34
|
+
* Rebuilt on this package's own already-shipped `Popover` (Tier 5) rather
|
|
35
|
+
* than reinventing its trigger-rect + panel-size positioning, the same
|
|
36
|
+
* standing pitfall `DatePicker` already avoided. The panel is just
|
|
37
|
+
* `TimeFields` — no Done button, unlike `DatePicker`'s `showTime` footer:
|
|
38
|
+
* there is no calendar tap to disambiguate from a close here, so each
|
|
39
|
+
* column commits live and the popover only closes the same way `Dropdown`'s
|
|
40
|
+
* does, by tapping outside or the trigger again.
|
|
41
|
+
*
|
|
42
|
+
* **`TimeFields`/`timeUtils` moved here from `DatePicker`'s own folder**,
|
|
43
|
+
* where they first shipped as an internal dependency of its `showTime`
|
|
44
|
+
* footer — this is their intended public home (per the ROADMAP note left
|
|
45
|
+
* when `DatePicker` shipped), `DatePicker` now imports them from here
|
|
46
|
+
* instead of carrying its own copy.
|
|
47
|
+
*
|
|
48
|
+
* The web version's entire keyboard layer drops (no `ArrowDown`-opens focus
|
|
49
|
+
* management, no `Enter`/`Space` on the trigger) — the same touch-first
|
|
50
|
+
* convention `DatePicker` already follows. `locale` is dropped in favor of
|
|
51
|
+
* `GnomeProvider`'s app-wide `useDateTimeFormatter`, same as `DatePicker`.
|
|
52
|
+
*
|
|
53
|
+
* @see https://developer.gnome.org/hig/patterns/controls/spin-buttons.html
|
|
54
|
+
*/
|
|
55
|
+
export declare const TimePicker: ({ value: controlledValue, defaultValue, onChange, hourCycle, minuteStep, placeholder, label, accessibilityLabel, disabled, placement, style, testID, }: TimePickerProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure time helpers shared by `TimePicker` and `DatePicker`'s `showTime`
|
|
3
|
+
* footer. Ported verbatim from `@gnome-ui/react`'s `TimePicker/timeUtils.ts`
|
|
4
|
+
* — no DOM dependency there already, the same `calendarUtils.ts` precedent.
|
|
5
|
+
*
|
|
6
|
+
* Not exported from the package barrel — `DatePicker` imports it directly
|
|
7
|
+
* via `@/components/TimePicker/timeUtils`, the same cross-folder internal
|
|
8
|
+
* import `Calendar/calendarUtils.ts`'s `WeekStart` already established.
|
|
9
|
+
*/
|
|
10
|
+
/** A wall-clock time, in 24-hour terms. */
|
|
11
|
+
export interface TimeValue {
|
|
12
|
+
/** Hours, `0`–`23`. */
|
|
13
|
+
hours: number;
|
|
14
|
+
/** Minutes, `0`–`59`. */
|
|
15
|
+
minutes: number;
|
|
16
|
+
}
|
|
17
|
+
/** Zero-padded two-digit rendering for a clock column. */
|
|
18
|
+
export declare const pad2: (n: number) => string;
|
|
19
|
+
/** Split a 0–23 hour into its 12-hour parts (`period`: 0 = AM, 1 = PM). */
|
|
20
|
+
export declare const to12: (hours24: number) => {
|
|
21
|
+
hour: number;
|
|
22
|
+
period: number;
|
|
23
|
+
};
|
|
24
|
+
/** Recombine a 12-hour clock reading into a 0–23 hour. */
|
|
25
|
+
export declare const to24: (hour12: number, period: number) => number;
|
|
26
|
+
/** The wall-clock time carried by a `Date`. */
|
|
27
|
+
export declare const timeOf: (date: Date) => TimeValue;
|
|
28
|
+
/**
|
|
29
|
+
* `date`'s calendar day at `time`'s wall clock.
|
|
30
|
+
*
|
|
31
|
+
* A local `Date` cannot represent an hour that a DST spring-forward skips, and
|
|
32
|
+
* the platform silently shifts it (02:30 → 03:30). That shift is kept — it is
|
|
33
|
+
* the only real instant for that reading — so callers should read the result
|
|
34
|
+
* back rather than assume the requested hour survived.
|
|
35
|
+
*/
|
|
36
|
+
export declare const mergeDateAndTime: (date: Date, time: TimeValue) => Date;
|