@ahrowe/ui 0.39.1 → 0.41.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 (203) hide show
  1. package/README.md +15 -14
  2. package/dist/cjs-types/common/ahroweProvider/ahroweProvider.d.ts +4 -0
  3. package/dist/cjs-types/common/ahroweProvider/ahroweProvider.types.d.ts +12 -0
  4. package/dist/cjs-types/common/ahroweProvider/index.d.ts +2 -0
  5. package/dist/cjs-types/common/bodyEnd/portalHostContext.d.ts +6 -0
  6. package/dist/cjs-types/common/calendar/calendar.d.ts +4 -0
  7. package/dist/cjs-types/common/calendar/calendar.types.d.ts +141 -0
  8. package/dist/cjs-types/common/calendar/components/agendaList/agendaList.d.ts +5 -0
  9. package/dist/cjs-types/common/calendar/components/agendaList/agendaList.types.d.ts +23 -0
  10. package/dist/cjs-types/common/calendar/components/agendaList/index.d.ts +1 -0
  11. package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.d.ts +4 -0
  12. package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +17 -0
  13. package/dist/cjs-types/common/calendar/components/calendarHeader/index.d.ts +1 -0
  14. package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.d.ts +9 -0
  15. package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.types.d.ts +1 -0
  16. package/dist/cjs-types/common/calendar/components/compactMonth/index.d.ts +1 -0
  17. package/dist/cjs-types/common/calendar/components/monthView/index.d.ts +1 -0
  18. package/dist/cjs-types/common/calendar/components/monthView/monthView.d.ts +5 -0
  19. package/dist/cjs-types/common/calendar/components/monthView/monthView.types.d.ts +10 -0
  20. package/dist/cjs-types/common/calendar/components/timeGrid/index.d.ts +1 -0
  21. package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.d.ts +5 -0
  22. package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.types.d.ts +40 -0
  23. package/dist/cjs-types/common/calendar/dates.d.ts +50 -0
  24. package/dist/cjs-types/common/calendar/format.d.ts +32 -0
  25. package/dist/cjs-types/common/calendar/gesture.d.ts +32 -0
  26. package/dist/cjs-types/common/calendar/index.d.ts +2 -0
  27. package/dist/cjs-types/common/calendar/layout.d.ts +74 -0
  28. package/dist/cjs-types/common/calendar/useGestures.d.ts +37 -0
  29. package/dist/cjs-types/common/calendar/usePager.d.ts +20 -0
  30. package/dist/cjs-types/common/calendar/view.types.d.ts +26 -0
  31. package/dist/cjs-types/common/configProvider/configProvider.types.d.ts +3 -0
  32. package/dist/cjs-types/common/confirmModal/confirmModal.types.d.ts +1 -1
  33. package/dist/cjs-types/common/datePicker/index.d.ts +1 -1
  34. package/dist/cjs-types/common/errorBoundary/errorBoundary.types.d.ts +2 -2
  35. package/dist/cjs-types/common/modal/modal.types.d.ts +4 -3
  36. package/dist/cjs-types/common/themeProvider/index.d.ts +1 -1
  37. package/dist/cjs-types/common/themeProvider/theme.types.d.ts +16 -0
  38. package/dist/cjs-types/common/themeProvider/themeProvider.d.ts +7 -9
  39. package/dist/cjs-types/common/themeProvider/themeVariablesContext.d.ts +2 -2
  40. package/dist/cjs-types/common/toast/index.d.ts +1 -2
  41. package/dist/cjs-types/common/toast/toast.types.d.ts +4 -4
  42. package/dist/cjs-types/common/toast/toastHost.d.ts +4 -0
  43. package/dist/cjs-types/common/toast/toastService.d.ts +1 -1
  44. package/dist/cjs-types/common/utils/day.d.ts +8 -0
  45. package/dist/cjs-types/common/virtualList/useColumns.d.ts +3 -1
  46. package/dist/cjs-types/index.d.ts +4 -1
  47. package/dist/esm/common/ahroweProvider/ahroweProvider.mjs +2 -0
  48. package/dist/esm/common/ahroweProvider/ahroweProvider.mjs.map +1 -0
  49. package/dist/esm/common/bodyEnd/bodyEnd.mjs +1 -1
  50. package/dist/esm/common/bodyEnd/bodyEnd.mjs.map +1 -1
  51. package/dist/esm/common/bodyEnd/portalHostContext.mjs +2 -0
  52. package/dist/esm/common/bodyEnd/portalHostContext.mjs.map +1 -0
  53. package/dist/esm/common/calendar/calendar.mjs +2 -0
  54. package/dist/esm/common/calendar/calendar.mjs.map +1 -0
  55. package/dist/esm/common/calendar/calendar.module.mjs +2 -0
  56. package/dist/esm/common/calendar/calendar.module.mjs.map +1 -0
  57. package/dist/esm/common/calendar/calendar.types.mjs +2 -0
  58. package/dist/esm/common/calendar/calendar.types.mjs.map +1 -0
  59. package/dist/esm/common/calendar/components/agendaList/agendaList.mjs +2 -0
  60. package/dist/esm/common/calendar/components/agendaList/agendaList.mjs.map +1 -0
  61. package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs +2 -0
  62. package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs.map +1 -0
  63. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs +2 -0
  64. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs.map +1 -0
  65. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs +2 -0
  66. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs.map +1 -0
  67. package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs +2 -0
  68. package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs.map +1 -0
  69. package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs +2 -0
  70. package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs.map +1 -0
  71. package/dist/esm/common/calendar/components/monthView/monthView.mjs +2 -0
  72. package/dist/esm/common/calendar/components/monthView/monthView.mjs.map +1 -0
  73. package/dist/esm/common/calendar/components/monthView/monthView.module.mjs +2 -0
  74. package/dist/esm/common/calendar/components/monthView/monthView.module.mjs.map +1 -0
  75. package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs +2 -0
  76. package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs.map +1 -0
  77. package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs +2 -0
  78. package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs.map +1 -0
  79. package/dist/esm/common/calendar/dates.mjs +2 -0
  80. package/dist/esm/common/calendar/dates.mjs.map +1 -0
  81. package/dist/esm/common/calendar/format.mjs +2 -0
  82. package/dist/esm/common/calendar/format.mjs.map +1 -0
  83. package/dist/esm/common/calendar/gesture.mjs +2 -0
  84. package/dist/esm/common/calendar/gesture.mjs.map +1 -0
  85. package/dist/esm/common/calendar/layout.mjs +2 -0
  86. package/dist/esm/common/calendar/layout.mjs.map +1 -0
  87. package/dist/esm/common/calendar/pager.module.mjs +2 -0
  88. package/dist/esm/common/calendar/pager.module.mjs.map +1 -0
  89. package/dist/esm/common/calendar/useGestures.mjs +2 -0
  90. package/dist/esm/common/calendar/useGestures.mjs.map +1 -0
  91. package/dist/esm/common/calendar/usePager.mjs +2 -0
  92. package/dist/esm/common/calendar/usePager.mjs.map +1 -0
  93. package/dist/esm/common/carousel/carousel.module.mjs.map +1 -1
  94. package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
  95. package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
  96. package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
  97. package/dist/esm/common/datePicker/dateFunctions.mjs +1 -1
  98. package/dist/esm/common/datePicker/datePicker.mjs +1 -1
  99. package/dist/esm/common/errorBoundary/errorBoundary.mjs +2 -2
  100. package/dist/esm/common/hooks/useAnchorTracking.mjs.map +1 -1
  101. package/dist/esm/common/input/input.mjs +1 -1
  102. package/dist/esm/common/input/input.mjs.map +1 -1
  103. package/dist/esm/common/modal/modal.mjs +1 -1
  104. package/dist/esm/common/modal/modal.mjs.map +1 -1
  105. package/dist/esm/common/popover/popover.mjs +1 -1
  106. package/dist/esm/common/popover/popover.mjs.map +1 -1
  107. package/dist/esm/common/scrollFade/scrollFade.mjs +1 -1
  108. package/dist/esm/common/scrollbarProvider/scrollbarProvider.module.mjs.map +1 -1
  109. package/dist/esm/common/tabHeader/tabHeader.module.mjs.map +1 -1
  110. package/dist/esm/common/themeProvider/themeProvider.mjs +1 -1
  111. package/dist/esm/common/themeProvider/themeProvider.mjs.map +1 -1
  112. package/dist/esm/common/themeProvider/themeVariablesContext.mjs.map +1 -1
  113. package/dist/esm/common/toast/toastHost.mjs +2 -0
  114. package/dist/esm/common/toast/toastHost.mjs.map +1 -0
  115. package/dist/esm/common/toast/toastService.mjs +1 -1
  116. package/dist/esm/common/toast/toastService.mjs.map +1 -1
  117. package/dist/esm/common/tooltip/tooltip.module.mjs.map +1 -1
  118. package/dist/esm/common/utils/day.mjs +1 -1
  119. package/dist/esm/common/utils/day.mjs.map +1 -1
  120. package/dist/esm/common/virtualList/useColumns.mjs +1 -1
  121. package/dist/esm/common/virtualList/useColumns.mjs.map +1 -1
  122. package/dist/esm/common/virtualList/virtualList.mjs +1 -1
  123. package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
  124. package/dist/esm/index.mjs +1 -1
  125. package/dist/index.cjs +3 -3
  126. package/dist/index.cjs.map +1 -1
  127. package/dist/mcp.js +2 -2
  128. package/dist/style.css +1 -1
  129. package/dist/types/common/ahroweProvider/ahroweProvider.d.ts +4 -0
  130. package/dist/types/common/ahroweProvider/ahroweProvider.types.d.ts +12 -0
  131. package/dist/types/common/ahroweProvider/index.d.ts +2 -0
  132. package/dist/types/common/bodyEnd/portalHostContext.d.ts +6 -0
  133. package/dist/types/common/calendar/calendar.d.ts +4 -0
  134. package/dist/types/common/calendar/calendar.types.d.ts +141 -0
  135. package/dist/types/common/calendar/components/agendaList/agendaList.d.ts +5 -0
  136. package/dist/types/common/calendar/components/agendaList/agendaList.types.d.ts +23 -0
  137. package/dist/types/common/calendar/components/agendaList/index.d.ts +1 -0
  138. package/dist/types/common/calendar/components/calendarHeader/calendarHeader.d.ts +4 -0
  139. package/dist/types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +17 -0
  140. package/dist/types/common/calendar/components/calendarHeader/index.d.ts +1 -0
  141. package/dist/types/common/calendar/components/compactMonth/compactMonth.d.ts +9 -0
  142. package/dist/types/common/calendar/components/compactMonth/compactMonth.types.d.ts +1 -0
  143. package/dist/types/common/calendar/components/compactMonth/index.d.ts +1 -0
  144. package/dist/types/common/calendar/components/monthView/index.d.ts +1 -0
  145. package/dist/types/common/calendar/components/monthView/monthView.d.ts +5 -0
  146. package/dist/types/common/calendar/components/monthView/monthView.types.d.ts +10 -0
  147. package/dist/types/common/calendar/components/timeGrid/index.d.ts +1 -0
  148. package/dist/types/common/calendar/components/timeGrid/timeGrid.d.ts +5 -0
  149. package/dist/types/common/calendar/components/timeGrid/timeGrid.types.d.ts +40 -0
  150. package/dist/types/common/calendar/dates.d.ts +50 -0
  151. package/dist/types/common/calendar/format.d.ts +32 -0
  152. package/dist/types/common/calendar/gesture.d.ts +32 -0
  153. package/dist/types/common/calendar/index.d.ts +2 -0
  154. package/dist/types/common/calendar/layout.d.ts +74 -0
  155. package/dist/types/common/calendar/useGestures.d.ts +37 -0
  156. package/dist/types/common/calendar/usePager.d.ts +20 -0
  157. package/dist/types/common/calendar/view.types.d.ts +26 -0
  158. package/dist/types/common/configProvider/configProvider.types.d.ts +3 -0
  159. package/dist/types/common/confirmModal/confirmModal.types.d.ts +1 -1
  160. package/dist/types/common/datePicker/index.d.ts +1 -1
  161. package/dist/types/common/errorBoundary/errorBoundary.types.d.ts +2 -2
  162. package/dist/types/common/modal/modal.types.d.ts +4 -3
  163. package/dist/types/common/themeProvider/index.d.ts +1 -1
  164. package/dist/types/common/themeProvider/theme.types.d.ts +16 -0
  165. package/dist/types/common/themeProvider/themeProvider.d.ts +7 -9
  166. package/dist/types/common/themeProvider/themeVariablesContext.d.ts +2 -2
  167. package/dist/types/common/toast/index.d.ts +1 -2
  168. package/dist/types/common/toast/toast.types.d.ts +4 -4
  169. package/dist/types/common/toast/toastHost.d.ts +4 -0
  170. package/dist/types/common/toast/toastService.d.ts +1 -1
  171. package/dist/types/common/utils/day.d.ts +8 -0
  172. package/dist/types/common/virtualList/useColumns.d.ts +3 -1
  173. package/dist/types/index.d.ts +4 -1
  174. package/docs/AhroweProvider.md +90 -0
  175. package/docs/BodyEnd.md +5 -12
  176. package/docs/Breadcrumb.md +0 -2
  177. package/docs/CLAUDE.md +21 -16
  178. package/docs/Calendar.md +184 -0
  179. package/docs/CommandPalette.md +0 -2
  180. package/docs/ConfigProvider.md +12 -8
  181. package/docs/ConfirmModal.md +1 -3
  182. package/docs/DatePicker.md +9 -2
  183. package/docs/ErrorBoundary.md +5 -3
  184. package/docs/FormValidatorGroup.md +1 -1
  185. package/docs/KlipyPicker.md +1 -1
  186. package/docs/Menu.md +0 -2
  187. package/docs/Modal.md +2 -4
  188. package/docs/MultiSelect.md +0 -2
  189. package/docs/OtpInput.md +0 -2
  190. package/docs/Popover.md +0 -2
  191. package/docs/RadioGroup.md +1 -1
  192. package/docs/ScrollbarProvider.md +4 -0
  193. package/docs/SplitButton.md +0 -2
  194. package/docs/ThemeProvider.md +13 -10
  195. package/docs/TimeInput.md +2 -0
  196. package/docs/Toast.md +18 -17
  197. package/docs/Tooltip.md +1 -1
  198. package/docs/VirtualList.md +0 -2
  199. package/package.json +1 -1
  200. package/dist/cjs-types/common/toast/toastProvider.d.ts +0 -8
  201. package/dist/esm/common/toast/toastProvider.mjs +0 -2
  202. package/dist/esm/common/toast/toastProvider.mjs.map +0 -1
  203. package/dist/types/common/toast/toastProvider.d.ts +0 -8
@@ -14,7 +14,7 @@ export interface ConfirmModalProps extends Omit<HtmlProps<HTMLDivElement>, 'onCl
14
14
  style?: CSSProperties;
15
15
  onClose?: (didSubmit: boolean) => void;
16
16
  onConfirm?: () => void | Promise<void>;
17
- title?: string;
17
+ title?: ReactNode;
18
18
  content?: ReactNode;
19
19
  isOpen?: boolean;
20
20
  isDelete?: boolean;
@@ -1,3 +1,3 @@
1
1
  export { default } from './datePicker.js';
2
2
  export * from './datePicker.types.js';
3
- export { dateToDay, dayToDate } from '../utils/day.js';
3
+ export { dateToDay, dayToDate, dateToTime, dayTimeToDate } from '../utils/day.js';
@@ -19,9 +19,9 @@ export interface ErrorBoundaryLabels {
19
19
  copied?: string;
20
20
  /** Reset button label. Default: "Try again". */
21
21
  reset?: string;
22
- /** Toast shown after a successful copy (only visible if `ToastProvider` is mounted). */
22
+ /** Toast shown after a successful copy, when the boundary is inside an `AhroweProvider`. */
23
23
  copySuccessToast?: string;
24
- /** Toast shown if the copy fails (only visible if `ToastProvider` is mounted). */
24
+ /** Toast shown if the copy fails, when the boundary is inside an `AhroweProvider`. */
25
25
  copyErrorToast?: string;
26
26
  }
27
27
  export interface ErrorBoundaryProps extends Omit<HtmlProps, 'title' | 'onError'> {
@@ -1,4 +1,4 @@
1
- import { CSSProperties } from 'react';
1
+ import { CSSProperties, ReactNode } from 'react';
2
2
  import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types.js';
3
3
  import { Presentation } from '../configProvider/presentation.types.js';
4
4
  export type ModalSlots = 'container' | 'backdrop' | 'modal' | 'header' | 'title' | 'closeButton' | 'body' | 'footer';
@@ -7,9 +7,10 @@ export interface ModalLabels {
7
7
  /** Close button, read out by screen readers. */
8
8
  close?: string;
9
9
  }
10
- export interface ModalProps extends HtmlProps<HTMLDivElement> {
10
+ export interface ModalProps extends Omit<HtmlProps<HTMLDivElement>, 'title'> {
11
11
  children?: React.ReactNode;
12
- title?: string;
12
+ /** Heading in the header. Its text becomes the dialog's accessible name, unless `aria-label` is passed. */
13
+ title?: ReactNode;
13
14
  isOpen?: boolean;
14
15
  onClose?: () => void;
15
16
  /** Applied to the modal panel itself */
@@ -1,4 +1,4 @@
1
1
  export { default } from './themeProvider.js';
2
2
  export { defaultTheme } from './defaultTheme.js';
3
3
  export { lightTheme } from './lightTheme.js';
4
- export type { Theme, ThemeVariables } from './theme.types.js';
4
+ export type { Theme, ThemeProviderProps, ThemeVariables } from './theme.types.js';
@@ -1,3 +1,4 @@
1
+ import { ReactNode } from 'react';
1
2
  /**
2
3
  * All CSS custom properties used by the component library.
3
4
  * Every key is optional so a theme only needs to declare the variables it overrides.
@@ -205,6 +206,14 @@ export interface ThemeVariables {
205
206
  '--tree-selected-background'?: string;
206
207
  /** Selected row text. Falls back to --text-on-primary. */
207
208
  '--tree-selected-color'?: string;
209
+ /** Height of one hour in the week and day views. Pinching zooms from it. Falls back to 3em. */
210
+ '--calendar-hour-height'?: string;
211
+ /** Today's date marker. Falls back to --primary-color. */
212
+ '--calendar-today-color'?: string;
213
+ /** The current-time line. Falls back to --error-color. */
214
+ '--calendar-now-color'?: string;
215
+ /** Corner radius of an event. Falls back to 6px. */
216
+ '--calendar-event-radius'?: string;
208
217
  /** Page button size. Falls back to 36px. */
209
218
  '--pagination-size'?: string;
210
219
  /** Gap between page buttons. Falls back to 4px. */
@@ -270,3 +279,10 @@ export interface Theme {
270
279
  baseThemeId?: string;
271
280
  variables: ThemeVariables;
272
281
  }
282
+ export interface ThemeProviderProps {
283
+ children: ReactNode;
284
+ /** The themes to choose from. Defaults to `[defaultTheme]`. */
285
+ themes?: Theme[];
286
+ /** The `id` of the theme to apply, from `themes`. */
287
+ currentThemeId?: string;
288
+ }
@@ -1,10 +1,6 @@
1
1
  import { default as React, Component } from 'react';
2
- import { Theme } from './theme.types.js';
3
- interface Props {
4
- children: React.ReactNode;
5
- themes?: Theme[];
6
- currentThemeId?: string;
7
- }
2
+ import { Theme, ThemeProviderProps } from './theme.types.js';
3
+ import { ThemeVariablesContext } from './themeVariablesContext.js';
8
4
  interface State {
9
5
  resolvedVariables: Record<string, string>;
10
6
  colorFadeActive: boolean;
@@ -15,15 +11,17 @@ interface State {
15
11
  currentThemeId: string | undefined;
16
12
  };
17
13
  }
18
- declare class ThemeProvider extends Component<Props, State> {
14
+ declare class ThemeProvider extends Component<ThemeProviderProps, State> {
15
+ static contextType: React.Context<Record<string, string> | null>;
16
+ context: React.ContextType<typeof ThemeVariablesContext>;
19
17
  state: State;
20
18
  private colorFadeTimeout;
21
19
  private wrapperRef;
22
20
  private themeColorMeta;
23
21
  private createdThemeColorMeta;
24
- static getDerivedStateFromProps(props: Props, state: State): Partial<State> | null;
22
+ static getDerivedStateFromProps(props: ThemeProviderProps, state: State): Partial<State> | null;
25
23
  componentDidMount(): void;
26
- componentDidUpdate(prevProps: Props, prevState: State): void;
24
+ componentDidUpdate(prevProps: ThemeProviderProps, prevState: State): void;
27
25
  componentWillUnmount(): void;
28
26
  /**
29
27
  * Replaces the former react-helmet usage: keep a single
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * The nearest ThemeProvider's resolved variables, for content that renders outside its DOM
3
3
  * subtree. Theme variables reach a component by CSS inheritance, which a portal breaks: a
4
- * `BodyEnd` child lands wherever `#bodyEnd` happens to be, so it picks up whatever provider
5
- * wraps *that* node rather than the one it was written under.
4
+ * `BodyEnd` child lands wherever the portal target is, so it picks up whatever provider wraps
5
+ * *that* node rather than the one it was written under.
6
6
  *
7
7
  * Deliberately its own module rather than a member of `themeProvider.tsx`: BodyEnd needs the
8
8
  * context and nothing else, and importing the component for it would pull the whole
@@ -1,3 +1,2 @@
1
- export { default } from './toastProvider.js';
2
1
  export { showToast } from './toastService.js';
3
- export type { ToastProviderProps, ToastContextConfig, ToastOptions, ToastType, ToastPosition, ToastSlots, } from './toast.types.js';
2
+ export type { ToastContextConfig, ToastLabels, ToastOptions, ToastType, ToastPosition, ToastSlots, } from './toast.types.js';
@@ -19,17 +19,17 @@ export interface ToastContextConfig {
19
19
  /** Pause the auto-dismiss timer while the toast is hovered or focused. */
20
20
  pauseOnHover?: boolean;
21
21
  /**
22
- * Overrides the text a toast renders of its own. Set on `ToastProvider` for
23
- * the whole app, or per toast through `showToast` options.
22
+ * Overrides the text a toast renders of its own. Set in `AhroweProvider`'s
23
+ * `toast` for the whole app, or per toast through `showToast` options.
24
24
  */
25
25
  labels?: ToastLabels;
26
26
  }
27
- export interface ToastOptions extends ToastContextConfig {
27
+ export interface ToastOptions extends Omit<ToastContextConfig, 'allowStacking'> {
28
28
  type?: ToastType;
29
29
  classNames?: SlotClassNames<ToastSlots>;
30
30
  styles?: SlotStyles<ToastSlots>;
31
31
  }
32
- export interface ToastProviderProps extends ToastContextConfig {
32
+ export interface ToastHostProps extends ToastContextConfig {
33
33
  children: ReactNode;
34
34
  }
35
35
  export interface ToastItem extends Pick<ToastOptions, 'labels'> {
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { ToastHostProps } from './toast.types.js';
3
+ declare function ToastHost({ children, position, duration, showRemainingTime, showCloseButton, allowStacking, pauseOnHover, labels, }: ToastHostProps): React.JSX.Element;
4
+ export default ToastHost;
@@ -2,6 +2,6 @@ import { ReactNode } from 'react';
2
2
  import { ToastOptions } from './toast.types.js';
3
3
  type ShowToastFn = (content: ReactNode, options?: ToastOptions) => void;
4
4
  export declare function _registerToastHandler(fn: ShowToastFn): void;
5
- export declare function _unregisterToastHandler(): void;
5
+ export declare function _unregisterToastHandler(fn: ShowToastFn): void;
6
6
  export declare function showToast(content: ReactNode, options?: ToastOptions): void;
7
7
  export {};
@@ -14,3 +14,11 @@ export declare function formatDay({ year, month, day }: DayParts): string;
14
14
  export declare function dateToDay(date: Date): string;
15
15
  /** The first moment of a `'YYYY-MM-DD'` day in the browser's time zone. An Invalid Date for anything else. */
16
16
  export declare function dayToDate(day: string): Date;
17
+ /** The `'HH:MM'` of `date` in the browser's time zone, the value a TimeInput holds; `''` for an Invalid Date. */
18
+ export declare function dateToTime(date: Date): string;
19
+ /**
20
+ * The moment a `'YYYY-MM-DD'` day and an `'HH:MM'` time stand for in the browser's time zone,
21
+ * DatePicker's and TimeInput's values together. A time the clock skips that day resolves forwards
22
+ * (02:30 becomes 03:30), a repeated one to its first occurrence. An Invalid Date for anything else.
23
+ */
24
+ export declare function dayTimeToDate(day: string, time: string): Date;
@@ -19,6 +19,8 @@ interface UseColumnsArgs<T> {
19
19
  containerHeight: number;
20
20
  /** Re-measure `fit` columns when the container width settles (e.g. after a route transition). */
21
21
  containerWidth: number;
22
+ /** Re-measure `fit` columns when rows replace the spinner under the same `items`. */
23
+ isLoading: boolean;
22
24
  }
23
25
  export interface UseColumnsResult<T> {
24
26
  hasColumns: boolean;
@@ -48,5 +50,5 @@ export interface UseColumnsResult<T> {
48
50
  * `fit`-column width measurement that pins one shared px track across the header
49
51
  * and every row grid so they stay aligned.
50
52
  */
51
- export declare function useColumns<T>({ columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey, showColumnToggle, userWidths, isFrozen, rootRef, startIndex, endIndex, containerHeight, containerWidth, }: UseColumnsArgs<T>): UseColumnsResult<T>;
53
+ export declare function useColumns<T>({ columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey, showColumnToggle, userWidths, isFrozen, rootRef, startIndex, endIndex, containerHeight, containerWidth, isLoading, }: UseColumnsArgs<T>): UseColumnsResult<T>;
52
54
  export {};
@@ -3,6 +3,8 @@ export * from './common/accordion/index.js';
3
3
  export * from './common/actionButtons/index.js';
4
4
  export { default as ActionIcon } from './common/actionIcon/index.js';
5
5
  export * from './common/actionIcon/index.js';
6
+ export { default as AhroweProvider } from './common/ahroweProvider/index.js';
7
+ export * from './common/ahroweProvider/index.js';
6
8
  export { default as Alert } from './common/alert/index.js';
7
9
  export * from './common/alert/index.js';
8
10
  export { default as AnimatedLogo } from './common/animatedLogo/index.js';
@@ -21,6 +23,8 @@ export { default as Button } from './common/button/index.js';
21
23
  export * from './common/button/index.js';
22
24
  export { default as ButtonGroup } from './common/buttonGroup/index.js';
23
25
  export * from './common/buttonGroup/index.js';
26
+ export { default as Calendar } from './common/calendar/index.js';
27
+ export * from './common/calendar/index.js';
24
28
  export { default as Card } from './common/card/index.js';
25
29
  export * from './common/card/index.js';
26
30
  export { default as Carousel } from './common/carousel/index.js';
@@ -142,7 +146,6 @@ export { default as Timeline } from './common/timeline/index.js';
142
146
  export * from './common/timeline/index.js';
143
147
  export { default as Timer } from './common/timer/index.js';
144
148
  export * from './common/timer/index.js';
145
- export { default as ToastProvider } from './common/toast/index.js';
146
149
  export * from './common/toast/index.js';
147
150
  export { default as Tooltip } from './common/tooltip/index.js';
148
151
  export * from './common/tooltip/index.js';
@@ -0,0 +1,90 @@
1
+ # AhroweProvider
2
+
3
+ **When to use:** The one wrapper an app needs, at its root: it applies the theme, sets default props for every component, shows toasts and renders the element that Modal, Tooltip, Popover, Menu and Toast portal into. Nest another one for a section with its own theme or defaults.
4
+
5
+ **Keywords:** setup, getting started, install, bootstrap, app shell, dark mode, notifications
6
+
7
+ **Import:** `import { AhroweProvider } from '@ahrowe/ui'`
8
+ **Types:** `import type { AhroweProviderProps } from '@ahrowe/ui'`
9
+
10
+ ```tsx
11
+ import '@ahrowe/ui/style.css';
12
+ import { AhroweProvider, defaultTheme, lightTheme, useTheme } from '@ahrowe/ui';
13
+
14
+ // Keep `themes` stable, here at module scope: a new array on every render reads as a theme change.
15
+ const THEMES = [defaultTheme, lightTheme];
16
+
17
+ function Root() {
18
+ const { currentThemeId } = useTheme();
19
+
20
+ return (
21
+ <AhroweProvider
22
+ themes={THEMES}
23
+ currentThemeId={currentThemeId}
24
+ defaultProps={{ Input: { alwaysFloatLabel: true } }}
25
+ toast={{ position: 'bottom-right', duration: 3000 }}
26
+ >
27
+ <App />
28
+ </AhroweProvider>
29
+ );
30
+ }
31
+ ```
32
+
33
+ Every prop is optional. `<AhroweProvider><App /></AhroweProvider>` applies `defaultTheme` and shows toasts with their built-in settings.
34
+
35
+ **Key props:**
36
+
37
+ | Prop | Type | Default | Description |
38
+ |------|------|---------|-------------|
39
+ | `themes` | `Theme[]` | `[defaultTheme]` | The themes to choose from. See [ThemeProvider.md](ThemeProvider.md) |
40
+ | `currentThemeId` | `string` | the first theme without a `baseThemeId` | The `id` of the theme to apply |
41
+ | `defaultProps` | `ComponentDefaults` | | Default props per component. See [ConfigProvider.md](ConfigProvider.md) |
42
+ | `presentation` | `Presentation` | | How every sheet-capable component presents. See [ConfigProvider.md](ConfigProvider.md) |
43
+ | `toast` | `ToastContextConfig` | | Settings for every toast `showToast` shows. See [Toast.md](Toast.md) |
44
+ | `scrollbars` | `boolean` | `true` | Styles every scrollbar inside the app in the theme's colours. See **Scrollbars** |
45
+
46
+ ## What it renders
47
+
48
+ The theme's wrapper `div`. Inside it, in a `display: contents` element that styles the scrollbars (unless `scrollbars={false}`), come an empty `<template>`, your app and, after it, the element everything portalled renders into. That is why no `<div id="bodyEnd" />` is needed. Portalled panels stay inside the theme's wrapper and come after the app, so they paint above it. Each one gets the font and colours of the theme it was written under, a nested one included.
49
+
50
+ On the server, and while hydrating, nothing is portalled: the server has nowhere to put it. Panels appear on the render right after hydration.
51
+
52
+ ## Nesting
53
+
54
+ A nested `AhroweProvider` applies its `themes`, `currentThemeId`, `defaultProps` and `presentation` to its section. Its `defaultProps` merge with the outer ones per component, the same as nested `ConfigProvider`s. Toasts, scrollbars and the portal element stay with the outermost provider, so a nested `toast` or `scrollbars` is ignored, with a warning.
55
+
56
+ Only a provider inside another `AhroweProvider` counts as nested. Put the outer one at the root first: one placed around a section of an app that has none renders the portal element inside that section, where an `overflow: hidden` or a `transform` around it clips every panel.
57
+
58
+ `ThemeProvider` and `ConfigProvider` still work on their own, for a section that needs only one of the two.
59
+
60
+ ## Scrollbars
61
+
62
+ Every scrollbar inside the provider, portalled panels included, is thin, with a rounded thumb in the theme's `--background-accent-light`. The page's own scrollbar, when the window itself scrolls, gets the same thumb colour: it belongs to `<html>`, outside the provider, so the provider hands the colour up in `--ahrowe-page-scrollbar-thumb`. A browser without `scrollbar-color` keeps its own page scrollbar.
63
+
64
+ None of this outweighs a rule of yours. Every one of these rules has zero specificity, so any scrollbar rule on an element, on `<html>` or on `:root` wins. `scrollbars={false}` turns all of it off; `ScrollbarProvider` then styles one region at a time.
65
+
66
+ ## Migrating from separate providers
67
+
68
+ ```tsx
69
+ // Before
70
+ <ThemeProvider themes={THEMES} currentThemeId={currentThemeId}>
71
+ <ConfigProvider defaultProps={defaults}>
72
+ <ToastProvider position="bottom-right">
73
+ <App />
74
+ </ToastProvider>
75
+ </ConfigProvider>
76
+ <div id="bodyEnd" />
77
+ </ThemeProvider>
78
+
79
+ // After
80
+ <AhroweProvider
81
+ themes={THEMES}
82
+ currentThemeId={currentThemeId}
83
+ defaultProps={defaults}
84
+ toast={{ position: 'bottom-right' }}
85
+ >
86
+ <App />
87
+ </AhroweProvider>
88
+ ```
89
+
90
+ Delete the `<div id="bodyEnd" />`, including one in `index.html`: inside `AhroweProvider` nothing renders into it. Delete a `ScrollbarProvider` around the app too, or, if the app had none, pass `scrollbars={false}` to keep the browser's scrollbars. `ToastProvider` was removed in 0.41, and its props are the keys of `toast`.
package/docs/BodyEnd.md CHANGED
@@ -1,19 +1,12 @@
1
1
  # BodyEnd
2
2
 
3
- **When to use:** Renders children via a React portal into a `#bodyEnd` DOM node. Use for modals, toasts, tooltips, or any UI that must escape the stacking context of its parent.
3
+ **When to use:** Renders children through a React portal, to the end of the app. Use for modals, toasts, tooltips, or any UI that must escape the stacking context of its parent.
4
4
 
5
5
  **Keywords:** teleport
6
6
 
7
7
  **Import:** `import { BodyEnd } from '@ahrowe/ui'`
8
8
 
9
- **Setup required:** Add `<div id="bodyEnd"></div>` inside your topmost `ThemeProvider` (usually as the last child) so portalled content inherits the theme's CSS variables.
10
-
11
- ```tsx
12
- <ThemeProvider>
13
- <App />
14
- <div id="bodyEnd"></div>
15
- </ThemeProvider>
16
- ```
9
+ **Setup:** none inside [AhroweProvider](AhroweProvider.md), which renders the element BodyEnd portals into. Without it, BodyEnd looks for an element with `id="bodyEnd"`: put `<div id="bodyEnd"></div>` inside your topmost `ThemeProvider`, as the last child, so portalled content inherits the theme.
17
10
 
18
11
  ```tsx
19
12
  import { BodyEnd } from '@ahrowe/ui';
@@ -27,9 +20,9 @@ import { BodyEnd } from '@ahrowe/ui';
27
20
 
28
21
  | Prop | Type | Description |
29
22
  |------|------|-------------|
30
- | `children` | `ReactNode` | Content rendered into `#bodyEnd` |
23
+ | `children` | `ReactNode` | Content rendered at the end of the app |
31
24
 
32
- **Note:** Returns `null` silently if `#bodyEnd` doesn't exist in the DOM.
25
+ **Note:** Outside `AhroweProvider` and without a `#bodyEnd`, it renders nothing and logs an error in development.
33
26
 
34
- **Theming crosses the portal.** Children keep the variables of the nearest `ThemeProvider` they were *written* under, not the one that happens to wrap `#bodyEnd`. BodyEnd applies them through a `display: contents` wrapper, which generates no box — positioning, stacking and clipping are unchanged — while custom properties still inherit. Variables that theme leaves unset fall through to whatever wraps `#bodyEnd`, the same cascade the children would have seen rendered in place. With no `ThemeProvider` above, no wrapper is added at all.
27
+ **Theming crosses the portal.** Children keep the variables of the nearest `ThemeProvider` they were *written* under, not the one that happens to wrap the element it portals into. BodyEnd applies them through a `display: contents` wrapper, which generates no box — positioning, stacking and clipping are unchanged — while custom properties still inherit. Variables that theme leaves unset fall through to whatever wraps that element, the same cascade the children would have seen rendered in place. With no `ThemeProvider` above, no wrapper is added at all.
35
28
 
@@ -80,8 +80,6 @@ function Example() {
80
80
  />
81
81
  ```
82
82
 
83
- **Requires:** `<div id="bodyEnd"></div>` in your HTML when `maxItems` is used and the trail actually collapses (the hidden-items menu is a `Popover`, which renders via portal).
84
-
85
83
  **BreadcrumbItem:**
86
84
 
87
85
  | Field | Type | Description |
package/docs/CLAUDE.md CHANGED
@@ -9,26 +9,29 @@ enums and slot names. Do not infer props from a component's name.
9
9
 
10
10
  ## Rules for every component
11
11
 
12
- - **`ThemeProvider` is required.** It injects the CSS variables every component paints with;
13
- without it they render unstyled. Wrap the app once. Two themes ship, `defaultTheme` (dark) and
14
- `lightTheme`; a custom theme is `{ id, variables: { '--primary-color': '#6200ea', … } }` passed
15
- through `themes`, selected with `currentThemeId`. `useTheme()` switches at runtime. The variable
16
- list is in ThemeProvider.md.
17
- - **Portals need a host.** Modal, Tooltip, Popover, Toast and Menu render into `<div id="bodyEnd" />`.
18
- Put it inside `ThemeProvider`, once.
12
+ - **`AhroweProvider` is required.** Wrap the app in it once (AhroweProvider.md). It injects the
13
+ CSS variables every component paints with, so without it they render unstyled; it renders the
14
+ element Modal, Tooltip, Popover, Toast and Menu portal into; and it shows toasts. Two themes
15
+ ship, `defaultTheme` (dark) and `lightTheme`; a custom theme is
16
+ `{ id, variables: { '--primary-color': '#6200ea', … } }` passed through `themes`, selected with
17
+ `currentThemeId`. `useTheme()` switches at runtime. The variable list is in ThemeProvider.md.
18
+ It already is a `ThemeProvider`, a `ConfigProvider`, a `ScrollbarProvider` and the toast host,
19
+ so do not add those or a `<div id="bodyEnd" />` beside it. A section with its own theme or defaults nests another one.
19
20
  - **Form components** (Input, NumberInput, Dropdown, MultiSelect, InputDropdown, Checkbox, Switch,
20
21
  RadioGroup, DatePicker, TimeInput, OtpInput, IconPicker) take `formValidator`, which then owns
21
22
  the value: `new FormValidator('', [Validators.required()])`. Whole forms use
22
23
  `useFormValidatorGroup`. See FormValidator.md and FormValidatorGroup.md.
23
- - **Days and times are strings**, never a `Date`: DatePicker holds `'YYYY-MM-DD'`, TimeInput
24
- `'HH:MM'`. `dateToDay` and `dayToDate` convert in the browser's time zone; never use
25
- `toISOString().slice(0, 10)`, which gives the UTC day. DatePicker.md shows how to turn a day
26
- into a moment in a given time zone.
24
+ - **Days and times are strings**, never a `Date`: DatePicker and Calendar's `date` hold
25
+ `'YYYY-MM-DD'`, TimeInput `'HH:MM'`. Calendar events are moments, so they stay `Date`s.
26
+ `dateToDay` and `dayToDate` convert a day in the browser's time zone, `dayTimeToDate(day, time)`
27
+ and `dateToTime` a day and a time together. Never use `toISOString().slice(0, 10)`, which gives
28
+ the UTC day. DatePicker.md shows how to turn a day into a moment in a given time zone.
27
29
  - **Styling.** `className` and `style` hit the root element; `classNames.<slot>` and `styles.<slot>`
28
30
  hit named inner elements. Slot names are on each doc's **Slots** line. Every native attribute of
29
31
  the root element passes through (`id`, `aria-*`, `data-*`, `on*`).
30
32
  - **Text a component renders itself** (close buttons, empty messages, page labels) is set with its
31
- `labels` prop. App-wide defaults for any prop go through `ConfigProvider` (ConfigProvider.md).
33
+ `labels` prop. App-wide defaults for any prop go through `AhroweProvider`'s `defaultProps`
34
+ (ConfigProvider.md).
32
35
  - **Variants are enums**, not strings: `ButtonStyleType.Primary`, `ButtonSize.Small`. Each doc lists
33
36
  them under **Enums**.
34
37
  - **`icon` props** take a FontAwesome `IconDefinition` or any React element.
@@ -49,15 +52,17 @@ enums and slot names. Do not infer props from a component's name.
49
52
  | Accordion.md | Accordion | Collapsible sections for progressive disclosure — FAQs, settings panels, long-form content that users expand on demand |
50
53
  | ActionButtons.md | ActionButtons | Standardised Submit / Cancel button pair for forms, dialogs, and drawer footers |
51
54
  | ActionIcon.md | ActionIcon | Clickable icon button without a label — toolbar actions, table row actions, icon-only controls |
55
+ | AhroweProvider.md | AhroweProvider | The one wrapper an app needs, at its root: it applies the theme, sets default props for every component, shows toasts and renders the element that Modal, Tooltip, Popover, Menu and Toast portal into |
52
56
  | Alert.md | Alert, AlertStyleType | A persistent inline status message, used for form-level errors, page/section banners, empty-config warnings, and "here's what changed" notices |
53
57
  | AnimatedLogo.md | AnimatedLogo | A self-drawing SVG mark for splash/loading screens, empty states, or anywhere a brand or icon mark should feel alive rather than static |
54
58
  | AnimatedText.md | AnimatedText, AnimatedTextVariant, AnimatedTextUnit | Decorative text entrance or emphasis effect, for hero headlines, empty-state messages, "premium"/"new" callouts, loading/decoding states |
55
59
  | Avatar.md | Avatar, AvatarGroup | User or entity image — profile pictures, comment authors, member lists |
56
60
  | Badge.md | Badge, BadgeStyleType, BadgePosition | Small count or status indicator — unread counts, notification dots, "new" markers |
57
- | BodyEnd.md | BodyEnd | Renders children via a React portal into a `#bodyEnd` DOM node |
61
+ | BodyEnd.md | BodyEnd | Renders children through a React portal, to the end of the app |
58
62
  | Breadcrumb.md | Breadcrumb | A trail showing the current page's position within a hierarchy, with links back to each ancestor, such as a file browser path, a category/subcategory drill-down, or a multi-level settings page |
59
63
  | Button.md | Button, ButtonStyleType, ButtonSize, ButtonType | Primary interactive action trigger |
60
64
  | ButtonGroup.md | ButtonGroup, ButtonGroupOrientation | Joins a row (or column) of buttons into a single seamless control, merging their borders and rounding only the outer corners |
65
+ | Calendar.md | Calendar, CalendarView | Showing and editing your own events over time, in month, week, day and agenda views: bookings, shifts, appointments, a team schedule |
61
66
  | Card.md | Card, CardStyleType, CardHeader, CardMedia, CardContent, CardActions | Surface container for grouping related content — list items, profile cards, dashboard tiles, product listings |
62
67
  | Carousel.md | Carousel | A slide track for stepping through a set of items one at a time, with arrows, dots, and drag/swipe support, plus optional autoplay |
63
68
  | Checkbox.md | Checkbox | Boolean toggle input — settings, multi-select lists, accept terms, feature flags |
@@ -67,7 +72,7 @@ enums and slot names. Do not infer props from a component's name.
67
72
  | ConfigProvider.md | ConfigProvider | Set global **default props** for library components once, near the root of your app, instead of repeating the same prop on every instance |
68
73
  | ConfirmModal.md | ConfirmModal | Confirmation dialog before destructive or irreversible actions — delete, archive, send, overwrite |
69
74
  | CopyButton.md | CopyButton | Icon-only button that copies a value to the clipboard: an invoice number, an ID in a table row, an API key or share link inside an `Input` |
70
- | DatePicker.md | DatePicker, dateToDay, dayToDate | Date selection input — booking forms, birth date fields, date range pickers, deadline selectors |
75
+ | DatePicker.md | DatePicker, dateToDay, dayToDate, dateToTime, dayTimeToDate | Date selection input — booking forms, birth date fields, date range pickers, deadline selectors |
71
76
  | Divider.md | Divider, DividerTextPosition, DividerOrientation | A rule that separates sections of content — horizontal by default, filling the width of its parent |
72
77
  | Drawer.md | Drawer | Inline horizontal panel that collapses and expands by animating its width — side panels, navigation rails, detail/filter panes that slide open beside the main content |
73
78
  | DropZone.md | DropZone, DropZoneReturnType, DropZoneStatus | Drag-and-drop file upload area, optionally click-to-open the native picker |
@@ -116,12 +121,12 @@ enums and slot names. Do not infer props from a component's name.
116
121
  | Switch.md | Switch | Sliding boolean toggle — settings panels, feature flags, preference lists |
117
122
  | TabHeader.md | TabHeader | A horizontal row of tabs to switch between sibling views or sections — settings panels, dashboards, detail pages |
118
123
  | Textarea.md | Textarea | Multiline text input — comments, descriptions, notes, code snippets, long-form content |
119
- | ThemeProvider.md | ThemeProvider | Required wrapper for the entire component library |
124
+ | ThemeProvider.md | ThemeProvider | Applies a theme to its subtree, injecting its CSS custom properties as inline styles so every component inside can use them |
120
125
  | Tilt.md | Tilt, TiltGroup | Wrap content that should tilt toward the cursor in 3D |
121
126
  | TimeInput.md | TimeInput | Time-of-day selection — appointment times, opening hours, shift starts, reminders |
122
127
  | Timeline.md | Timeline, TimelineAlignment, TimelineItemStatus | A vertical list of dated events, connected by a line, for audit logs, activity feeds, order status history, and deploy logs |
123
128
  | Timer.md | Timer | A countdown timer with a depleting ring, add/remove-time and pause/cancel controls, and an imperative ref API |
124
- | Toast.md | ToastProvider, showToast | Non-blocking notifications — save confirmations, error alerts, info messages, warnings |
129
+ | Toast.md | showToast | Non-blocking notifications — save confirmations, error alerts, info messages, warnings |
125
130
  | Tooltip.md | Tooltip | Contextual help, info icons, field explanations, error pointers |
126
131
  | Tree.md | Tree, flattenTree | A hierarchical list the user can expand, collapse and pick from: categories, nested locations, folder structures, org charts |
127
132
  | VirtualList.md | VirtualList | Efficiently render large lists or tables — thousands of rows rendered with a virtualised scroll window so only visible rows are in the DOM |