@astryxdesign/core 0.6.3-canary.ea2f048 → 0.6.3
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/dist/Chat/ChatLayout.d.ts +0 -19
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +0 -19
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +5 -5
- package/dist/astryx.css +2 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/package.json +4 -9
- package/src/Chat/ChatLayout.doc.mjs +4 -12
- package/src/Chat/ChatLayout.test.tsx +0 -28
- package/src/Chat/ChatLayout.tsx +0 -19
- package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -31
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -16
- package/src/index.ts +0 -3
- package/src/tailwind-theme.css +6 -0
- package/dist/Timer/Timer.d.ts +0 -49
- package/dist/Timer/Timer.d.ts.map +0 -1
- package/dist/Timer/Timer.js +0 -158
- package/dist/Timer/index.d.ts +0 -9
- package/dist/Timer/index.d.ts.map +0 -1
- package/dist/Timer/index.js +0 -10
- package/src/Chat/ChatLayout.spec.md +0 -271
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +0 -510
- package/src/Timer/Timer.doc.mjs +0 -183
- package/src/Timer/Timer.spec.md +0 -215
- package/src/Timer/Timer.test.tsx +0 -302
- package/src/Timer/Timer.tsx +0 -258
- package/src/Timer/index.ts +0 -11
package/src/Timer/Timer.tsx
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @file Timer.tsx
|
|
7
|
-
* @input Uses an optional start time, standardized format, Timestamp typography, BaseProps, and React ref
|
|
8
|
-
* @output Exports Timer, TimerProps, and TimerFormat with non-rendering elapsed-time updates
|
|
9
|
-
* @position Core content primitive for elapsed duration in active operations
|
|
10
|
-
*
|
|
11
|
-
* SYNC: When modified, update these files to stay in sync:
|
|
12
|
-
* - /packages/core/src/Timer/Timer.spec.md
|
|
13
|
-
* - /packages/core/src/Timer/Timer.doc.mjs
|
|
14
|
-
* - /packages/core/src/Timer/Timer.test.tsx
|
|
15
|
-
* - /packages/core/src/Timer/index.ts
|
|
16
|
-
* - /apps/storybook/stories/Timer.stories.tsx
|
|
17
|
-
* - /packages/cli/assets/templates/blocks/components/Timer/
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import {useEffect, useRef, useState} from 'react';
|
|
21
|
-
import * as stylex from '@stylexjs/stylex';
|
|
22
|
-
import type {BaseProps} from '../BaseProps';
|
|
23
|
-
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
24
|
-
import {Text} from '../Text';
|
|
25
|
-
import type {TextColor, TextSize, TextType, TextWeight} from '../theme/types';
|
|
26
|
-
import {mergeProps} from '../utils';
|
|
27
|
-
import {themeProps} from '../utils/themeProps';
|
|
28
|
-
|
|
29
|
-
const ONE_SECOND_MS = 1000;
|
|
30
|
-
const ONE_MINUTE_MS = 60 * ONE_SECOND_MS;
|
|
31
|
-
const ONE_HOUR_SECONDS = 60 * 60;
|
|
32
|
-
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
33
|
-
|
|
34
|
-
const styles = stylex.create({
|
|
35
|
-
time: {
|
|
36
|
-
color: 'inherit',
|
|
37
|
-
display: 'inline',
|
|
38
|
-
fontFamily: 'inherit',
|
|
39
|
-
fontSize: 'inherit',
|
|
40
|
-
fontStyle: 'normal',
|
|
41
|
-
fontVariantNumeric: 'tabular-nums',
|
|
42
|
-
fontWeight: 'inherit',
|
|
43
|
-
lineHeight: 'inherit',
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
export type TimerFormat = 'elapsed' | 'clock';
|
|
48
|
-
|
|
49
|
-
type TimerPresentation = {
|
|
50
|
-
dateTime: string;
|
|
51
|
-
text: string;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
function pad(value: number): string {
|
|
55
|
-
return String(value).padStart(2, '0');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function resolveFormat(format: TimerFormat): TimerFormat {
|
|
59
|
-
return format === 'clock' ? 'clock' : 'elapsed';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getElapsedMilliseconds(now: number, startTime: number): number {
|
|
63
|
-
return Math.max(0, now - startTime);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getPresentation(
|
|
67
|
-
elapsedMilliseconds: number,
|
|
68
|
-
format: TimerFormat,
|
|
69
|
-
): TimerPresentation {
|
|
70
|
-
const elapsedSeconds = Math.floor(elapsedMilliseconds / ONE_SECOND_MS);
|
|
71
|
-
|
|
72
|
-
if (format === 'clock') {
|
|
73
|
-
const hours = Math.floor(elapsedSeconds / ONE_HOUR_SECONDS);
|
|
74
|
-
const minutes = Math.floor((elapsedSeconds % ONE_HOUR_SECONDS) / 60);
|
|
75
|
-
const seconds = elapsedSeconds % 60;
|
|
76
|
-
return {
|
|
77
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
78
|
-
text:
|
|
79
|
-
hours > 0
|
|
80
|
-
? `${String(hours)}:${pad(minutes)}:${pad(seconds)}`
|
|
81
|
-
: `${String(minutes)}:${pad(seconds)}`,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (elapsedSeconds < 60) {
|
|
86
|
-
return {
|
|
87
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
88
|
-
text: `${String(elapsedSeconds)}s`,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const totalMinutes = Math.floor(elapsedSeconds / 60);
|
|
93
|
-
if (totalMinutes < 60) {
|
|
94
|
-
return {
|
|
95
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
96
|
-
text: `${String(totalMinutes)}m ${pad(elapsedSeconds % 60)}s`,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const representedSeconds = totalMinutes * 60;
|
|
101
|
-
return {
|
|
102
|
-
dateTime: `PT${representedSeconds}S`,
|
|
103
|
-
text: `${String(Math.floor(totalMinutes / 60))}h ${pad(totalMinutes % 60)}m`,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function getMillisecondsUntilNextChange(
|
|
108
|
-
now: number,
|
|
109
|
-
startTime: number,
|
|
110
|
-
elapsedMilliseconds: number,
|
|
111
|
-
format: TimerFormat,
|
|
112
|
-
): number {
|
|
113
|
-
if (now < startTime) {
|
|
114
|
-
return Math.min(startTime - now + ONE_SECOND_MS, MAX_TIMEOUT_MS);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const precision =
|
|
118
|
-
format === 'elapsed' &&
|
|
119
|
-
elapsedMilliseconds >= ONE_HOUR_SECONDS * ONE_SECOND_MS
|
|
120
|
-
? ONE_MINUTE_MS
|
|
121
|
-
: ONE_SECOND_MS;
|
|
122
|
-
return precision - (elapsedMilliseconds % precision);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface TimerProps extends Omit<
|
|
126
|
-
BaseProps<HTMLTimeElement>,
|
|
127
|
-
'dateTime'
|
|
128
|
-
> {
|
|
129
|
-
/** Ref forwarded to the rendered `<time>` element. */
|
|
130
|
-
ref?: React.Ref<HTMLTimeElement>;
|
|
131
|
-
/**
|
|
132
|
-
* Unix time in milliseconds when the measured operation began. Omit it to
|
|
133
|
-
* start counting from this Timer's mount.
|
|
134
|
-
*/
|
|
135
|
-
startTime?: number;
|
|
136
|
-
/**
|
|
137
|
-
* Standard duration representation.
|
|
138
|
-
* @default 'elapsed'
|
|
139
|
-
*/
|
|
140
|
-
format?: TimerFormat;
|
|
141
|
-
/**
|
|
142
|
-
* Semantic text type. Matches Timestamp typography behavior.
|
|
143
|
-
* @default 'supporting'
|
|
144
|
-
*/
|
|
145
|
-
type?: TextType;
|
|
146
|
-
/** Explicit font size override. Overrides the size from `type`. */
|
|
147
|
-
size?: TextSize;
|
|
148
|
-
/**
|
|
149
|
-
* Text color.
|
|
150
|
-
* @default 'secondary'
|
|
151
|
-
*/
|
|
152
|
-
color?: TextColor;
|
|
153
|
-
/** Font weight override. */
|
|
154
|
-
weight?: TextWeight;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Displays a standardized elapsed duration without scheduling React tick renders.
|
|
159
|
-
*
|
|
160
|
-
* Timer writes changing text and its ISO 8601 duration directly to the owned
|
|
161
|
-
* `<time>` node. Use `elapsed` for compact duration text or `clock` for a
|
|
162
|
-
* stopwatch-like reading.
|
|
163
|
-
*
|
|
164
|
-
* @example
|
|
165
|
-
* ```
|
|
166
|
-
* <Timer />
|
|
167
|
-
* <Timer format="clock" />
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
|
-
export function Timer({
|
|
171
|
-
startTime,
|
|
172
|
-
format = 'elapsed',
|
|
173
|
-
type = 'supporting',
|
|
174
|
-
size,
|
|
175
|
-
color = 'secondary',
|
|
176
|
-
weight,
|
|
177
|
-
ref,
|
|
178
|
-
xstyle,
|
|
179
|
-
className,
|
|
180
|
-
style,
|
|
181
|
-
...rest
|
|
182
|
-
}: TimerProps) {
|
|
183
|
-
const [mountTime] = useState(() => Date.now());
|
|
184
|
-
const timerRef = useRef<HTMLTimeElement>(null);
|
|
185
|
-
const mergedRef = useMergedRefs(ref, timerRef);
|
|
186
|
-
const resolvedFormat = resolveFormat(format);
|
|
187
|
-
const initialPresentation = getPresentation(0, resolvedFormat);
|
|
188
|
-
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
const resolvedStartTime =
|
|
191
|
-
startTime !== undefined && Number.isFinite(startTime)
|
|
192
|
-
? startTime
|
|
193
|
-
: mountTime;
|
|
194
|
-
let timeoutID: ReturnType<typeof setTimeout> | undefined;
|
|
195
|
-
let previousDateTime: string | undefined;
|
|
196
|
-
let previousText: string | undefined;
|
|
197
|
-
|
|
198
|
-
const tick = () => {
|
|
199
|
-
const now = Date.now();
|
|
200
|
-
const elapsedMilliseconds = getElapsedMilliseconds(
|
|
201
|
-
now,
|
|
202
|
-
resolvedStartTime,
|
|
203
|
-
);
|
|
204
|
-
const presentation = getPresentation(elapsedMilliseconds, resolvedFormat);
|
|
205
|
-
const node = timerRef.current;
|
|
206
|
-
|
|
207
|
-
if (node != null) {
|
|
208
|
-
if (presentation.text !== previousText) {
|
|
209
|
-
node.textContent = presentation.text;
|
|
210
|
-
previousText = presentation.text;
|
|
211
|
-
}
|
|
212
|
-
if (presentation.dateTime !== previousDateTime) {
|
|
213
|
-
node.dateTime = presentation.dateTime;
|
|
214
|
-
previousDateTime = presentation.dateTime;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
timeoutID = setTimeout(
|
|
219
|
-
tick,
|
|
220
|
-
getMillisecondsUntilNextChange(
|
|
221
|
-
now,
|
|
222
|
-
resolvedStartTime,
|
|
223
|
-
elapsedMilliseconds,
|
|
224
|
-
resolvedFormat,
|
|
225
|
-
),
|
|
226
|
-
);
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
tick();
|
|
230
|
-
return () => {
|
|
231
|
-
if (timeoutID !== undefined) {
|
|
232
|
-
clearTimeout(timeoutID);
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
}, [mountTime, resolvedFormat, startTime]);
|
|
236
|
-
|
|
237
|
-
const timerProps = mergeProps(themeProps('timer'), {className, style});
|
|
238
|
-
|
|
239
|
-
return (
|
|
240
|
-
<Text
|
|
241
|
-
type={type}
|
|
242
|
-
size={size}
|
|
243
|
-
color={color}
|
|
244
|
-
weight={weight}
|
|
245
|
-
xstyle={xstyle}
|
|
246
|
-
{...timerProps}>
|
|
247
|
-
<time
|
|
248
|
-
{...rest}
|
|
249
|
-
ref={mergedRef}
|
|
250
|
-
dateTime="PT0S"
|
|
251
|
-
{...stylex.props(styles.time)}>
|
|
252
|
-
{initialPresentation.text}
|
|
253
|
-
</time>
|
|
254
|
-
</Text>
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
Timer.displayName = 'Timer';
|
package/src/Timer/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file index.ts
|
|
5
|
-
* @input Imports Timer, TimerProps, and TimerFormat
|
|
6
|
-
* @output Public Timer component barrel
|
|
7
|
-
* @position Component subpath entry point for @astryxdesign/core/Timer
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export {Timer} from './Timer';
|
|
11
|
-
export type {TimerFormat, TimerProps} from './Timer';
|