@liveblocks/react-ui 3.5.3 → 3.5.4

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 (40) hide show
  1. package/dist/_private/index.d.cts +0 -4
  2. package/dist/_private/index.d.ts +0 -4
  3. package/dist/components/Thread.cjs.map +1 -1
  4. package/dist/components/Thread.js.map +1 -1
  5. package/dist/components/internal/AiChatAssistantMessage.cjs +9 -29
  6. package/dist/components/internal/AiChatAssistantMessage.cjs.map +1 -1
  7. package/dist/components/internal/AiChatAssistantMessage.js +10 -30
  8. package/dist/components/internal/AiChatAssistantMessage.js.map +1 -1
  9. package/dist/index.d.cts +3 -4
  10. package/dist/index.d.ts +3 -4
  11. package/dist/overrides.cjs +1 -42
  12. package/dist/overrides.cjs.map +1 -1
  13. package/dist/overrides.js +1 -42
  14. package/dist/overrides.js.map +1 -1
  15. package/dist/primitives/AiMessage/index.cjs +1 -7
  16. package/dist/primitives/AiMessage/index.cjs.map +1 -1
  17. package/dist/primitives/AiMessage/index.js +1 -7
  18. package/dist/primitives/AiMessage/index.js.map +1 -1
  19. package/dist/primitives/AiMessage/tool-invocation.cjs.map +1 -1
  20. package/dist/primitives/AiMessage/tool-invocation.js.map +1 -1
  21. package/dist/primitives/Timestamp.cjs +3 -4
  22. package/dist/primitives/Timestamp.cjs.map +1 -1
  23. package/dist/primitives/Timestamp.js +4 -4
  24. package/dist/primitives/Timestamp.js.map +1 -1
  25. package/dist/primitives/index.cjs +0 -2
  26. package/dist/primitives/index.cjs.map +1 -1
  27. package/dist/primitives/index.d.cts +4 -59
  28. package/dist/primitives/index.d.ts +4 -59
  29. package/dist/primitives/index.js +0 -1
  30. package/dist/primitives/index.js.map +1 -1
  31. package/dist/version.cjs +1 -1
  32. package/dist/version.js +1 -1
  33. package/package.json +4 -4
  34. package/src/styles/index.css +2 -20
  35. package/styles.css +1 -1
  36. package/styles.css.map +1 -1
  37. package/dist/primitives/Duration.cjs +0 -195
  38. package/dist/primitives/Duration.cjs.map +0 -1
  39. package/dist/primitives/Duration.js +0 -192
  40. package/dist/primitives/Duration.js.map +0 -1
@@ -1,195 +0,0 @@
1
- "use client";
2
- 'use strict';
3
-
4
- var jsxRuntime = require('react/jsx-runtime');
5
- var reactSlot = require('@radix-ui/react-slot');
6
- var react = require('react');
7
- var intl = require('../utils/intl.cjs');
8
- var useInterval = require('../utils/use-interval.cjs');
9
- var useRerender = require('../utils/use-rerender.cjs');
10
-
11
-
12
- const RENDER_INTERVAL = 0.5 * 1e3;
13
- const DURATION_NAME = "Duration";
14
- function getDurationParts(duration) {
15
- let remaining = Math.max(duration, 0);
16
- const milliseconds = remaining % 1e3;
17
- remaining = Math.floor(remaining / 1e3);
18
- const seconds = remaining % 60;
19
- remaining = Math.floor(remaining / 60);
20
- const minutes = remaining % 60;
21
- remaining = Math.floor(remaining / 60);
22
- const hours = remaining % 24;
23
- remaining = Math.floor(remaining / 24);
24
- const days = remaining % 7;
25
- const weeks = Math.floor(remaining / 7);
26
- return { weeks, days, hours, minutes, seconds, milliseconds };
27
- }
28
- const durationPartsToNumberFormatOptions = {
29
- weeks: "week",
30
- days: "day",
31
- hours: "hour",
32
- minutes: "minute",
33
- seconds: "second",
34
- milliseconds: "millisecond"
35
- };
36
- function formatShortDuration(duration, locale) {
37
- let resolvedLocale;
38
- if (locale) {
39
- resolvedLocale = locale;
40
- } else {
41
- const formatter = intl.numberFormat();
42
- resolvedLocale = formatter.resolvedOptions().locale;
43
- }
44
- const parts = getDurationParts(duration);
45
- const formattedParts = [];
46
- for (const [unit, value] of Object.entries(parts)) {
47
- if (value === 0 || unit === "milliseconds") {
48
- continue;
49
- }
50
- const formatter = intl.numberFormat(resolvedLocale, {
51
- style: "unit",
52
- unit: durationPartsToNumberFormatOptions[unit],
53
- unitDisplay: "narrow"
54
- });
55
- formattedParts.push(formatter.format(value));
56
- }
57
- if (!formattedParts.length) {
58
- formattedParts.push(
59
- intl.numberFormat(resolvedLocale, {
60
- style: "unit",
61
- unit: "second",
62
- unitDisplay: "narrow"
63
- }).format(0)
64
- );
65
- }
66
- return formattedParts.join(" ");
67
- }
68
- function formatVerboseDuration(duration, locale) {
69
- let resolvedLocale;
70
- if (locale) {
71
- resolvedLocale = locale;
72
- } else {
73
- const formatter = intl.numberFormat();
74
- resolvedLocale = formatter.resolvedOptions().locale;
75
- }
76
- const parts = getDurationParts(duration);
77
- const formattedParts = [];
78
- for (const [unit, value] of Object.entries(parts)) {
79
- if (value === 0 || unit === "milliseconds") {
80
- continue;
81
- }
82
- const formatter = intl.numberFormat(resolvedLocale, {
83
- style: "unit",
84
- unit: durationPartsToNumberFormatOptions[unit],
85
- unitDisplay: "long"
86
- });
87
- formattedParts.push(formatter.format(value));
88
- }
89
- if (!formattedParts.length) {
90
- formattedParts.push(
91
- intl.numberFormat(resolvedLocale, {
92
- style: "unit",
93
- unit: "second",
94
- unitDisplay: "long"
95
- }).format(0)
96
- );
97
- }
98
- return formattedParts.join(" ");
99
- }
100
- function formatIso8601Duration(duration) {
101
- const normalizedDuration = Math.max(duration, 0);
102
- if (normalizedDuration === 0) {
103
- return "PT0S";
104
- }
105
- const { weeks, days, hours, minutes, seconds, milliseconds } = getDurationParts(normalizedDuration);
106
- let isoDuration = "P";
107
- if (weeks > 0) {
108
- isoDuration += `${weeks}W`;
109
- }
110
- if (days > 0) {
111
- isoDuration += `${days}D`;
112
- }
113
- if (hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0) {
114
- isoDuration += "T";
115
- if (hours > 0) {
116
- isoDuration += `${hours}H`;
117
- }
118
- if (minutes > 0) {
119
- isoDuration += `${minutes}M`;
120
- }
121
- if (seconds > 0 || milliseconds > 0) {
122
- if (milliseconds > 0) {
123
- isoDuration += `${seconds}.${milliseconds.toString().padStart(3, "0").replace(/0+$/, "")}S`;
124
- } else {
125
- isoDuration += `${seconds}S`;
126
- }
127
- }
128
- }
129
- return isoDuration;
130
- }
131
- function getDateTime(date) {
132
- if (date instanceof Date) {
133
- return date.getTime();
134
- }
135
- return new Date(date).getTime();
136
- }
137
- function getDuration(from, to) {
138
- return getDateTime(to) - getDateTime(from);
139
- }
140
- const Duration = react.forwardRef(
141
- ({
142
- duration,
143
- from,
144
- to,
145
- locale,
146
- dateTime,
147
- title: renderTitle = formatVerboseDuration,
148
- children: renderChildren = formatShortDuration,
149
- interval = RENDER_INTERVAL,
150
- asChild,
151
- ...props
152
- }, forwardedRef) => {
153
- const Component = asChild ? reactSlot.Slot : "time";
154
- const [rerender, key] = useRerender.useRerender();
155
- const resolvedDuration = react.useMemo(() => {
156
- if (duration !== void 0) {
157
- return duration;
158
- }
159
- if (from !== void 0) {
160
- return getDuration(from, to ?? Date.now());
161
- }
162
- return 0;
163
- }, [duration, from, to, key]);
164
- const normalizedDuration = react.useMemo(
165
- () => formatIso8601Duration(resolvedDuration),
166
- [resolvedDuration]
167
- );
168
- const title = react.useMemo(
169
- () => typeof renderTitle === "function" ? renderTitle(resolvedDuration, locale) : renderTitle,
170
- [renderTitle, resolvedDuration, locale]
171
- );
172
- const children = react.useMemo(
173
- () => typeof renderChildren === "function" ? renderChildren(resolvedDuration, locale) : renderChildren,
174
- [renderChildren, resolvedDuration, locale]
175
- );
176
- useInterval.useInterval(
177
- rerender,
178
- from !== void 0 && to === void 0 ? interval : false
179
- );
180
- return /* @__PURE__ */ jsxRuntime.jsx(Component, {
181
- ...props,
182
- ref: forwardedRef,
183
- dateTime: dateTime ?? normalizedDuration,
184
- title,
185
- children
186
- });
187
- }
188
- );
189
- if (process.env.NODE_ENV !== "production") {
190
- Duration.displayName = DURATION_NAME;
191
- }
192
-
193
- exports.Duration = Duration;
194
- exports.formatIso8601Duration = formatIso8601Duration;
195
- //# sourceMappingURL=Duration.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Duration.cjs","sources":["../../src/primitives/Duration.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Relax } from \"@liveblocks/core\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { forwardRef, type ReactNode, useMemo } from \"react\";\n\nimport type { ComponentPropsWithSlot } from \"../types\";\nimport { numberFormat } from \"../utils/intl\";\nimport { useInterval } from \"../utils/use-interval\";\nimport { useRerender } from \"../utils/use-rerender\";\n\nconst RENDER_INTERVAL = 0.5 * 1000; // 0.5 second\n\nconst DURATION_NAME = \"Duration\";\n\nexport type DurationProps = Omit<\n ComponentPropsWithSlot<\"time\">,\n \"children\" | \"title\"\n> &\n Relax<\n | {\n /**\n * The duration in milliseconds.\n * If provided, `from` and `to` will be ignored.\n */\n duration: number;\n }\n | {\n /**\n * The date at which the duration starts.\n * If provided, `duration` will be ignored.\n * If provided without `to` it means that the duration is in progress,\n * and the component will re-render at an interval, customizable with\n * the `interval` prop.\n */\n from: Date | string | number;\n\n /**\n * The date at which the duration ends.\n * If `from` is provided without `to`, `Date.now()` will be used.\n */\n to?: Date | string | number;\n }\n > & {\n /**\n * A function to format the displayed duration.\n */\n children?: (duration: number, locale?: string) => ReactNode;\n\n /**\n * The `title` attribute's value or a function to format it.\n */\n title?: string | ((duration: number, locale?: string) => string);\n\n /**\n * The interval in milliseconds at which the component will re-render if\n * `from` is provided without `to`, meaning that the duration is in progress.\n * Can be set to `false` to disable re-rendering.\n */\n interval?: number | false;\n\n /**\n * The locale used when formatting the duration.\n */\n locale?: string;\n };\n\ninterface DurationParts {\n weeks: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n}\n\nfunction getDurationParts(duration: number): DurationParts {\n let remaining = Math.max(duration, 0);\n\n const milliseconds = remaining % 1000;\n remaining = Math.floor(remaining / 1000);\n\n const seconds = remaining % 60;\n remaining = Math.floor(remaining / 60);\n\n const minutes = remaining % 60;\n remaining = Math.floor(remaining / 60);\n\n const hours = remaining % 24;\n remaining = Math.floor(remaining / 24);\n\n const days = remaining % 7;\n const weeks = Math.floor(remaining / 7);\n\n return { weeks, days, hours, minutes, seconds, milliseconds };\n}\n\nconst durationPartsToNumberFormatOptions: Record<\n keyof DurationParts,\n Intl.NumberFormatOptions[\"unit\"]\n> = {\n weeks: \"week\",\n days: \"day\",\n hours: \"hour\",\n minutes: \"minute\",\n seconds: \"second\",\n milliseconds: \"millisecond\",\n};\n\n/**\n * Formats a duration in a short format.\n * TODO: Use `Intl.DurationFormat` when it's better supported.\n */\nfunction formatShortDuration(duration: number, locale?: string) {\n let resolvedLocale: string;\n\n if (locale) {\n resolvedLocale = locale;\n } else {\n const formatter = numberFormat();\n\n resolvedLocale = formatter.resolvedOptions().locale;\n }\n\n const parts = getDurationParts(duration);\n const formattedParts: string[] = [];\n\n for (const [unit, value] of Object.entries(parts) as [\n keyof DurationParts,\n number,\n ][]) {\n if (value === 0 || unit === \"milliseconds\") {\n continue;\n }\n\n const formatter = numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: durationPartsToNumberFormatOptions[unit],\n unitDisplay: \"narrow\",\n });\n\n formattedParts.push(formatter.format(value));\n }\n\n if (!formattedParts.length) {\n formattedParts.push(\n numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: \"second\",\n unitDisplay: \"narrow\",\n }).format(0)\n );\n }\n\n return formattedParts.join(\" \");\n}\n\n/**\n * Formats a duration in a longer format.\n * TODO: Use `Intl.DurationFormat` when it's better supported.\n */\nfunction formatVerboseDuration(duration: number, locale?: string) {\n let resolvedLocale: string;\n\n if (locale) {\n resolvedLocale = locale;\n } else {\n const formatter = numberFormat();\n\n resolvedLocale = formatter.resolvedOptions().locale;\n }\n\n const parts = getDurationParts(duration);\n const formattedParts: string[] = [];\n\n for (const [unit, value] of Object.entries(parts) as [\n keyof DurationParts,\n number,\n ][]) {\n if (value === 0 || unit === \"milliseconds\") {\n continue;\n }\n\n const formatter = numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: durationPartsToNumberFormatOptions[unit],\n unitDisplay: \"long\",\n });\n\n formattedParts.push(formatter.format(value));\n }\n\n if (!formattedParts.length) {\n formattedParts.push(\n numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: \"second\",\n unitDisplay: \"long\",\n }).format(0)\n );\n }\n\n return formattedParts.join(\" \");\n}\n\n/**\n * Formats a duration as ISO 8601.\n * TODO: Use `Temporal.Duration` when it's better supported.\n */\nexport function formatIso8601Duration(duration: number) {\n const normalizedDuration = Math.max(duration, 0);\n\n if (normalizedDuration === 0) {\n return \"PT0S\";\n }\n\n const { weeks, days, hours, minutes, seconds, milliseconds } =\n getDurationParts(normalizedDuration);\n\n let isoDuration = \"P\";\n\n // 1. Weeks\n if (weeks > 0) {\n isoDuration += `${weeks}W`;\n }\n\n // 2. Days\n if (days > 0) {\n isoDuration += `${days}D`;\n }\n\n if (hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0) {\n isoDuration += \"T\";\n\n // 3. Hours\n if (hours > 0) {\n isoDuration += `${hours}H`;\n }\n\n // 4. Minutes\n if (minutes > 0) {\n isoDuration += `${minutes}M`;\n }\n\n // 5. Seconds and milliseconds\n if (seconds > 0 || milliseconds > 0) {\n if (milliseconds > 0) {\n isoDuration += `${seconds}.${milliseconds.toString().padStart(3, \"0\").replace(/0+$/, \"\")}S`;\n } else {\n isoDuration += `${seconds}S`;\n }\n }\n }\n\n return isoDuration;\n}\n\n/**\n * Converts a Date or Date-like value to a timestamp in milliseconds.\n */\nfunction getDateTime(date: Date | string | number) {\n if (date instanceof Date) {\n return date.getTime();\n }\n\n return new Date(date).getTime();\n}\n\n/**\n * Get a duration between two Date or Date-like values.\n */\nfunction getDuration(from: Date | string | number, to: Date | string | number) {\n return getDateTime(to) - getDateTime(from);\n}\n\n/**\n * Displays a formatted duration, and automatically re-renders to if the\n * duration is in progress.\n *\n * @example\n * <Duration duration={3 * 60 * 1000} />\n *\n * @example\n * <Duration from={fiveHoursAgoDate} />\n *\n * @example\n * <Duration from={fiveHoursAgoDate} to={oneHourAgoDate} />\n */\nexport const Duration = forwardRef<HTMLTimeElement, DurationProps>(\n (\n {\n duration,\n from,\n to,\n locale,\n dateTime,\n title: renderTitle = formatVerboseDuration,\n children: renderChildren = formatShortDuration,\n interval = RENDER_INTERVAL,\n asChild,\n ...props\n },\n forwardedRef\n ) => {\n const Component = asChild ? Slot : \"time\";\n const [rerender, key] = useRerender();\n const resolvedDuration = useMemo(() => {\n if (duration !== undefined) {\n return duration;\n }\n\n if (from !== undefined) {\n return getDuration(from, to ?? Date.now());\n }\n\n return 0;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [duration, from, to, key]);\n const normalizedDuration = useMemo(\n () => formatIso8601Duration(resolvedDuration),\n [resolvedDuration]\n );\n const title = useMemo(\n () =>\n typeof renderTitle === \"function\"\n ? renderTitle(resolvedDuration, locale)\n : renderTitle,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [renderTitle, resolvedDuration, locale]\n );\n const children = useMemo(\n () =>\n typeof renderChildren === \"function\"\n ? renderChildren(resolvedDuration, locale)\n : renderChildren,\n\n [renderChildren, resolvedDuration, locale]\n );\n\n // Only re-render if the duration is in progress.\n useInterval(\n rerender,\n from !== undefined && to === undefined ? interval : false\n );\n\n return (\n <Component\n {...props}\n ref={forwardedRef}\n dateTime={dateTime ?? normalizedDuration}\n title={title}\n >\n {children}\n </Component>\n );\n }\n);\n\nif (process.env.NODE_ENV !== \"production\") {\n Duration.displayName = DURATION_NAME;\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAWA;AAEA;AA+DA;AACE;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACF;AAEA;AAGI;AACK;AACD;AACC;AACE;AACA;AAEX;AAMA;AACE;AAEA;AACE;AAAiB;AAEjB;AAEA;AAA6C;AAG/C;AACA;AAEA;AAIE;AACE;AAAA;AAGF;AAA+C;AACtC;AACkC;AAC5B;AAGf;AAA2C;AAG7C;AACE;AAAe;AACgB;AACpB;AACD;AACO;AACJ;AACb;AAGF;AACF;AAMA;AACE;AAEA;AACE;AAAiB;AAEjB;AAEA;AAA6C;AAG/C;AACA;AAEA;AAIE;AACE;AAAA;AAGF;AAA+C;AACtC;AACkC;AAC5B;AAGf;AAA2C;AAG7C;AACE;AAAe;AACgB;AACpB;AACD;AACO;AACJ;AACb;AAGF;AACF;AAMO;AACL;AAEA;AACE;AAAO;AAGT;AAGA;AAGA;AACE;AAAkB;AAIpB;AACE;AAAkB;AAGpB;AACE;AAGA;AACE;AAAkB;AAIpB;AACE;AAAkB;AAIpB;AACE;AACE;AAAuF;AAEvF;AAAkB;AACpB;AACF;AAGF;AACF;AAKA;AACE;AACE;AAAoB;AAGtB;AACF;AAKA;AACE;AACF;AAeO;AAAiB;AAEpB;AACE;AACA;AACA;AACA;AACA;AACqB;AACM;AAChB;AACX;AACG;AAIL;AACA;AACA;AACE;AACE;AAAO;AAGT;AACE;AAAyC;AAG3C;AAAO;AAGT;AAA2B;AACmB;AAC3B;AAEnB;AAAc;AAIN;AAEgC;AAExC;AAAiB;AAIT;AAEmC;AAI3C;AAAA;AACE;AACoD;AAGtD;AACG;AACK;AACC;AACiB;AACtB;AAEC;AACH;AAGN;AAEA;AACE;AACF;;;"}
@@ -1,192 +0,0 @@
1
- "use client";
2
- import { jsx } from 'react/jsx-runtime';
3
- import { Slot } from '@radix-ui/react-slot';
4
- import { forwardRef, useMemo } from 'react';
5
- import { numberFormat } from '../utils/intl.js';
6
- import { useInterval } from '../utils/use-interval.js';
7
- import { useRerender } from '../utils/use-rerender.js';
8
-
9
-
10
- const RENDER_INTERVAL = 0.5 * 1e3;
11
- const DURATION_NAME = "Duration";
12
- function getDurationParts(duration) {
13
- let remaining = Math.max(duration, 0);
14
- const milliseconds = remaining % 1e3;
15
- remaining = Math.floor(remaining / 1e3);
16
- const seconds = remaining % 60;
17
- remaining = Math.floor(remaining / 60);
18
- const minutes = remaining % 60;
19
- remaining = Math.floor(remaining / 60);
20
- const hours = remaining % 24;
21
- remaining = Math.floor(remaining / 24);
22
- const days = remaining % 7;
23
- const weeks = Math.floor(remaining / 7);
24
- return { weeks, days, hours, minutes, seconds, milliseconds };
25
- }
26
- const durationPartsToNumberFormatOptions = {
27
- weeks: "week",
28
- days: "day",
29
- hours: "hour",
30
- minutes: "minute",
31
- seconds: "second",
32
- milliseconds: "millisecond"
33
- };
34
- function formatShortDuration(duration, locale) {
35
- let resolvedLocale;
36
- if (locale) {
37
- resolvedLocale = locale;
38
- } else {
39
- const formatter = numberFormat();
40
- resolvedLocale = formatter.resolvedOptions().locale;
41
- }
42
- const parts = getDurationParts(duration);
43
- const formattedParts = [];
44
- for (const [unit, value] of Object.entries(parts)) {
45
- if (value === 0 || unit === "milliseconds") {
46
- continue;
47
- }
48
- const formatter = numberFormat(resolvedLocale, {
49
- style: "unit",
50
- unit: durationPartsToNumberFormatOptions[unit],
51
- unitDisplay: "narrow"
52
- });
53
- formattedParts.push(formatter.format(value));
54
- }
55
- if (!formattedParts.length) {
56
- formattedParts.push(
57
- numberFormat(resolvedLocale, {
58
- style: "unit",
59
- unit: "second",
60
- unitDisplay: "narrow"
61
- }).format(0)
62
- );
63
- }
64
- return formattedParts.join(" ");
65
- }
66
- function formatVerboseDuration(duration, locale) {
67
- let resolvedLocale;
68
- if (locale) {
69
- resolvedLocale = locale;
70
- } else {
71
- const formatter = numberFormat();
72
- resolvedLocale = formatter.resolvedOptions().locale;
73
- }
74
- const parts = getDurationParts(duration);
75
- const formattedParts = [];
76
- for (const [unit, value] of Object.entries(parts)) {
77
- if (value === 0 || unit === "milliseconds") {
78
- continue;
79
- }
80
- const formatter = numberFormat(resolvedLocale, {
81
- style: "unit",
82
- unit: durationPartsToNumberFormatOptions[unit],
83
- unitDisplay: "long"
84
- });
85
- formattedParts.push(formatter.format(value));
86
- }
87
- if (!formattedParts.length) {
88
- formattedParts.push(
89
- numberFormat(resolvedLocale, {
90
- style: "unit",
91
- unit: "second",
92
- unitDisplay: "long"
93
- }).format(0)
94
- );
95
- }
96
- return formattedParts.join(" ");
97
- }
98
- function formatIso8601Duration(duration) {
99
- const normalizedDuration = Math.max(duration, 0);
100
- if (normalizedDuration === 0) {
101
- return "PT0S";
102
- }
103
- const { weeks, days, hours, minutes, seconds, milliseconds } = getDurationParts(normalizedDuration);
104
- let isoDuration = "P";
105
- if (weeks > 0) {
106
- isoDuration += `${weeks}W`;
107
- }
108
- if (days > 0) {
109
- isoDuration += `${days}D`;
110
- }
111
- if (hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0) {
112
- isoDuration += "T";
113
- if (hours > 0) {
114
- isoDuration += `${hours}H`;
115
- }
116
- if (minutes > 0) {
117
- isoDuration += `${minutes}M`;
118
- }
119
- if (seconds > 0 || milliseconds > 0) {
120
- if (milliseconds > 0) {
121
- isoDuration += `${seconds}.${milliseconds.toString().padStart(3, "0").replace(/0+$/, "")}S`;
122
- } else {
123
- isoDuration += `${seconds}S`;
124
- }
125
- }
126
- }
127
- return isoDuration;
128
- }
129
- function getDateTime(date) {
130
- if (date instanceof Date) {
131
- return date.getTime();
132
- }
133
- return new Date(date).getTime();
134
- }
135
- function getDuration(from, to) {
136
- return getDateTime(to) - getDateTime(from);
137
- }
138
- const Duration = forwardRef(
139
- ({
140
- duration,
141
- from,
142
- to,
143
- locale,
144
- dateTime,
145
- title: renderTitle = formatVerboseDuration,
146
- children: renderChildren = formatShortDuration,
147
- interval = RENDER_INTERVAL,
148
- asChild,
149
- ...props
150
- }, forwardedRef) => {
151
- const Component = asChild ? Slot : "time";
152
- const [rerender, key] = useRerender();
153
- const resolvedDuration = useMemo(() => {
154
- if (duration !== void 0) {
155
- return duration;
156
- }
157
- if (from !== void 0) {
158
- return getDuration(from, to ?? Date.now());
159
- }
160
- return 0;
161
- }, [duration, from, to, key]);
162
- const normalizedDuration = useMemo(
163
- () => formatIso8601Duration(resolvedDuration),
164
- [resolvedDuration]
165
- );
166
- const title = useMemo(
167
- () => typeof renderTitle === "function" ? renderTitle(resolvedDuration, locale) : renderTitle,
168
- [renderTitle, resolvedDuration, locale]
169
- );
170
- const children = useMemo(
171
- () => typeof renderChildren === "function" ? renderChildren(resolvedDuration, locale) : renderChildren,
172
- [renderChildren, resolvedDuration, locale]
173
- );
174
- useInterval(
175
- rerender,
176
- from !== void 0 && to === void 0 ? interval : false
177
- );
178
- return /* @__PURE__ */ jsx(Component, {
179
- ...props,
180
- ref: forwardedRef,
181
- dateTime: dateTime ?? normalizedDuration,
182
- title,
183
- children
184
- });
185
- }
186
- );
187
- if (process.env.NODE_ENV !== "production") {
188
- Duration.displayName = DURATION_NAME;
189
- }
190
-
191
- export { Duration, formatIso8601Duration };
192
- //# sourceMappingURL=Duration.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Duration.js","sources":["../../src/primitives/Duration.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Relax } from \"@liveblocks/core\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { forwardRef, type ReactNode, useMemo } from \"react\";\n\nimport type { ComponentPropsWithSlot } from \"../types\";\nimport { numberFormat } from \"../utils/intl\";\nimport { useInterval } from \"../utils/use-interval\";\nimport { useRerender } from \"../utils/use-rerender\";\n\nconst RENDER_INTERVAL = 0.5 * 1000; // 0.5 second\n\nconst DURATION_NAME = \"Duration\";\n\nexport type DurationProps = Omit<\n ComponentPropsWithSlot<\"time\">,\n \"children\" | \"title\"\n> &\n Relax<\n | {\n /**\n * The duration in milliseconds.\n * If provided, `from` and `to` will be ignored.\n */\n duration: number;\n }\n | {\n /**\n * The date at which the duration starts.\n * If provided, `duration` will be ignored.\n * If provided without `to` it means that the duration is in progress,\n * and the component will re-render at an interval, customizable with\n * the `interval` prop.\n */\n from: Date | string | number;\n\n /**\n * The date at which the duration ends.\n * If `from` is provided without `to`, `Date.now()` will be used.\n */\n to?: Date | string | number;\n }\n > & {\n /**\n * A function to format the displayed duration.\n */\n children?: (duration: number, locale?: string) => ReactNode;\n\n /**\n * The `title` attribute's value or a function to format it.\n */\n title?: string | ((duration: number, locale?: string) => string);\n\n /**\n * The interval in milliseconds at which the component will re-render if\n * `from` is provided without `to`, meaning that the duration is in progress.\n * Can be set to `false` to disable re-rendering.\n */\n interval?: number | false;\n\n /**\n * The locale used when formatting the duration.\n */\n locale?: string;\n };\n\ninterface DurationParts {\n weeks: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n}\n\nfunction getDurationParts(duration: number): DurationParts {\n let remaining = Math.max(duration, 0);\n\n const milliseconds = remaining % 1000;\n remaining = Math.floor(remaining / 1000);\n\n const seconds = remaining % 60;\n remaining = Math.floor(remaining / 60);\n\n const minutes = remaining % 60;\n remaining = Math.floor(remaining / 60);\n\n const hours = remaining % 24;\n remaining = Math.floor(remaining / 24);\n\n const days = remaining % 7;\n const weeks = Math.floor(remaining / 7);\n\n return { weeks, days, hours, minutes, seconds, milliseconds };\n}\n\nconst durationPartsToNumberFormatOptions: Record<\n keyof DurationParts,\n Intl.NumberFormatOptions[\"unit\"]\n> = {\n weeks: \"week\",\n days: \"day\",\n hours: \"hour\",\n minutes: \"minute\",\n seconds: \"second\",\n milliseconds: \"millisecond\",\n};\n\n/**\n * Formats a duration in a short format.\n * TODO: Use `Intl.DurationFormat` when it's better supported.\n */\nfunction formatShortDuration(duration: number, locale?: string) {\n let resolvedLocale: string;\n\n if (locale) {\n resolvedLocale = locale;\n } else {\n const formatter = numberFormat();\n\n resolvedLocale = formatter.resolvedOptions().locale;\n }\n\n const parts = getDurationParts(duration);\n const formattedParts: string[] = [];\n\n for (const [unit, value] of Object.entries(parts) as [\n keyof DurationParts,\n number,\n ][]) {\n if (value === 0 || unit === \"milliseconds\") {\n continue;\n }\n\n const formatter = numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: durationPartsToNumberFormatOptions[unit],\n unitDisplay: \"narrow\",\n });\n\n formattedParts.push(formatter.format(value));\n }\n\n if (!formattedParts.length) {\n formattedParts.push(\n numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: \"second\",\n unitDisplay: \"narrow\",\n }).format(0)\n );\n }\n\n return formattedParts.join(\" \");\n}\n\n/**\n * Formats a duration in a longer format.\n * TODO: Use `Intl.DurationFormat` when it's better supported.\n */\nfunction formatVerboseDuration(duration: number, locale?: string) {\n let resolvedLocale: string;\n\n if (locale) {\n resolvedLocale = locale;\n } else {\n const formatter = numberFormat();\n\n resolvedLocale = formatter.resolvedOptions().locale;\n }\n\n const parts = getDurationParts(duration);\n const formattedParts: string[] = [];\n\n for (const [unit, value] of Object.entries(parts) as [\n keyof DurationParts,\n number,\n ][]) {\n if (value === 0 || unit === \"milliseconds\") {\n continue;\n }\n\n const formatter = numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: durationPartsToNumberFormatOptions[unit],\n unitDisplay: \"long\",\n });\n\n formattedParts.push(formatter.format(value));\n }\n\n if (!formattedParts.length) {\n formattedParts.push(\n numberFormat(resolvedLocale, {\n style: \"unit\",\n unit: \"second\",\n unitDisplay: \"long\",\n }).format(0)\n );\n }\n\n return formattedParts.join(\" \");\n}\n\n/**\n * Formats a duration as ISO 8601.\n * TODO: Use `Temporal.Duration` when it's better supported.\n */\nexport function formatIso8601Duration(duration: number) {\n const normalizedDuration = Math.max(duration, 0);\n\n if (normalizedDuration === 0) {\n return \"PT0S\";\n }\n\n const { weeks, days, hours, minutes, seconds, milliseconds } =\n getDurationParts(normalizedDuration);\n\n let isoDuration = \"P\";\n\n // 1. Weeks\n if (weeks > 0) {\n isoDuration += `${weeks}W`;\n }\n\n // 2. Days\n if (days > 0) {\n isoDuration += `${days}D`;\n }\n\n if (hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0) {\n isoDuration += \"T\";\n\n // 3. Hours\n if (hours > 0) {\n isoDuration += `${hours}H`;\n }\n\n // 4. Minutes\n if (minutes > 0) {\n isoDuration += `${minutes}M`;\n }\n\n // 5. Seconds and milliseconds\n if (seconds > 0 || milliseconds > 0) {\n if (milliseconds > 0) {\n isoDuration += `${seconds}.${milliseconds.toString().padStart(3, \"0\").replace(/0+$/, \"\")}S`;\n } else {\n isoDuration += `${seconds}S`;\n }\n }\n }\n\n return isoDuration;\n}\n\n/**\n * Converts a Date or Date-like value to a timestamp in milliseconds.\n */\nfunction getDateTime(date: Date | string | number) {\n if (date instanceof Date) {\n return date.getTime();\n }\n\n return new Date(date).getTime();\n}\n\n/**\n * Get a duration between two Date or Date-like values.\n */\nfunction getDuration(from: Date | string | number, to: Date | string | number) {\n return getDateTime(to) - getDateTime(from);\n}\n\n/**\n * Displays a formatted duration, and automatically re-renders to if the\n * duration is in progress.\n *\n * @example\n * <Duration duration={3 * 60 * 1000} />\n *\n * @example\n * <Duration from={fiveHoursAgoDate} />\n *\n * @example\n * <Duration from={fiveHoursAgoDate} to={oneHourAgoDate} />\n */\nexport const Duration = forwardRef<HTMLTimeElement, DurationProps>(\n (\n {\n duration,\n from,\n to,\n locale,\n dateTime,\n title: renderTitle = formatVerboseDuration,\n children: renderChildren = formatShortDuration,\n interval = RENDER_INTERVAL,\n asChild,\n ...props\n },\n forwardedRef\n ) => {\n const Component = asChild ? Slot : \"time\";\n const [rerender, key] = useRerender();\n const resolvedDuration = useMemo(() => {\n if (duration !== undefined) {\n return duration;\n }\n\n if (from !== undefined) {\n return getDuration(from, to ?? Date.now());\n }\n\n return 0;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [duration, from, to, key]);\n const normalizedDuration = useMemo(\n () => formatIso8601Duration(resolvedDuration),\n [resolvedDuration]\n );\n const title = useMemo(\n () =>\n typeof renderTitle === \"function\"\n ? renderTitle(resolvedDuration, locale)\n : renderTitle,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [renderTitle, resolvedDuration, locale]\n );\n const children = useMemo(\n () =>\n typeof renderChildren === \"function\"\n ? renderChildren(resolvedDuration, locale)\n : renderChildren,\n\n [renderChildren, resolvedDuration, locale]\n );\n\n // Only re-render if the duration is in progress.\n useInterval(\n rerender,\n from !== undefined && to === undefined ? interval : false\n );\n\n return (\n <Component\n {...props}\n ref={forwardedRef}\n dateTime={dateTime ?? normalizedDuration}\n title={title}\n >\n {children}\n </Component>\n );\n }\n);\n\nif (process.env.NODE_ENV !== \"production\") {\n Duration.displayName = DURATION_NAME;\n}\n"],"names":[],"mappings":";;;;;;;;;AAWA;AAEA;AA+DA;AACE;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACF;AAEA;AAGI;AACK;AACD;AACC;AACE;AACA;AAEX;AAMA;AACE;AAEA;AACE;AAAiB;AAEjB;AAEA;AAA6C;AAG/C;AACA;AAEA;AAIE;AACE;AAAA;AAGF;AAA+C;AACtC;AACkC;AAC5B;AAGf;AAA2C;AAG7C;AACE;AAAe;AACgB;AACpB;AACD;AACO;AACJ;AACb;AAGF;AACF;AAMA;AACE;AAEA;AACE;AAAiB;AAEjB;AAEA;AAA6C;AAG/C;AACA;AAEA;AAIE;AACE;AAAA;AAGF;AAA+C;AACtC;AACkC;AAC5B;AAGf;AAA2C;AAG7C;AACE;AAAe;AACgB;AACpB;AACD;AACO;AACJ;AACb;AAGF;AACF;AAMO;AACL;AAEA;AACE;AAAO;AAGT;AAGA;AAGA;AACE;AAAkB;AAIpB;AACE;AAAkB;AAGpB;AACE;AAGA;AACE;AAAkB;AAIpB;AACE;AAAkB;AAIpB;AACE;AACE;AAAuF;AAEvF;AAAkB;AACpB;AACF;AAGF;AACF;AAKA;AACE;AACE;AAAoB;AAGtB;AACF;AAKA;AACE;AACF;AAeO;AAAiB;AAEpB;AACE;AACA;AACA;AACA;AACA;AACqB;AACM;AAChB;AACX;AACG;AAIL;AACA;AACA;AACE;AACE;AAAO;AAGT;AACE;AAAyC;AAG3C;AAAO;AAGT;AAA2B;AACmB;AAC3B;AAEnB;AAAc;AAIN;AAEgC;AAExC;AAAiB;AAIT;AAEmC;AAI3C;AAAA;AACE;AACoD;AAGtD;AACG;AACK;AACC;AACiB;AACtB;AAEC;AACH;AAGN;AAEA;AACE;AACF;;"}