@pk-design/react-tailwind 1.8.1 → 1.10.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.
Files changed (63) hide show
  1. package/dist/cjs/components/Banner/Banner.js +1 -1
  2. package/dist/cjs/components/Banner/Banner.js.map +1 -1
  3. package/dist/cjs/components/BottomNavigation/BottomNavigation.js +14 -5
  4. package/dist/cjs/components/BottomNavigation/BottomNavigation.js.map +1 -1
  5. package/dist/cjs/components/Button/Button.js +88 -60
  6. package/dist/cjs/components/Button/Button.js.map +1 -1
  7. package/dist/cjs/components/Drawer/Drawer.js +6 -2
  8. package/dist/cjs/components/Drawer/Drawer.js.map +1 -1
  9. package/dist/cjs/components/MobileHeader/MobileHeader.js +21 -3
  10. package/dist/cjs/components/MobileHeader/MobileHeader.js.map +1 -1
  11. package/dist/cjs/components/PullToRefresh/PullToRefresh.js +145 -57
  12. package/dist/cjs/components/PullToRefresh/PullToRefresh.js.map +1 -1
  13. package/dist/cjs/components/SelectBox/SelectBox.js +25 -4
  14. package/dist/cjs/components/SelectBox/SelectBox.js.map +1 -1
  15. package/dist/cjs/components/StickyActionBar/StickyActionBar.js +2 -2
  16. package/dist/cjs/components/StickyActionBar/StickyActionBar.js.map +1 -1
  17. package/dist/cjs/components/Toast/Toast.js +1 -1
  18. package/dist/cjs/components/Toast/Toast.js.map +1 -1
  19. package/dist/cjs/hooks/use-breakpoint.js +48 -0
  20. package/dist/cjs/hooks/use-breakpoint.js.map +1 -0
  21. package/dist/cjs/index.js +5 -0
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/es/components/Banner/Banner.js +1 -1
  24. package/dist/es/components/Banner/Banner.js.map +1 -1
  25. package/dist/es/components/BottomNavigation/BottomNavigation.js +14 -5
  26. package/dist/es/components/BottomNavigation/BottomNavigation.js.map +1 -1
  27. package/dist/es/components/Button/Button.js +89 -61
  28. package/dist/es/components/Button/Button.js.map +1 -1
  29. package/dist/es/components/Drawer/Drawer.js +6 -2
  30. package/dist/es/components/Drawer/Drawer.js.map +1 -1
  31. package/dist/es/components/MobileHeader/MobileHeader.js +21 -3
  32. package/dist/es/components/MobileHeader/MobileHeader.js.map +1 -1
  33. package/dist/es/components/PullToRefresh/PullToRefresh.js +146 -58
  34. package/dist/es/components/PullToRefresh/PullToRefresh.js.map +1 -1
  35. package/dist/es/components/SelectBox/SelectBox.js +26 -5
  36. package/dist/es/components/SelectBox/SelectBox.js.map +1 -1
  37. package/dist/es/components/StickyActionBar/StickyActionBar.js +2 -2
  38. package/dist/es/components/StickyActionBar/StickyActionBar.js.map +1 -1
  39. package/dist/es/components/Toast/Toast.js +1 -1
  40. package/dist/es/components/Toast/Toast.js.map +1 -1
  41. package/dist/es/hooks/use-breakpoint.js +43 -0
  42. package/dist/es/hooks/use-breakpoint.js.map +1 -0
  43. package/dist/es/index.js +1 -0
  44. package/dist/es/index.js.map +1 -1
  45. package/dist/react-tailwind.cjs.js +344 -135
  46. package/dist/react-tailwind.cjs.js.map +1 -1
  47. package/dist/react-tailwind.es.js +342 -137
  48. package/dist/react-tailwind.es.js.map +1 -1
  49. package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +1 -1
  50. package/dist/types/components/BottomNavigation/BottomNavigation.types.d.ts +28 -3
  51. package/dist/types/components/Button/Button.types.d.ts +12 -6
  52. package/dist/types/components/Drawer/Drawer.types.d.ts +8 -4
  53. package/dist/types/components/MobileHeader/MobileHeader.d.ts +1 -1
  54. package/dist/types/components/MobileHeader/MobileHeader.types.d.ts +13 -0
  55. package/dist/types/components/PullToRefresh/PullToRefresh.d.ts +1 -1
  56. package/dist/types/components/PullToRefresh/PullToRefresh.types.d.ts +45 -6
  57. package/dist/types/components/SelectBox/SelectBox.types.d.ts +18 -1
  58. package/dist/types/components/StickyActionBar/StickyActionBar.types.d.ts +12 -0
  59. package/dist/types/hooks/use-breakpoint.d.ts +27 -0
  60. package/dist/types/hooks/use-breakpoint.test.d.ts +1 -0
  61. package/dist/types/index.d.ts +1 -0
  62. package/dist/types/test-utils/mock-viewport.d.ts +7 -0
  63. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import type { BottomNavigationProps } from './BottomNavigation.types';
2
- export declare function BottomNavigation({ items, activeId, onChange, fixed, showLabels, theme, activeIndicatorStyle, containerClass, itemClass, }: BottomNavigationProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function BottomNavigation({ items, activeId, onChange, fixed, showLabels, theme, activeIndicatorStyle, containerClass, itemClass, linkAs, linkHrefProp, ariaLabel, hidden, }: BottomNavigationProps): import("react/jsx-runtime").JSX.Element | null;
3
3
  export declare namespace BottomNavigation {
4
4
  var displayName: string;
5
5
  }
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ElementType, ReactNode } from 'react';
2
2
  export type BottomNavigationLabelVisibility = 'always' | 'active' | 'never';
3
3
  export type BottomNavigationTheme = 'primary' | 'dark' | 'light';
4
4
  export interface BottomNavigationItem {
@@ -18,14 +18,19 @@ export interface BottomNavigationItem {
18
18
  disabled?: boolean;
19
19
  /** Custom click handler */
20
20
  onClick?: () => void;
21
+ /**
22
+ * Destination for a navigation tab. When set, the item renders as a link
23
+ * (`linkAs`) instead of a button, so it opens in a new tab and is announced as a link.
24
+ */
25
+ href?: string;
21
26
  }
22
27
  export interface BottomNavigationProps {
23
28
  /** Array of bottom navigation items (3 to 5 recommended) */
24
29
  items: BottomNavigationItem[];
25
30
  /** Controlled active tab ID */
26
31
  activeId: string;
27
- /** Callback fired when a tab is selected */
28
- onChange: (id: string) => void;
32
+ /** Callback fired when a tab is selected (optional when items navigate via `href`) */
33
+ onChange?: (id: string) => void;
29
34
  /** Fixed positioning at bottom of viewport (default: true) */
30
35
  fixed?: boolean;
31
36
  /** Controls when tab labels are visible ('always' | 'active' | 'never', default: 'always') */
@@ -38,4 +43,24 @@ export interface BottomNavigationProps {
38
43
  containerClass?: string;
39
44
  /** Tab button item class string */
40
45
  itemClass?: string;
46
+ /**
47
+ * Element or component used for items with an `href`, e.g. a router's `Link`.
48
+ * @default 'a'
49
+ */
50
+ linkAs?: ElementType;
51
+ /**
52
+ * Prop name `linkAs` takes the destination on ('to' for react-router's `Link`).
53
+ * @default 'href'
54
+ */
55
+ linkHrefProp?: 'href' | 'to';
56
+ /**
57
+ * Accessible name of the navigation landmark.
58
+ * @default 'Bottom Navigation'
59
+ */
60
+ ariaLabel?: string;
61
+ /**
62
+ * Removes the bar from the tree (not just visually), e.g. while a full-screen task owns the bottom edge.
63
+ * @default false
64
+ */
65
+ hidden?: boolean;
41
66
  }
@@ -85,23 +85,27 @@ export interface ButtonBaseProps {
85
85
  */
86
86
  loadingText?: string;
87
87
  /**
88
- * Applies 50% border radius, producing a pill-shaped button.
88
+ * Applies a fully rounded border radius, producing a pill-shaped button
89
+ * (or a circle when combined with `iconOnly`).
89
90
  * @default false
90
91
  */
91
92
  rounded?: boolean;
92
93
  /**
93
- * Indicates that the button only contains an icon.
94
+ * Indicates that the button only contains an icon. Requires `aria-label`
95
+ * or `aria-labelledby` so the button has an accessible name.
94
96
  * @default false
95
97
  */
96
98
  iconOnly?: boolean;
97
99
  /**
98
- * Prevents outline styles on keyboard focus.
100
+ * Removes the focus ring shown on keyboard focus. Only use this when the
101
+ * button gets another visible focus indicator, e.g. via `className`.
99
102
  * @default false
100
103
  */
101
104
  noOutlineOnFocus?: boolean;
102
105
  /**
103
- * Indicates active toggle state (applies aria-pressed).
104
- * @default false
106
+ * Turns the button into a toggle: when set to `true` or `false`,
107
+ * `aria-pressed` reflects it and `true` shows a ring. Leave unset for a
108
+ * regular (non-toggle) button.
105
109
  */
106
110
  active?: boolean;
107
111
  /**
@@ -113,7 +117,9 @@ export interface ButtonBaseProps {
113
117
  */
114
118
  type?: 'button' | 'submit' | 'reset';
115
119
  /**
116
- * Standard disabled attribute. Only applies when as="button".
120
+ * Disables the button. Rendered as the native `disabled` attribute on
121
+ * `<button>`, or as `aria-disabled` (with `tabIndex={-1}` and clicks
122
+ * blocked) for any other element passed via `as`.
117
123
  */
118
124
  disabled?: boolean;
119
125
  }
@@ -1,4 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
+ import type { ResponsiveValue } from '../../hooks/use-breakpoint';
2
3
  export type DrawerAlignment = 'center' | 'start' | 'end' | 'top' | 'bottom';
3
4
  export type DrawerSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
4
5
  export interface DrawerProps {
@@ -17,10 +18,12 @@ export interface DrawerProps {
17
18
  */
18
19
  closeOnOutsideClick?: boolean;
19
20
  /**
20
- * Drawer alignment on the page ('start' | 'end' | 'top' | 'bottom' | 'center')
21
+ * Drawer alignment on the page ('start' | 'end' | 'top' | 'bottom' | 'center').
22
+ * Pass `{ base, md, lg }` to change it per breakpoint, e.g. `{ base: 'bottom', md: 'end' }`
23
+ * for a bottom sheet on phones and a side panel from 768px.
21
24
  * @default "end"
22
25
  */
23
- align?: DrawerAlignment;
26
+ align?: ResponsiveValue<DrawerAlignment>;
24
27
  /**
25
28
  * Whether to add backdrop overlay
26
29
  * @default true
@@ -52,10 +55,11 @@ export interface DrawerProps {
52
55
  */
53
56
  footerSticky?: boolean;
54
57
  /**
55
- * Drawer size ('xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full')
58
+ * Drawer size ('xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full').
59
+ * Pass `{ base, md, lg }` to change it per breakpoint, e.g. `{ base: 'full', md: 'md' }`.
56
60
  * @default "md"
57
61
  */
58
- size?: DrawerSize;
62
+ size?: ResponsiveValue<DrawerSize>;
59
63
  /**
60
64
  * Shows top-right ✕ close button
61
65
  * @default true
@@ -1,5 +1,5 @@
1
1
  import type { MobileHeaderProps } from './MobileHeader.types';
2
- export declare function MobileHeader({ title, subtitle, titleAlign, onBack, backLabel, leading, actions, searchable, searchValue: externalSearchValue, onSearchChange, searchPlaceholder, sticky, transparent, bottomSlot, className, }: MobileHeaderProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function MobileHeader({ title, subtitle, titleAlign, onBack, backLabel, leading, actions, maxVisibleActions, overflowLabel, trailing, searchable, searchValue: externalSearchValue, onSearchChange, searchPlaceholder, sticky, transparent, bottomSlot, className, }: MobileHeaderProps): import("react/jsx-runtime").JSX.Element;
3
3
  export declare namespace MobileHeader {
4
4
  var displayName: string;
5
5
  }
@@ -30,6 +30,19 @@ export interface MobileHeaderProps {
30
30
  leading?: ReactNode;
31
31
  /** Right side action items */
32
32
  actions?: MobileHeaderAction[];
33
+ /**
34
+ * Maximum icon buttons shown in the header. When `actions` has more, the
35
+ * extras collapse into a "More actions" button that opens an `ActionSheet`.
36
+ * Unset shows every action.
37
+ */
38
+ maxVisibleActions?: number;
39
+ /**
40
+ * Accessible label of the overflow button.
41
+ * @default 'More actions'
42
+ */
43
+ overflowLabel?: string;
44
+ /** Custom content after the actions, e.g. an avatar or a context switcher with its own state */
45
+ trailing?: ReactNode;
33
46
  /** Enables in-header search bar layout */
34
47
  searchable?: boolean;
35
48
  /** Controlled search input value */
@@ -1,5 +1,5 @@
1
1
  import type { PullToRefreshProps } from './PullToRefresh.types';
2
- export declare function PullToRefresh({ onRefresh, pullThreshold, maxPullDistance, disabled, refreshing: externalRefreshing, pullingContent, refreshingContent, children, className, contentClass, }: PullToRefreshProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function PullToRefresh({ onRefresh, onError, variant, pullThreshold, maxPullDistance, disabled, refreshing: externalRefreshing, pullingContent, refreshingContent, pullLabel, releaseLabel, refreshingLabel, refreshedLabel, children, className, contentClass, }: PullToRefreshProps): import("react/jsx-runtime").JSX.Element;
3
3
  export declare namespace PullToRefresh {
4
4
  var displayName: string;
5
5
  }
@@ -1,19 +1,58 @@
1
1
  import type { ReactNode } from 'react';
2
+ /**
3
+ * - `push`: a labelled pill opens above the content, which moves down with the pull.
4
+ * - `overlay`: the content stays still; a round badge slides down over it (e.g. from
5
+ * behind a sticky app header) and parks at the threshold while refreshing.
6
+ */
7
+ export type PullToRefreshVariant = 'push' | 'overlay';
2
8
  export interface PullToRefreshProps {
3
- /** Async callback function triggered when user pulls to refresh */
4
- onRefresh: () => Promise<void> | void;
5
- /** Pull distance threshold in px to trigger refresh (default: 70) */
9
+ /** Callback triggered when the user pulls past the threshold; return a promise to keep the indicator until it settles */
10
+ onRefresh: () => Promise<unknown> | void;
11
+ /** Called when `onRefresh` throws or rejects, so the failure can be shown instead of lost */
12
+ onError?: (error: unknown) => void;
13
+ /**
14
+ * Indicator style
15
+ * @default 'push'
16
+ */
17
+ variant?: PullToRefreshVariant;
18
+ /**
19
+ * Pull distance in px (after resistance) that triggers a refresh
20
+ * @default 70
21
+ */
6
22
  pullThreshold?: number;
7
- /** Maximum pull distance in px (default: 120) */
23
+ /**
24
+ * Maximum pull distance in px
25
+ * @default 120
26
+ */
8
27
  maxPullDistance?: number;
9
28
  /** Disables the pull-to-refresh touch gesture */
10
29
  disabled?: boolean;
11
30
  /** Controlled refreshing state */
12
31
  refreshing?: boolean;
13
- /** Custom content rendered while pulling down */
32
+ /** Custom content rendered while pulling down (replaces the default indicator content) */
14
33
  pullingContent?: ReactNode;
15
- /** Custom content rendered while refreshing */
34
+ /** Custom content rendered while refreshing (replaces the default indicator content) */
16
35
  refreshingContent?: ReactNode;
36
+ /**
37
+ * Indicator text before the threshold is reached (`push` variant)
38
+ * @default 'Pull down to refresh'
39
+ */
40
+ pullLabel?: string;
41
+ /**
42
+ * Indicator text once releasing will refresh (`push` variant)
43
+ * @default 'Release to refresh'
44
+ */
45
+ releaseLabel?: string;
46
+ /**
47
+ * Indicator text and screen-reader announcement while refreshing
48
+ * @default 'Refreshing...'
49
+ */
50
+ refreshingLabel?: string;
51
+ /**
52
+ * Screen-reader announcement once a refresh finishes
53
+ * @default 'Content refreshed'
54
+ */
55
+ refreshedLabel?: string;
17
56
  /** Main scrollable content node */
18
57
  children: ReactNode;
19
58
  /** Container class string */
@@ -22,11 +22,21 @@ export interface SelectBoxProps<T extends BaseOption | string = BaseOption> {
22
22
  /** List of option groups to display in the dropdown (alternative to options) */
23
23
  groups?: OptionGroup<T>[];
24
24
  /**
25
- * Currently selected option(s).
25
+ * Currently selected option(s). Passing this makes the SelectBox controlled:
26
+ * it shows exactly this value, so update it from `onChange`.
26
27
  * - For single select: a single T or null
27
28
  * - For multi-select: T[]
29
+ *
30
+ * Leave it undefined to let the SelectBox manage its own selection
31
+ * (optionally seeded with `defaultSelected`).
28
32
  */
29
33
  selected?: T | T[] | null;
34
+ /**
35
+ * Initial selection when the SelectBox is uncontrolled (`selected` not passed).
36
+ * Only read on mount; later changes are ignored. `onChange` still fires on
37
+ * every change.
38
+ */
39
+ defaultSelected?: T | T[] | null;
30
40
  /** Size scale of the SelectBox component (`"sm"` | `"md"` | `"lg"`). Defaults to `"md"`. */
31
41
  size?: SelectBoxSize;
32
42
  /** Name of the field inside option objects to use as the label (defaults to "label") */
@@ -59,6 +69,13 @@ export interface SelectBoxProps<T extends BaseOption | string = BaseOption> {
59
69
  placeholder?: string;
60
70
  /** CSS classes applied to the dropdown options container */
61
71
  dropdownContainerClass?: string;
72
+ /**
73
+ * Minimum width of the dropdown panel. By default the panel matches the
74
+ * input width; set this so it can grow wider than a narrow input. Numbers
75
+ * are treated as pixels, strings accept any CSS length (e.g. `"16rem"`).
76
+ * The panel stays left-aligned with the input.
77
+ */
78
+ dropdownMinWidth?: number | string;
62
79
  /**
63
80
  * Whether the open dropdown traps focus and makes the rest of the page inert.
64
81
  * @default false
@@ -27,4 +27,16 @@ export interface StickyActionBarProps extends HTMLAttributes<HTMLDivElement> {
27
27
  * @default "max-w-5xl"
28
28
  */
29
29
  containerMaxWidth?: string;
30
+ /**
31
+ * Pads the bar's bottom edge for `env(safe-area-inset-bottom)` so its actions clear the
32
+ * home indicator on notched phones (no effect elsewhere).
33
+ * @default true
34
+ */
35
+ safeArea?: boolean;
36
+ /**
37
+ * Distance from the viewport bottom for `fixed`/`sticky` bars, as a CSS length or variable,
38
+ * e.g. `var(--app-bottom-inset)` to sit above an app's bottom navigation.
39
+ * @default '0px'
40
+ */
41
+ bottomOffset?: string;
30
42
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Layout ranges matching Tailwind's `md` (768px) and `lg` (1024px) tokens, so a
3
+ * JS decision and an `md:`/`lg:` class always agree:
4
+ * - `compact`: phones
5
+ * - `medium`: tablets and narrow windows
6
+ * - `expanded`: desktop
7
+ *
8
+ * Width only. Unlike `useIsMobile`, touch capability is never considered, so a
9
+ * phone in landscape and a narrow desktop window get the layout for their size.
10
+ */
11
+ export type Breakpoint = 'compact' | 'medium' | 'expanded';
12
+ export declare const BREAKPOINT_QUERIES: {
13
+ readonly medium: "(min-width: 768px)";
14
+ readonly expanded: "(min-width: 1024px)";
15
+ };
16
+ /** Live result of a CSS media query. `false` during server rendering or without `matchMedia`. */
17
+ export declare const useMediaQuery: (query: string) => boolean;
18
+ /** Current layout range; `compact` during server rendering. */
19
+ export declare const useBreakpoint: () => Breakpoint;
20
+ /** A value per breakpoint; missing ranges fall back to the next smaller one. */
21
+ export type ResponsiveValue<T> = T | {
22
+ base: T;
23
+ md?: T;
24
+ lg?: T;
25
+ };
26
+ /** Resolves a `ResponsiveValue` for the current viewport. */
27
+ export declare const useResponsiveValue: <T>(value: ResponsiveValue<T>) => T;
@@ -0,0 +1 @@
1
+ export {};
@@ -54,6 +54,7 @@ export * from './components/Textarea';
54
54
  export * from './components/Toast';
55
55
  export * from './components/VirtualizedDataTable';
56
56
  export * from './components/common-type';
57
+ export * from './hooks/use-breakpoint';
57
58
  export * from './hooks/use-debounce';
58
59
  export * from './hooks/use-is-mobile';
59
60
  export * from './hooks/use-is-tablet';
@@ -0,0 +1,7 @@
1
+ export declare function mockViewport(initialWidth: number): {
2
+ resize(next: number): void;
3
+ listenerCount: () => number;
4
+ };
5
+ export declare namespace mockViewport {
6
+ var restore: () => void;
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pk-design/react-tailwind",
3
- "version": "1.8.1",
3
+ "version": "1.10.0",
4
4
  "main": "dist/react-tailwind.cjs.js",
5
5
  "module": "dist/react-tailwind.es.js",
6
6
  "types": "dist/types/index.d.ts",