@giddaa-housing/ui 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/generated/shared.css +1 -1
- package/dist/accordion.js +1 -1
- package/dist/activity-timeline.js +1 -1
- package/dist/alert.js +1 -1
- package/dist/auth-layout.js +1 -1
- package/dist/avatar.js +1 -1
- package/dist/badge.js +1 -1
- package/dist/bar-chart.js +1 -1
- package/dist/breadcrumb.js +1 -1
- package/dist/bullet-chart.js +1 -1
- package/dist/button-group.js +1 -1
- package/dist/button.js +1 -1
- package/dist/calendar.js +2 -2
- package/dist/call-card.js +1 -1
- package/dist/card.js +1 -1
- package/dist/carousel.js +2 -2
- package/dist/chart.js +1 -1
- package/dist/chat.js +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/collapsible.js +1 -1
- package/dist/combobox-B7cKFJ9V.js +398 -0
- package/dist/combobox.d.ts +2 -2
- package/dist/combobox.js +1 -308
- package/dist/cta.js +1 -1
- package/dist/currency-selector.js +2 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/data-table.js +1 -1
- package/dist/date-picker.d.ts +4 -3
- package/dist/date-picker.js +7 -17
- package/dist/details-card.js +1 -1
- package/dist/dialog.js +1 -1
- package/dist/dropdown-menu.js +1 -1
- package/dist/dropzone.js +1 -1
- package/dist/editorial-card.js +2 -4
- package/dist/empty-state.js +1 -1
- package/dist/field.js +1 -1
- package/dist/file-upload.js +1 -1
- package/dist/filter.js +1 -1
- package/dist/footer.js +1 -1
- package/dist/funnel-chart.js +1 -1
- package/dist/gallery-indicator.js +1 -1
- package/dist/icons-C9JXR5Xv.d.ts +111 -0
- package/dist/icons.d.ts +2 -93
- package/dist/icons.js +37 -1
- package/dist/image.d.ts +59 -0
- package/dist/image.js +53 -0
- package/dist/infinite-scroll.js +3 -29
- package/dist/infotip.js +1 -1
- package/dist/input-group.js +1 -1
- package/dist/input-otp.js +1 -1
- package/dist/input.js +1 -1
- package/dist/item.js +1 -1
- package/dist/kpi-card.js +1 -1
- package/dist/label.js +1 -1
- package/dist/line-chart.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/map-indicator.js +1 -1
- package/dist/match.js +1 -1
- package/dist/media-gallery-hero.js +6 -3
- package/dist/media-player.js +5 -13
- package/dist/message.js +2 -12
- package/dist/mobile-sidebar.js +1 -1
- package/dist/multi-step-form.js +2 -2
- package/dist/number-input.js +1 -1
- package/dist/page-header.js +1 -1
- package/dist/pagination.js +1 -1
- package/dist/password-input.js +1 -1
- package/dist/phone-input.js +11 -17
- package/dist/photo-gallery.js +6 -3
- package/dist/picker-CsnHtbe4.d.ts +14 -0
- package/dist/{picker-xSTzeYhc.js → picker-DmIiQKLJ.js} +2 -7
- package/dist/pie-chart.js +1 -1
- package/dist/popover-DSlPeH7x.d.ts +20 -0
- package/dist/popover.d.ts +1 -19
- package/dist/popover.js +1 -1
- package/dist/price-tag.d.ts +1 -1
- package/dist/price-tag.js +50 -22
- package/dist/progress.js +1 -1
- package/dist/property-listing-card.d.ts +63 -1
- package/dist/property-listing-card.js +97 -28
- package/dist/purchase-option-card.js +1 -1
- package/dist/radar-chart.js +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/review-block.js +1 -1
- package/dist/rich-text-editor.js +1 -1
- package/dist/scatter-chart.js +1 -1
- package/dist/scroll-spy.js +3 -3
- package/dist/search-input.js +1 -1
- package/dist/select.js +1 -1
- package/dist/separator.js +1 -1
- package/dist/sheet.js +1 -1
- package/dist/sidebar.js +3 -16
- package/dist/skeleton.js +1 -1
- package/dist/slider.js +1 -1
- package/dist/sonar.js +1 -1
- package/dist/sparkline.js +1 -1
- package/dist/stepper.js +1 -1
- package/dist/styles.css +42 -2
- package/dist/switch.js +1 -1
- package/dist/table-card.js +1 -1
- package/dist/table.js +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tag.js +1 -1
- package/dist/testimonial-block.js +1 -1
- package/dist/textarea.js +1 -1
- package/dist/theme-switcher.js +1 -1
- package/dist/time-picker.d.ts +3 -2
- package/dist/time-picker.js +5 -7
- package/dist/toast.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/top-navbar.js +1 -1
- package/dist/tree-map.js +1 -1
- package/dist/utils/cn.d.ts +5 -0
- package/dist/utils/cn.js +33 -0
- package/dist/utils/format.d.ts +45 -0
- package/dist/utils/format.js +70 -0
- package/dist/utils/phone.d.ts +98 -0
- package/dist/utils/phone.js +93 -0
- package/dist/utils/use-intersection.d.ts +9 -0
- package/dist/utils/use-intersection.js +29 -0
- package/dist/utils/use-is-mobile.d.ts +5 -0
- package/dist/utils/use-is-mobile.js +16 -0
- package/dist/utils/use-reduced-motion.d.ts +5 -0
- package/dist/{use-reduced-motion-BDvOK14x.js → utils/use-reduced-motion.js} +2 -2
- package/dist/utils/use-uncontrolled.d.ts +11 -0
- package/dist/{use-uncontrolled-CLfM1XbB.js → utils/use-uncontrolled.js} +2 -2
- package/dist/video-player-dialog.d.ts +12 -2
- package/dist/video-player-dialog.js +47 -7
- package/dist/waterfall-chart.js +1 -1
- package/package.json +9 -1
- package/dist/cn-BI_4DMBf.js +0 -23
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { CountryCode } from "libphonenumber-js";
|
|
2
|
+
//#region src/utils/phone.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Phone number helpers, shared by `PhoneInput` and by the forms around it.
|
|
5
|
+
*
|
|
6
|
+
* These are here because a phone number is validated in more places than it is
|
|
7
|
+
* typed — a zod schema, a server action, a CSV import, a table cell — and every
|
|
8
|
+
* one of those was otherwise reaching for its own regex. They carry no React
|
|
9
|
+
* and no styling, so a server-only module can import them.
|
|
10
|
+
*
|
|
11
|
+
* One rule runs through all of them: **invalid in, empty out**. Anything that
|
|
12
|
+
* is not a real, dialable number formats and parses to `""` rather than to
|
|
13
|
+
* `null`, to `undefined`, or to a half-cleaned version of what you passed. A
|
|
14
|
+
* caller then has one thing to check instead of three.
|
|
15
|
+
*/
|
|
16
|
+
/** How a number should read once it is formatted. */
|
|
17
|
+
type PhoneNumberFormat =
|
|
18
|
+
/** `+234 801 234 5678` — the one to show when the country matters. */
|
|
19
|
+
"international" |
|
|
20
|
+
/** `0801 234 5678` — the one to show to someone in that country. */
|
|
21
|
+
"national" |
|
|
22
|
+
/** `+2348012345678` — the one to store. */
|
|
23
|
+
"e164" |
|
|
24
|
+
/** `tel:+234-801-234-5678` — the one to put in an `href`. */
|
|
25
|
+
"rfc3966";
|
|
26
|
+
interface PhoneNumberOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The country to read a number against when it does not carry its own
|
|
29
|
+
* calling code. `"08012345678"` is a valid Nigerian number and nothing at
|
|
30
|
+
* all without this; `"+2348012345678"` needs it either way.
|
|
31
|
+
*/
|
|
32
|
+
country?: CountryCode;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether a value is a phone number that could actually be dialed. Stricter
|
|
36
|
+
* than "has the right number of digits" — it checks the number against the
|
|
37
|
+
* ranges its country has assigned.
|
|
38
|
+
*
|
|
39
|
+
* Written to be passed by reference to a schema:
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* z.string().refine(validatePhoneNumber, "Enter a valid phone number");
|
|
43
|
+
* yup.string().test("phone", "Enter a valid phone number", validatePhoneNumber);
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* Empty and `null` are invalid. Mark the field optional in the schema rather
|
|
47
|
+
* than asking this to have an opinion about whether a missing number is a
|
|
48
|
+
* problem, which is the schema's business and not this function's.
|
|
49
|
+
*/
|
|
50
|
+
declare function validatePhoneNumber(value: unknown, options?: PhoneNumberOptions): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* The E.164 form of a valid number — `+2348012345678`, the one to store — or
|
|
53
|
+
* `""` if the value is not a valid number.
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* parsePhoneNumber("0801 234 5678", { country: "NG" }); // "+2348012345678"
|
|
57
|
+
* parsePhoneNumber("0801 234"); // ""
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function parsePhoneNumber(value: unknown, options?: PhoneNumberOptions): string;
|
|
61
|
+
/**
|
|
62
|
+
* A valid number written for a reader, or `""` if the value is not a valid
|
|
63
|
+
* number. Defaults to `international`, which is the form that does not depend
|
|
64
|
+
* on knowing where the reader is.
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* formatPhoneNumber("+2348012345678"); // "+234 801 234 5678"
|
|
68
|
+
* formatPhoneNumber("+2348012345678", { format: "national" }); // "0801 234 5678"
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Blanking an invalid number is the point rather than an oversight: a value
|
|
72
|
+
* that cannot be formatted is a value that should be fixed, and showing a
|
|
73
|
+
* half-formatted one hides that.
|
|
74
|
+
*/
|
|
75
|
+
declare function formatPhoneNumber(value: unknown, options?: PhoneNumberOptions & {
|
|
76
|
+
format?: PhoneNumberFormat;
|
|
77
|
+
}): string;
|
|
78
|
+
/** The country a valid number belongs to, or `undefined`. */
|
|
79
|
+
declare function getPhoneNumberCountry(value: unknown, options?: PhoneNumberOptions): CountryCode | undefined;
|
|
80
|
+
interface PhoneCountry {
|
|
81
|
+
/** ISO 3166-1 alpha-2, e.g. `"NG"`. */
|
|
82
|
+
code: CountryCode;
|
|
83
|
+
/** Localised display name, falling back to the code where `Intl` is absent. */
|
|
84
|
+
name: string;
|
|
85
|
+
/** Calling code without the `+`, e.g. `"234"`. */
|
|
86
|
+
callingCode: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Every country a number can be entered for, sorted by name in `locale`.
|
|
90
|
+
*
|
|
91
|
+
* `PhoneInput` builds its own list from this. It is exported because the
|
|
92
|
+
* country a phone number belongs to tends to be asked for elsewhere in the
|
|
93
|
+
* same form — an address, a nationality — and a second, differently-sorted
|
|
94
|
+
* list of countries in one form is a bug people notice.
|
|
95
|
+
*/
|
|
96
|
+
declare function getPhoneCountries(locale?: string): PhoneCountry[];
|
|
97
|
+
//#endregion
|
|
98
|
+
export { type CountryCode, type PhoneCountry, type PhoneNumberFormat, type PhoneNumberOptions, formatPhoneNumber, getPhoneCountries, getPhoneNumberCountry, parsePhoneNumber, validatePhoneNumber };
|
|
@@ -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,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 };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
//#region src/
|
|
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
|
|
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/
|
|
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
|
|
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<"
|
|
37
|
+
interface VideoPlayerDialogPlaylistIndicatorProps extends Omit<React.ComponentProps<"button">, "type"> {
|
|
38
38
|
current: number;
|
|
39
39
|
total: number;
|
|
40
40
|
}
|
|
41
|
-
|
|
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 {
|
|
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";
|
|
@@ -105,10 +107,42 @@ function VideoPlayerDialogDescription({ className, ...props }) {
|
|
|
105
107
|
...props
|
|
106
108
|
});
|
|
107
109
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Brings the playlist into view from the indicator.
|
|
112
|
+
*
|
|
113
|
+
* The playlist is found through the DOM rather than a ref because the two
|
|
114
|
+
* parts sit in unrelated branches of the tree — the indicator is inside the
|
|
115
|
+
* media's controls, the playlist is a sibling of the media — and the search is
|
|
116
|
+
* bounded by the dialog surface, so a second dialog on the page can't be the
|
|
117
|
+
* one that scrolls.
|
|
118
|
+
*/
|
|
119
|
+
function scrollToPlaylist(from, smooth) {
|
|
120
|
+
(from.closest("[data-slot=video-player-dialog-surface]") ?? document).querySelector("[data-slot=video-player-dialog-playlist]")?.scrollIntoView({
|
|
121
|
+
behavior: smooth ? "smooth" : "auto",
|
|
122
|
+
block: "start"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Position in the playlist, and the way down to it. Clicking scrolls the
|
|
127
|
+
* dialog's surface to the playlist — the count is the only sign the playlist
|
|
128
|
+
* exists when the media fills the viewport, so it should be the thing that
|
|
129
|
+
* takes you there.
|
|
130
|
+
*
|
|
131
|
+
* A consumer's `onClick` runs first; calling `preventDefault` on the event
|
|
132
|
+
* keeps the scroll from happening, for a dialog that reveals its playlist some
|
|
133
|
+
* other way.
|
|
134
|
+
*/
|
|
135
|
+
function VideoPlayerDialogPlaylistIndicator({ current, total, className, onClick, ...props }) {
|
|
136
|
+
const reducedMotion = useReducedMotion();
|
|
137
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
138
|
+
type: "button",
|
|
110
139
|
"data-slot": "video-player-dialog-playlist-indicator",
|
|
111
|
-
className: cn("
|
|
140
|
+
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),
|
|
141
|
+
onClick: (event) => {
|
|
142
|
+
onClick?.(event);
|
|
143
|
+
if (event.defaultPrevented) return;
|
|
144
|
+
scrollToPlaylist(event.currentTarget, !reducedMotion);
|
|
145
|
+
},
|
|
112
146
|
...props,
|
|
113
147
|
children: [
|
|
114
148
|
/* @__PURE__ */ jsx(ListVideo, {
|
|
@@ -123,13 +157,18 @@ function VideoPlayerDialogPlaylistIndicator({ current, total, className, ...prop
|
|
|
123
157
|
total
|
|
124
158
|
]
|
|
125
159
|
}),
|
|
160
|
+
/* @__PURE__ */ jsx(ChevronDown, {
|
|
161
|
+
"aria-hidden": "true",
|
|
162
|
+
className: "size-4"
|
|
163
|
+
}),
|
|
126
164
|
/* @__PURE__ */ jsxs("span", {
|
|
127
165
|
className: "sr-only",
|
|
128
166
|
children: [
|
|
129
167
|
"Video ",
|
|
130
168
|
current,
|
|
131
169
|
" of ",
|
|
132
|
-
total
|
|
170
|
+
total,
|
|
171
|
+
". Go to the playlist."
|
|
133
172
|
]
|
|
134
173
|
})
|
|
135
174
|
]
|
|
@@ -168,7 +207,8 @@ function VideoPlayerDialogPlaylistItem({ active = false, index, poster, title, d
|
|
|
168
207
|
className: "w-5 shrink-0 text-center text-gdt-xs font-semibold text-fg-caption-placeholder",
|
|
169
208
|
children: index
|
|
170
209
|
}) : null,
|
|
171
|
-
poster ? /* @__PURE__ */ jsx(
|
|
210
|
+
poster ? /* @__PURE__ */ jsx(Image, {
|
|
211
|
+
slot: "video-player-dialog-playlist-poster",
|
|
172
212
|
src: poster,
|
|
173
213
|
alt: "",
|
|
174
214
|
className: "aspect-video w-20 shrink-0 rounded-md object-cover"
|
package/dist/waterfall-chart.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
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.
|
|
3
|
+
"version": "3.5.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"
|
package/dist/cn-BI_4DMBf.js
DELETED
|
@@ -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 };
|