@giddaa-housing/ui 3.4.0 → 3.6.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 (190) hide show
  1. package/css/components.css +13 -0
  2. package/css/generated/shared.css +1 -1
  3. package/dist/accordion.js +1 -1
  4. package/dist/activity-timeline.js +1 -1
  5. package/dist/alert.js +1 -1
  6. package/dist/auth-layout.js +1 -1
  7. package/dist/avatar.js +1 -1
  8. package/dist/badge.d.ts +5 -1
  9. package/dist/badge.js +20 -6
  10. package/dist/bar-chart.d.ts +1 -1
  11. package/dist/bar-chart.js +1 -1
  12. package/dist/breadcrumb.js +1 -1
  13. package/dist/bullet-chart.d.ts +1 -1
  14. package/dist/bullet-chart.js +1 -1
  15. package/dist/button-BS5KCibF.d.ts +33 -0
  16. package/dist/button-group.d.ts +1 -1
  17. package/dist/button-group.js +1 -1
  18. package/dist/button.d.ts +1 -1
  19. package/dist/button.js +50 -22
  20. package/dist/calendar.js +2 -2
  21. package/dist/call-card.js +1 -1
  22. package/dist/card.js +1 -1
  23. package/dist/carousel.d.ts +4 -2
  24. package/dist/carousel.js +13 -16
  25. package/dist/chart.d.ts +1 -1
  26. package/dist/chart.js +1 -1
  27. package/dist/chat.d.ts +1 -1
  28. package/dist/chat.js +1 -1
  29. package/dist/checkbox.d.ts +2 -2
  30. package/dist/checkbox.js +21 -7
  31. package/dist/collapsible.js +1 -1
  32. package/dist/combobox-CACVdp1R.js +430 -0
  33. package/dist/combobox.d.ts +9 -4
  34. package/dist/combobox.js +2 -309
  35. package/dist/cta.d.ts +1 -1
  36. package/dist/cta.js +1 -1
  37. package/dist/currency-selector.js +2 -2
  38. package/dist/data-table.d.ts +2 -2
  39. package/dist/data-table.js +1 -1
  40. package/dist/date-picker.d.ts +6 -5
  41. package/dist/date-picker.js +7 -17
  42. package/dist/details-card.js +1 -1
  43. package/dist/dialog.d.ts +3 -1
  44. package/dist/dialog.js +10 -6
  45. package/dist/dropdown-menu.d.ts +1 -1
  46. package/dist/dropdown-menu.js +1 -1
  47. package/dist/dropzone.js +1 -1
  48. package/dist/editorial-card.js +2 -4
  49. package/dist/empty-state.js +1 -1
  50. package/dist/field.d.ts +4 -1
  51. package/dist/field.js +29 -12
  52. package/dist/file-upload.js +1 -1
  53. package/dist/filter.js +1 -1
  54. package/dist/footer.d.ts +2 -2
  55. package/dist/footer.js +1 -1
  56. package/dist/funnel-chart.d.ts +1 -1
  57. package/dist/funnel-chart.js +1 -1
  58. package/dist/gallery-indicator.js +1 -1
  59. package/dist/heatmap-chart.d.ts +1 -1
  60. package/dist/icons-C9JXR5Xv.d.ts +111 -0
  61. package/dist/icons.d.ts +2 -93
  62. package/dist/icons.js +37 -1
  63. package/dist/image.d.ts +59 -0
  64. package/dist/image.js +53 -0
  65. package/dist/infinite-scroll.js +3 -29
  66. package/dist/infotip.js +1 -1
  67. package/dist/input-group.d.ts +6 -6
  68. package/dist/input-group.js +39 -14
  69. package/dist/input-otp.d.ts +2 -2
  70. package/dist/input-otp.js +32 -15
  71. package/dist/input-size-context-BMhves-J.d.ts +13 -0
  72. package/dist/input-size-context.d.ts +2 -2
  73. package/dist/input-size-context.js +9 -2
  74. package/dist/input.d.ts +20 -2
  75. package/dist/input.js +31 -12
  76. package/dist/item.js +1 -1
  77. package/dist/kpi-card.js +1 -1
  78. package/dist/label.js +1 -1
  79. package/dist/line-chart.d.ts +1 -1
  80. package/dist/line-chart.js +1 -1
  81. package/dist/list-item.js +1 -1
  82. package/dist/map-indicator.js +1 -1
  83. package/dist/mask-input.d.ts +1 -1
  84. package/dist/match.d.ts +5 -2
  85. package/dist/match.js +183 -27
  86. package/dist/media-gallery-hero.js +15 -10
  87. package/dist/media-player.js +5 -13
  88. package/dist/message.js +2 -12
  89. package/dist/mobile-sidebar.js +2 -1
  90. package/dist/multi-step-form.js +2 -2
  91. package/dist/number-input.d.ts +2 -2
  92. package/dist/number-input.js +3 -3
  93. package/dist/page-header.js +1 -1
  94. package/dist/pagination.d.ts +1 -1
  95. package/dist/pagination.js +1 -1
  96. package/dist/password-input.js +1 -1
  97. package/dist/phone-input.d.ts +2 -2
  98. package/dist/phone-input.js +16 -21
  99. package/dist/photo-gallery.js +6 -3
  100. package/dist/picker-BTXBrsl4.js +62 -0
  101. package/dist/picker-j3txxA5t.d.ts +14 -0
  102. package/dist/pie-chart.d.ts +1 -1
  103. package/dist/pie-chart.js +1 -1
  104. package/dist/popover-CNymD33m.d.ts +20 -0
  105. package/dist/popover.d.ts +1 -19
  106. package/dist/popover.js +1 -1
  107. package/dist/price-tag.d.ts +1 -1
  108. package/dist/price-tag.js +50 -22
  109. package/dist/progress.js +1 -1
  110. package/dist/property-listing-card.d.ts +68 -2
  111. package/dist/property-listing-card.js +115 -29
  112. package/dist/purchase-option-card.js +1 -1
  113. package/dist/radar-chart.d.ts +1 -1
  114. package/dist/radar-chart.js +1 -1
  115. package/dist/radio-group.d.ts +2 -2
  116. package/dist/radio-group.js +24 -10
  117. package/dist/review-block.js +1 -1
  118. package/dist/rich-text-editor.d.ts +1 -1
  119. package/dist/rich-text-editor.js +1 -1
  120. package/dist/scatter-chart.d.ts +1 -1
  121. package/dist/scatter-chart.js +1 -1
  122. package/dist/scroll-spy.d.ts +8 -2
  123. package/dist/scroll-spy.js +16 -16
  124. package/dist/search-input.js +1 -1
  125. package/dist/section-jumper.d.ts +31 -0
  126. package/dist/section-jumper.js +276 -0
  127. package/dist/select.d.ts +9 -4
  128. package/dist/select.js +113 -20
  129. package/dist/separator.js +1 -1
  130. package/dist/sheet.d.ts +3 -1
  131. package/dist/sheet.js +10 -6
  132. package/dist/sidebar.d.ts +2 -2
  133. package/dist/sidebar.js +4 -16
  134. package/dist/size-context-BVhHduLi.d.ts +33 -0
  135. package/dist/size-context.d.ts +2 -2
  136. package/dist/size-context.js +30 -1
  137. package/dist/skeleton.js +1 -1
  138. package/dist/slider.d.ts +5 -3
  139. package/dist/slider.js +26 -11
  140. package/dist/sonar.d.ts +1 -1
  141. package/dist/sonar.js +2 -2
  142. package/dist/sparkline.d.ts +1 -1
  143. package/dist/sparkline.js +1 -1
  144. package/dist/stepper.js +1 -1
  145. package/dist/styles.css +1622 -264
  146. package/dist/switch.d.ts +2 -2
  147. package/dist/switch.js +21 -7
  148. package/dist/table-card.js +1 -1
  149. package/dist/table.js +1 -1
  150. package/dist/tabs.d.ts +1 -1
  151. package/dist/tabs.js +1 -1
  152. package/dist/tag.d.ts +1 -1
  153. package/dist/tag.js +1 -1
  154. package/dist/testimonial-block.js +1 -1
  155. package/dist/textarea.d.ts +17 -1
  156. package/dist/textarea.js +24 -10
  157. package/dist/theme-switcher.js +1 -1
  158. package/dist/time-picker.d.ts +5 -4
  159. package/dist/time-picker.js +5 -7
  160. package/dist/toast.js +1 -1
  161. package/dist/tooltip.js +1 -1
  162. package/dist/top-navbar.js +1 -1
  163. package/dist/tree-map.d.ts +1 -1
  164. package/dist/tree-map.js +1 -1
  165. package/dist/utils/cn.d.ts +5 -0
  166. package/dist/utils/cn.js +33 -0
  167. package/dist/utils/format.d.ts +45 -0
  168. package/dist/utils/format.js +70 -0
  169. package/dist/utils/phone.d.ts +98 -0
  170. package/dist/utils/phone.js +93 -0
  171. package/dist/utils/use-intersection.d.ts +9 -0
  172. package/dist/utils/use-intersection.js +29 -0
  173. package/dist/utils/use-is-mobile.d.ts +5 -0
  174. package/dist/utils/use-is-mobile.js +16 -0
  175. package/dist/utils/use-reduced-motion.d.ts +5 -0
  176. package/dist/{use-reduced-motion-BDvOK14x.js → utils/use-reduced-motion.js} +2 -2
  177. package/dist/utils/use-uncontrolled.d.ts +11 -0
  178. package/dist/{use-uncontrolled-CLfM1XbB.js → utils/use-uncontrolled.js} +2 -2
  179. package/dist/video-player-dialog.d.ts +12 -2
  180. package/dist/video-player-dialog.js +50 -9
  181. package/dist/waterfall-chart.d.ts +1 -1
  182. package/dist/waterfall-chart.js +1 -1
  183. package/package.json +13 -1
  184. package/dist/button-DW5OijoR.d.ts +0 -17
  185. package/dist/cn-BI_4DMBf.js +0 -23
  186. package/dist/input-CfoEJ8A6.d.ts +0 -12
  187. package/dist/input-size-context-C-SFx9sx.d.ts +0 -10
  188. package/dist/picker-xSTzeYhc.js +0 -50
  189. package/dist/size-context-BX6kAdVj.d.ts +0 -11
  190. package/dist/textarea-IS_D8pXf.d.ts +0 -11
@@ -0,0 +1,93 @@
1
+ import { getCountries, getCountryCallingCode, parsePhoneNumberFromString } from "libphonenumber-js";
2
+ //#region src/utils/phone.ts
3
+ /**
4
+ * Reads a value into a phone number, or `undefined` if it is not one.
5
+ *
6
+ * Deliberately tolerant about its argument: the exported helpers are written
7
+ * to be handed straight to `zod`'s `refine` or `yup`'s `test`, both of which
8
+ * call a validator with a second argument of their own, and to survive the
9
+ * `null` a database hands back.
10
+ */
11
+ function readPhoneNumber(value, options) {
12
+ if (typeof value !== "string" || value.trim() === "") return;
13
+ const country = typeof options === "object" && options !== null && "country" in options ? options.country : void 0;
14
+ const parsed = parsePhoneNumberFromString(value.trim(), country);
15
+ return parsed?.isValid() ? parsed : void 0;
16
+ }
17
+ /**
18
+ * Whether a value is a phone number that could actually be dialed. Stricter
19
+ * than "has the right number of digits" — it checks the number against the
20
+ * ranges its country has assigned.
21
+ *
22
+ * Written to be passed by reference to a schema:
23
+ *
24
+ * ```ts
25
+ * z.string().refine(validatePhoneNumber, "Enter a valid phone number");
26
+ * yup.string().test("phone", "Enter a valid phone number", validatePhoneNumber);
27
+ * ```
28
+ *
29
+ * Empty and `null` are invalid. Mark the field optional in the schema rather
30
+ * than asking this to have an opinion about whether a missing number is a
31
+ * problem, which is the schema's business and not this function's.
32
+ */
33
+ function validatePhoneNumber(value, options) {
34
+ return readPhoneNumber(value, options) !== void 0;
35
+ }
36
+ /**
37
+ * The E.164 form of a valid number — `+2348012345678`, the one to store — or
38
+ * `""` if the value is not a valid number.
39
+ *
40
+ * ```ts
41
+ * parsePhoneNumber("0801 234 5678", { country: "NG" }); // "+2348012345678"
42
+ * parsePhoneNumber("0801 234"); // ""
43
+ * ```
44
+ */
45
+ function parsePhoneNumber(value, options) {
46
+ return readPhoneNumber(value, options)?.number ?? "";
47
+ }
48
+ /**
49
+ * A valid number written for a reader, or `""` if the value is not a valid
50
+ * number. Defaults to `international`, which is the form that does not depend
51
+ * on knowing where the reader is.
52
+ *
53
+ * ```ts
54
+ * formatPhoneNumber("+2348012345678"); // "+234 801 234 5678"
55
+ * formatPhoneNumber("+2348012345678", { format: "national" }); // "0801 234 5678"
56
+ * ```
57
+ *
58
+ * Blanking an invalid number is the point rather than an oversight: a value
59
+ * that cannot be formatted is a value that should be fixed, and showing a
60
+ * half-formatted one hides that.
61
+ */
62
+ function formatPhoneNumber(value, options) {
63
+ const parsed = readPhoneNumber(value, options);
64
+ if (!parsed) return "";
65
+ switch (options?.format ?? "international") {
66
+ case "national": return parsed.formatNational();
67
+ case "e164": return parsed.number;
68
+ case "rfc3966": return parsed.getURI();
69
+ default: return parsed.formatInternational();
70
+ }
71
+ }
72
+ /** The country a valid number belongs to, or `undefined`. */
73
+ function getPhoneNumberCountry(value, options) {
74
+ return readPhoneNumber(value, options)?.country;
75
+ }
76
+ /**
77
+ * Every country a number can be entered for, sorted by name in `locale`.
78
+ *
79
+ * `PhoneInput` builds its own list from this. It is exported because the
80
+ * country a phone number belongs to tends to be asked for elsewhere in the
81
+ * same form — an address, a nationality — and a second, differently-sorted
82
+ * list of countries in one form is a bug people notice.
83
+ */
84
+ function getPhoneCountries(locale = "en") {
85
+ const regionNames = typeof Intl !== "undefined" && "DisplayNames" in Intl ? new Intl.DisplayNames([locale], { type: "region" }) : void 0;
86
+ return getCountries().map((code) => ({
87
+ code,
88
+ name: regionNames?.of(code) ?? code,
89
+ callingCode: getCountryCallingCode(code)
90
+ })).sort((a, b) => a.name.localeCompare(b.name, locale));
91
+ }
92
+ //#endregion
93
+ export { formatPhoneNumber, getPhoneCountries, getPhoneNumberCountry, parsePhoneNumber, validatePhoneNumber };
@@ -0,0 +1,9 @@
1
+ import { RefCallback } from "react";
2
+ //#region src/utils/use-intersection.d.ts
3
+ interface UseIntersectionReturnValue<T> {
4
+ ref: RefCallback<T | null>;
5
+ entry: IntersectionObserverEntry | null;
6
+ }
7
+ declare function useIntersection<T extends Element>(options?: IntersectionObserverInit): UseIntersectionReturnValue<T>;
8
+ //#endregion
9
+ export { UseIntersectionReturnValue, useIntersection };
@@ -0,0 +1,29 @@
1
+ import { useCallback, useRef, useState } from "react";
2
+ //#region src/utils/use-intersection.ts
3
+ function useIntersection(options) {
4
+ const [entry, setEntry] = useState(null);
5
+ const observer = useRef(null);
6
+ return {
7
+ ref: useCallback((element) => {
8
+ if (observer.current) {
9
+ observer.current.disconnect();
10
+ observer.current = null;
11
+ }
12
+ if (element === null) {
13
+ setEntry(null);
14
+ return;
15
+ }
16
+ if (typeof IntersectionObserver === "undefined") {
17
+ setEntry(null);
18
+ return;
19
+ }
20
+ observer.current = new IntersectionObserver(([_entry]) => {
21
+ setEntry(_entry ?? null);
22
+ }, options);
23
+ observer.current.observe(element);
24
+ }, [options]),
25
+ entry
26
+ };
27
+ }
28
+ //#endregion
29
+ export { useIntersection };
@@ -0,0 +1,5 @@
1
+ //#region src/utils/use-is-mobile.d.ts
2
+ declare const DEFAULT_MOBILE_BREAKPOINT = 1024;
3
+ declare function useIsMobile(breakpoint?: number): boolean;
4
+ //#endregion
5
+ export { DEFAULT_MOBILE_BREAKPOINT, useIsMobile };
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ //#region src/utils/use-is-mobile.ts
3
+ const DEFAULT_MOBILE_BREAKPOINT = 1024;
4
+ function useIsMobile(breakpoint = DEFAULT_MOBILE_BREAKPOINT) {
5
+ const [isMobile, setIsMobile] = React.useState(false);
6
+ React.useEffect(() => {
7
+ const mediaQuery = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
8
+ const update = () => setIsMobile(window.innerWidth < breakpoint);
9
+ update();
10
+ mediaQuery.addEventListener("change", update);
11
+ return () => mediaQuery.removeEventListener("change", update);
12
+ }, [breakpoint]);
13
+ return isMobile;
14
+ }
15
+ //#endregion
16
+ export { DEFAULT_MOBILE_BREAKPOINT, useIsMobile };
@@ -0,0 +1,5 @@
1
+ //#region src/utils/use-reduced-motion.d.ts
2
+ declare function subscribeToReducedMotion(onChange: (reduced: boolean) => void): () => void;
3
+ declare function useReducedMotion(): boolean;
4
+ //#endregion
5
+ export { subscribeToReducedMotion, useReducedMotion };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- //#region src/lib/use-reduced-motion.ts
2
+ //#region src/utils/use-reduced-motion.ts
3
3
  const QUERY = "(prefers-reduced-motion: reduce)";
4
4
  function subscribeToReducedMotion(onChange) {
5
5
  const media = window.matchMedia(QUERY);
@@ -14,4 +14,4 @@ function useReducedMotion() {
14
14
  return reduced;
15
15
  }
16
16
  //#endregion
17
- export { useReducedMotion as t };
17
+ export { subscribeToReducedMotion, useReducedMotion };
@@ -0,0 +1,11 @@
1
+ //#region src/utils/use-uncontrolled.d.ts
2
+ interface UseUncontrolledOptions<T> {
3
+ value?: T;
4
+ defaultValue?: T;
5
+ finalValue?: T;
6
+ onChange?: (value: T, ...payload: unknown[]) => void;
7
+ }
8
+ type UseUncontrolledReturnValue<T> = [T, (value: T, ...payload: unknown[]) => void, boolean];
9
+ declare function useUncontrolled<T>({ value, defaultValue, finalValue, onChange }: UseUncontrolledOptions<T>): UseUncontrolledReturnValue<T>;
10
+ //#endregion
11
+ export { type UseUncontrolledOptions, type UseUncontrolledReturnValue, useUncontrolled };
@@ -1,5 +1,5 @@
1
1
  import { useState } from "react";
2
- //#region src/lib/use-uncontrolled.ts
2
+ //#region src/utils/use-uncontrolled.ts
3
3
  function useUncontrolled({ value, defaultValue, finalValue, onChange = () => {} }) {
4
4
  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue !== void 0 ? defaultValue : finalValue);
5
5
  const handleUncontrolledChange = (nextValue, ...payload) => {
@@ -18,4 +18,4 @@ function useUncontrolled({ value, defaultValue, finalValue, onChange = () => {}
18
18
  ];
19
19
  }
20
20
  //#endregion
21
- export { useUncontrolled as t };
21
+ export { useUncontrolled };
@@ -34,11 +34,21 @@ type VideoPlayerDialogTitleProps = React.ComponentProps<typeof DialogTitle>;
34
34
  declare function VideoPlayerDialogTitle({ className, ...props }: VideoPlayerDialogTitleProps): React.JSX.Element;
35
35
  type VideoPlayerDialogDescriptionProps = React.ComponentProps<typeof DialogDescription>;
36
36
  declare function VideoPlayerDialogDescription({ className, ...props }: VideoPlayerDialogDescriptionProps): React.JSX.Element;
37
- interface VideoPlayerDialogPlaylistIndicatorProps extends React.ComponentProps<"span"> {
37
+ interface VideoPlayerDialogPlaylistIndicatorProps extends Omit<React.ComponentProps<"button">, "type"> {
38
38
  current: number;
39
39
  total: number;
40
40
  }
41
- declare function VideoPlayerDialogPlaylistIndicator({ current, total, className, ...props }: VideoPlayerDialogPlaylistIndicatorProps): React.JSX.Element;
41
+ /**
42
+ * Position in the playlist, and the way down to it. Clicking scrolls the
43
+ * dialog's surface to the playlist — the count is the only sign the playlist
44
+ * exists when the media fills the viewport, so it should be the thing that
45
+ * takes you there.
46
+ *
47
+ * A consumer's `onClick` runs first; calling `preventDefault` on the event
48
+ * keeps the scroll from happening, for a dialog that reveals its playlist some
49
+ * other way.
50
+ */
51
+ declare function VideoPlayerDialogPlaylistIndicator({ current, total, className, onClick, ...props }: VideoPlayerDialogPlaylistIndicatorProps): React.JSX.Element;
42
52
  type VideoPlayerDialogPlaylistProps = React.ComponentProps<"section">;
43
53
  declare function VideoPlayerDialogPlaylist({ className, ...props }: VideoPlayerDialogPlaylistProps): React.JSX.Element;
44
54
  type VideoPlayerDialogPlaylistHeaderProps = React.ComponentProps<"h3">;
@@ -1,7 +1,9 @@
1
1
  "use client";
2
- import { ListVideo } from "./icons.js";
3
- import { t as cn } from "./cn-BI_4DMBf.js";
2
+ import { ChevronDown, ListVideo } from "./icons.js";
3
+ import { cn } from "./utils/cn.js";
4
+ import { useReducedMotion } from "./utils/use-reduced-motion.js";
4
5
  import { Dialog, DialogContent, DialogDescription, DialogTitle, DialogTrigger } from "./dialog.js";
6
+ import { Image } from "./image.js";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  import { cva } from "class-variance-authority";
7
9
  import * as React from "react";
@@ -55,13 +57,14 @@ function VideoPlayerDialogContent({ size = "md", theme = "light", showCloseButto
55
57
  "data-size": size,
56
58
  "data-slot": "video-player-dialog-content",
57
59
  "data-theme": theme,
58
- className: cn("inset-0 m-auto h-fit max-h-none translate-x-0 translate-y-0 gap-0 overflow-visible border-0 bg-transparent p-0 shadow-none sm:w-full [--dialog-padding:0px]", WIDTHS[size], className),
60
+ popupClassName: cn("inset-0 m-auto h-fit max-h-none w-[calc(100%-2rem)] translate-x-0 translate-y-0 gap-0 overflow-visible border-0 bg-transparent p-0 shadow-none sm:w-full [--dialog-padding:0px]", WIDTHS[size]),
61
+ className: cn("max-h-none gap-0 border-0 bg-transparent p-0 shadow-none", className),
59
62
  ...props,
60
63
  children: /* @__PURE__ */ jsx(VideoPlayerDialogContext.Provider, {
61
64
  value: context,
62
65
  children: /* @__PURE__ */ jsx("div", {
63
66
  "data-slot": "video-player-dialog-surface",
64
- className: cn("max-h-[calc(100dvh-4rem)] overflow-y-auto overscroll-contain", videoPlayerDialogSurfaceVariants({
67
+ className: cn("max-h-[calc(100dvh-6rem)] overflow-y-auto overscroll-contain", videoPlayerDialogSurfaceVariants({
65
68
  size,
66
69
  theme
67
70
  }), surfaceClassName),
@@ -105,10 +108,42 @@ function VideoPlayerDialogDescription({ className, ...props }) {
105
108
  ...props
106
109
  });
107
110
  }
108
- function VideoPlayerDialogPlaylistIndicator({ current, total, className, ...props }) {
109
- return /* @__PURE__ */ jsxs("span", {
111
+ /**
112
+ * Brings the playlist into view from the indicator.
113
+ *
114
+ * The playlist is found through the DOM rather than a ref because the two
115
+ * parts sit in unrelated branches of the tree — the indicator is inside the
116
+ * media's controls, the playlist is a sibling of the media — and the search is
117
+ * bounded by the dialog surface, so a second dialog on the page can't be the
118
+ * one that scrolls.
119
+ */
120
+ function scrollToPlaylist(from, smooth) {
121
+ (from.closest("[data-slot=video-player-dialog-surface]") ?? document).querySelector("[data-slot=video-player-dialog-playlist]")?.scrollIntoView({
122
+ behavior: smooth ? "smooth" : "auto",
123
+ block: "start"
124
+ });
125
+ }
126
+ /**
127
+ * Position in the playlist, and the way down to it. Clicking scrolls the
128
+ * dialog's surface to the playlist — the count is the only sign the playlist
129
+ * exists when the media fills the viewport, so it should be the thing that
130
+ * takes you there.
131
+ *
132
+ * A consumer's `onClick` runs first; calling `preventDefault` on the event
133
+ * keeps the scroll from happening, for a dialog that reveals its playlist some
134
+ * other way.
135
+ */
136
+ function VideoPlayerDialogPlaylistIndicator({ current, total, className, onClick, ...props }) {
137
+ const reducedMotion = useReducedMotion();
138
+ return /* @__PURE__ */ jsxs("button", {
139
+ type: "button",
110
140
  "data-slot": "video-player-dialog-playlist-indicator",
111
- className: cn("pointer-events-none absolute top-3 right-3 z-20 inline-flex h-9 items-center gap-2 rounded-full bg-black/40 px-3 text-gdt-xs font-bold whitespace-nowrap text-white shadow-[0_0_4px_rgb(0_0_0/0.1)] backdrop-blur-[15px]", className),
141
+ className: cn("absolute top-3 right-3 z-20 inline-flex h-9 cursor-pointer items-center gap-2 rounded-full bg-black/40 px-3 text-gdt-xs font-bold whitespace-nowrap text-white shadow-[0_0_4px_rgb(0_0_0/0.1)] backdrop-blur-[15px] transition-[background-color,transform] duration-(--duration-motion-press) ease-gdt-out outline-none hover:bg-black/60 focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-focus)] active:scale-[0.97] motion-reduce:active:scale-100", className),
142
+ onClick: (event) => {
143
+ onClick?.(event);
144
+ if (event.defaultPrevented) return;
145
+ scrollToPlaylist(event.currentTarget, !reducedMotion);
146
+ },
112
147
  ...props,
113
148
  children: [
114
149
  /* @__PURE__ */ jsx(ListVideo, {
@@ -123,13 +158,18 @@ function VideoPlayerDialogPlaylistIndicator({ current, total, className, ...prop
123
158
  total
124
159
  ]
125
160
  }),
161
+ /* @__PURE__ */ jsx(ChevronDown, {
162
+ "aria-hidden": "true",
163
+ className: "size-4"
164
+ }),
126
165
  /* @__PURE__ */ jsxs("span", {
127
166
  className: "sr-only",
128
167
  children: [
129
168
  "Video ",
130
169
  current,
131
170
  " of ",
132
- total
171
+ total,
172
+ ". Go to the playlist."
133
173
  ]
134
174
  })
135
175
  ]
@@ -168,7 +208,8 @@ function VideoPlayerDialogPlaylistItem({ active = false, index, poster, title, d
168
208
  className: "w-5 shrink-0 text-center text-gdt-xs font-semibold text-fg-caption-placeholder",
169
209
  children: index
170
210
  }) : null,
171
- poster ? /* @__PURE__ */ jsx("img", {
211
+ poster ? /* @__PURE__ */ jsx(Image, {
212
+ slot: "video-player-dialog-playlist-poster",
172
213
  src: poster,
173
214
  alt: "",
174
215
  className: "aspect-video w-20 shrink-0 rounded-md object-cover"
@@ -1,4 +1,4 @@
1
- import { t as ComponentSize } from "./size-context-BX6kAdVj.js";
1
+ import { t as ComponentSize } from "./size-context-BVhHduLi.js";
2
2
  import { ChartCard, ChartValueType } from "./chart.js";
3
3
  import * as React from "react";
4
4
  //#region src/waterfall-chart.d.ts
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-BI_4DMBf.js";
2
+ import { cn } from "./utils/cn.js";
3
3
  import { SizeProvider, useComponentSize } from "./size-context.js";
4
4
  import { ChartCard, ChartContainer, ChartDescription, ChartHeader, ChartTitle, ChartTooltip, ChartTooltipContent } from "./chart.js";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@giddaa-housing/ui",
3
- "version": "3.4.0",
3
+ "version": "3.6.0",
4
4
  "description": "Giddaa reusable UI component library.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -17,6 +17,10 @@
17
17
  "types": "./dist/logo.d.ts",
18
18
  "import": "./dist/logo.js"
19
19
  },
20
+ "./utils/*": {
21
+ "types": "./dist/utils/*.d.ts",
22
+ "import": "./dist/utils/*.js"
23
+ },
20
24
  "./accordion": {
21
25
  "types": "./dist/accordion.d.ts",
22
26
  "import": "./dist/accordion.js"
@@ -169,6 +173,10 @@
169
173
  "types": "./dist/icons.d.ts",
170
174
  "import": "./dist/icons.js"
171
175
  },
176
+ "./image": {
177
+ "types": "./dist/image.d.ts",
178
+ "import": "./dist/image.js"
179
+ },
172
180
  "./infotip": {
173
181
  "types": "./dist/infotip.d.ts",
174
182
  "import": "./dist/infotip.js"
@@ -321,6 +329,10 @@
321
329
  "types": "./dist/scroll-spy.d.ts",
322
330
  "import": "./dist/scroll-spy.js"
323
331
  },
332
+ "./section-jumper": {
333
+ "types": "./dist/section-jumper.d.ts",
334
+ "import": "./dist/section-jumper.js"
335
+ },
324
336
  "./search-input": {
325
337
  "types": "./dist/search-input.d.ts",
326
338
  "import": "./dist/search-input.js"
@@ -1,17 +0,0 @@
1
- import { useRender } from "@base-ui/react/use-render";
2
- import { VariantProps } from "class-variance-authority";
3
- import { Button } from "@base-ui/react/button";
4
- //#region src/button.d.ts
5
- declare const buttonVariants: (props?: ({
6
- variant?: "back" | "danger" | "ghost" | "glass-overlay" | "link-brand" | "link-neutral" | "primary" | "primary-outline" | "secondary" | "secondary-outline" | "tertiary" | "tertiary-outline" | "whatsapp" | null | undefined;
7
- size?: "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "lg" | "md" | "sm" | "xl" | null | undefined;
8
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
- declare function Button$1({ className, variant, size, isLoading, children, disabled, ...props }: Button.Props & VariantProps<typeof buttonVariants> & {
10
- isLoading?: boolean;
11
- }): import("react").JSX.Element;
12
- type ButtonLinkProps = useRender.ComponentProps<"a"> & VariantProps<typeof buttonVariants> & {
13
- disabled?: boolean;
14
- };
15
- declare function ButtonLink({ className, render, variant, size, disabled, onClick, children, ...props }: ButtonLinkProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
16
- //#endregion
17
- export { ButtonLink as n, buttonVariants as r, Button$1 as t };
@@ -1,23 +0,0 @@
1
- import { clsx } from "clsx";
2
- import { extendTailwindMerge } from "tailwind-merge";
3
- //#region src/lib/cn.ts
4
- const twMerge = extendTailwindMerge({ extend: { classGroups: { "font-size": [{ text: [
5
- "gdt-display",
6
- "gdt-h1",
7
- "gdt-h2",
8
- "gdt-h3",
9
- "gdt-h4",
10
- "gdt-h5",
11
- "gdt-xl",
12
- "gdt-lg",
13
- "gdt-md",
14
- "gdt-sm",
15
- "gdt-xs",
16
- "gdt-subtext",
17
- "gdt-capitalized"
18
- ] }] } } });
19
- function cn(...inputs) {
20
- return twMerge(clsx(inputs));
21
- }
22
- //#endregion
23
- export { cn as t };
@@ -1,12 +0,0 @@
1
- import { t as InputComponentSize } from "./input-size-context-C-SFx9sx.js";
2
- import { VariantProps } from "class-variance-authority";
3
- import * as React from "react";
4
- //#region src/input.d.ts
5
- declare const inputVariants: (props?: ({
6
- size?: "lg" | "md" | "sm" | "xl" | null | undefined;
7
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
- type InputProps = Omit<React.ComponentProps<"input">, "size"> & VariantProps<typeof inputVariants>;
9
- type InputSize = InputComponentSize;
10
- declare function Input({ className, size, type, ...props }: InputProps): React.JSX.Element;
11
- //#endregion
12
- export { InputSize as n, inputVariants as r, Input as t };
@@ -1,10 +0,0 @@
1
- import { ReactNode } from "react";
2
- //#region src/input-size-context.d.ts
3
- type InputComponentSize = "sm" | "md" | "lg" | "xl";
4
- declare function InputSizeProvider({ children, size }: {
5
- children: ReactNode;
6
- size?: InputComponentSize | null;
7
- }): import("react").JSX.Element;
8
- declare function useInputComponentSize(size?: InputComponentSize | null, fallback?: InputComponentSize): InputComponentSize;
9
- //#endregion
10
- export { InputSizeProvider as n, useInputComponentSize as r, InputComponentSize as t };
@@ -1,50 +0,0 @@
1
- import { t as cn } from "./cn-BI_4DMBf.js";
2
- import { Button } from "./button.js";
3
- import { useInputComponentSize } from "./input-size-context.js";
4
- import { PopoverTrigger } from "./popover.js";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- import { cva } from "class-variance-authority";
7
- //#region src/lib/picker.tsx
8
- const PICKER_COLLISION_AVOIDANCE = {
9
- side: "flip",
10
- align: "shift",
11
- fallbackAxisSide: "none"
12
- };
13
- const pickerTriggerVariants = cva("flex w-full items-center justify-between rounded-full border transition-[border-color,box-shadow] outline-none", {
14
- variants: { size: {
15
- sm: "h-8 px-3 text-gdt-xs [&_svg]:size-3.5",
16
- md: "h-10 px-3.5 text-gdt-sm [&_svg]:size-4",
17
- lg: "h-12 px-4 text-gdt-md [&_svg]:size-4.5",
18
- xl: "h-14 px-4.5 text-gdt-lg [&_svg]:size-5"
19
- } },
20
- defaultVariants: { size: "md" }
21
- });
22
- function PickerTrigger({ icon: Icon, displayValue, placeholder, disabled, open, size, className }) {
23
- const resolvedSize = useInputComponentSize(size);
24
- return /* @__PURE__ */ jsxs(PopoverTrigger, {
25
- disabled,
26
- "data-size": resolvedSize,
27
- className: cn(pickerTriggerVariants({ size: resolvedSize }), disabled ? "cursor-not-allowed border-line-subtle bg-surface text-fg-caption-placeholder" : open ? "border-line-focus bg-canvas text-fg-primary inset-ring-1 inset-ring-line-focus" : "border-line bg-canvas text-fg-primary hover:border-line-strong", className),
28
- children: [/* @__PURE__ */ jsx("span", {
29
- className: cn("min-w-0 truncate", !displayValue && "text-fg-caption-placeholder"),
30
- children: displayValue || placeholder
31
- }), /* @__PURE__ */ jsx(Icon, { className: cn("ml-2 shrink-0", disabled ? "text-fg-caption-placeholder" : "text-fg-secondary") })]
32
- });
33
- }
34
- function PickerFooter({ secondaryLabel, onSecondary, onApply }) {
35
- return /* @__PURE__ */ jsxs("div", {
36
- className: "flex w-full items-center justify-between border-t border-line-subtle px-4 py-3",
37
- children: [/* @__PURE__ */ jsx(Button, {
38
- variant: "tertiary-outline",
39
- size: "sm",
40
- onClick: onSecondary,
41
- children: secondaryLabel
42
- }), /* @__PURE__ */ jsx(Button, {
43
- size: "sm",
44
- onClick: onApply,
45
- children: "Apply"
46
- })]
47
- });
48
- }
49
- //#endregion
50
- export { PickerFooter as n, PickerTrigger as r, PICKER_COLLISION_AVOIDANCE as t };
@@ -1,11 +0,0 @@
1
- import { ReactNode } from "react";
2
- //#region src/size-context.d.ts
3
- type ComponentSize = "sm" | "md" | "lg";
4
- declare function useInheritedComponentSize(): ComponentSize | undefined;
5
- declare function SizeProvider({ children, size }: {
6
- children: ReactNode;
7
- size?: ComponentSize | null;
8
- }): import("react").JSX.Element;
9
- declare function useComponentSize(size?: ComponentSize | null, fallback?: ComponentSize): ComponentSize;
10
- //#endregion
11
- export { useInheritedComponentSize as i, SizeProvider as n, useComponentSize as r, ComponentSize as t };
@@ -1,11 +0,0 @@
1
- import { VariantProps } from "class-variance-authority";
2
- import * as React from "react";
3
- //#region src/textarea.d.ts
4
- declare const textareaVariants: (props?: ({
5
- size?: "lg" | "md" | "sm" | null | undefined;
6
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
- type TextareaProps = Omit<React.ComponentProps<"textarea">, "size"> & VariantProps<typeof textareaVariants>;
8
- type TextareaSize = NonNullable<VariantProps<typeof textareaVariants>["size"]>;
9
- declare function Textarea({ className, size, ...props }: TextareaProps): React.JSX.Element;
10
- //#endregion
11
- export { TextareaSize as n, textareaVariants as r, Textarea as t };