@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
|
@@ -70,25 +70,6 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
|
|
|
70
70
|
*/
|
|
71
71
|
density?: Density;
|
|
72
72
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Layout shell for a full chat interface: messages in page flow, composer
|
|
75
|
-
* docked to the bottom behind a frosted glass layer, with auto-scroll and a
|
|
76
|
-
* scroll-to-bottom button wired in.
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
* ```
|
|
80
|
-
* <ChatLayout
|
|
81
|
-
* density="spacious"
|
|
82
|
-
* composer={<ChatComposer onSubmit={send} />}
|
|
83
|
-
* emptyState={<EmptyState title="No messages yet" />}>
|
|
84
|
-
* <ChatMessageList>
|
|
85
|
-
* <ChatMessage sender="assistant">
|
|
86
|
-
* <ChatMessageBubble>How can I help?</ChatMessageBubble>
|
|
87
|
-
* </ChatMessage>
|
|
88
|
-
* </ChatMessageList>
|
|
89
|
-
* </ChatLayout>
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
73
|
export declare function ChatLayout({ children, composer, density, emptyState, scrollButton, scrollRef: externalScrollRef, xstyle, className, style, 'data-testid': testId, ref, ...rest }: ChatLayoutProps): import("react").JSX.Element;
|
|
93
74
|
export declare namespace ChatLayout {
|
|
94
75
|
var displayName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatLayout.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,KAAK,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA4KD
|
|
1
|
+
{"version":3,"file":"ChatLayout.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,KAAK,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA4KD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,OAAoB,EACpB,UAAU,EACV,YAAY,EACZ,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BA4GjB;yBAzHe,UAAU"}
|
package/dist/Chat/ChatLayout.js
CHANGED
|
@@ -184,25 +184,6 @@ function hasVisibleContent(children) {
|
|
|
184
184
|
// Component
|
|
185
185
|
// =============================================================================
|
|
186
186
|
|
|
187
|
-
/**
|
|
188
|
-
* Layout shell for a full chat interface: messages in page flow, composer
|
|
189
|
-
* docked to the bottom behind a frosted glass layer, with auto-scroll and a
|
|
190
|
-
* scroll-to-bottom button wired in.
|
|
191
|
-
*
|
|
192
|
-
* @example
|
|
193
|
-
* ```
|
|
194
|
-
* <ChatLayout
|
|
195
|
-
* density="spacious"
|
|
196
|
-
* composer={<ChatComposer onSubmit={send} />}
|
|
197
|
-
* emptyState={<EmptyState title="No messages yet" />}>
|
|
198
|
-
* <ChatMessageList>
|
|
199
|
-
* <ChatMessage sender="assistant">
|
|
200
|
-
* <ChatMessageBubble>How can I help?</ChatMessageBubble>
|
|
201
|
-
* </ChatMessage>
|
|
202
|
-
* </ChatMessageList>
|
|
203
|
-
* </ChatLayout>
|
|
204
|
-
* ```
|
|
205
|
-
*/
|
|
206
187
|
export function ChatLayout({
|
|
207
188
|
children,
|
|
208
189
|
composer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAS5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2DD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,2BAA2B,qBAkC7B;yBA3Ce,sBAAsB"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import React from 'react';
|
|
19
19
|
import * as stylex from '@stylexjs/stylex';
|
|
20
20
|
import "../theme/tokens.stylex.js";
|
|
21
|
-
import { colorVars, spacingVars, radiusVars, shadowVars,
|
|
21
|
+
import { colorVars, spacingVars, radiusVars, shadowVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
|
|
22
22
|
import { Icon } from "../Icon/index.js";
|
|
23
23
|
import { Button } from "../Button/index.js";
|
|
24
24
|
import { mergeProps } from "../utils/index.js";
|
|
@@ -82,16 +82,16 @@ export function ChatLayoutScrollButton({
|
|
|
82
82
|
children: /*#__PURE__*/_jsx("div", {
|
|
83
83
|
...{
|
|
84
84
|
0: {
|
|
85
|
-
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27
|
|
85
|
+
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl x1x67gh"
|
|
86
86
|
},
|
|
87
87
|
2: {
|
|
88
|
-
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27
|
|
88
|
+
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w x1x67gh"
|
|
89
89
|
},
|
|
90
90
|
1: {
|
|
91
|
-
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27
|
|
91
|
+
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl x1ncir08"
|
|
92
92
|
},
|
|
93
93
|
3: {
|
|
94
|
-
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27
|
|
94
|
+
className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w x1ncir08"
|
|
95
95
|
}
|
|
96
96
|
}[!!isVisible << 1 | !!label << 0],
|
|
97
97
|
children: /*#__PURE__*/_jsx(Button, {
|
package/dist/astryx.css
CHANGED
|
@@ -1281,7 +1281,7 @@
|
|
|
1281
1281
|
.xnpjden:not(#\#):not(#\#):not(#\#){transition-property:opacity,background-color}
|
|
1282
1282
|
.xsm4mo9:not(#\#):not(#\#):not(#\#){transition-property:opacity,display,overlay}
|
|
1283
1283
|
.x1n1p2mu:not(#\#):not(#\#):not(#\#){transition-property:opacity,position}
|
|
1284
|
-
.
|
|
1284
|
+
.x1apppo2:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform,max-width}
|
|
1285
1285
|
.x4bbghf:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform,overlay,display}
|
|
1286
1286
|
.x6o7n8i:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform}
|
|
1287
1287
|
.xxup5nn:not(#\#):not(#\#):not(#\#){transition-property:opacity,visibility,transform}
|
|
@@ -1656,6 +1656,7 @@
|
|
|
1656
1656
|
.x55n99s:not(#\#):not(#\#):not(#\#):not(#\#){max-width:15em}
|
|
1657
1657
|
.x1ncir08:not(#\#):not(#\#):not(#\#):not(#\#){max-width:200px}
|
|
1658
1658
|
.xw5ewwj:not(#\#):not(#\#):not(#\#):not(#\#){max-width:300px}
|
|
1659
|
+
.x1x67gh:not(#\#):not(#\#):not(#\#):not(#\#){max-width:32px}
|
|
1659
1660
|
.xxc7z9f:not(#\#):not(#\#):not(#\#):not(#\#){max-width:360px}
|
|
1660
1661
|
.x1j9u4d2:not(#\#):not(#\#):not(#\#):not(#\#){max-width:400px}
|
|
1661
1662
|
.x17fpy1y:not(#\#):not(#\#):not(#\#):not(#\#){max-width:480px}
|
|
@@ -1670,7 +1671,6 @@
|
|
|
1670
1671
|
.x1m1aaou:not(#\#):not(#\#):not(#\#):not(#\#){max-width:min(960px,calc(100dvw - var(--spacing-4)))}
|
|
1671
1672
|
.x1x1rfll:not(#\#):not(#\#):not(#\#):not(#\#){max-width:none}
|
|
1672
1673
|
.xjl2t3p:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--layout-content-width,none)}
|
|
1673
|
-
.x1jys5uj:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--size-element-md)}
|
|
1674
1674
|
.xf68679:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--x-maxWidth)}
|
|
1675
1675
|
.x2lwn1j:not(#\#):not(#\#):not(#\#):not(#\#){min-height:0}
|
|
1676
1676
|
.x1us19tq:not(#\#):not(#\#):not(#\#):not(#\#){min-height:100%}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAGH,YAAY,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAG3C,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAE1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAG3B,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAG9B,cAAc,UAAU,CAAC;AAGzB,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAC;AACjC,YAAY,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AACtC,YAAY,EAAC,kBAAkB,EAAE,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAGlE,OAAO,EAAC,KAAK,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AACxC,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAGjB,cAAc,WAAW,CAAC;AAG1B,cAAc,aAAa,CAAC;AAG5B,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,aAAa,CAAC;AAG5B,cAAc,WAAW,CAAC;AAG1B,cAAc,aAAa,CAAC;AAG5B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -133,9 +133,6 @@ export * from "./Spinner/index.js";
|
|
|
133
133
|
// Timestamp display
|
|
134
134
|
export * from "./Timestamp/index.js";
|
|
135
135
|
|
|
136
|
-
// Elapsed timer display
|
|
137
|
-
export * from "./Timer/index.js";
|
|
138
|
-
|
|
139
136
|
// Overlay
|
|
140
137
|
export * from "./Overlay/index.js";
|
|
141
138
|
export * from "./Outline/index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.6.3
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -539,11 +539,6 @@
|
|
|
539
539
|
"types": "./dist/TimeInput/index.d.ts",
|
|
540
540
|
"default": "./dist/TimeInput/index.js"
|
|
541
541
|
},
|
|
542
|
-
"./Timer": {
|
|
543
|
-
"source": "./src/Timer/index.ts",
|
|
544
|
-
"types": "./dist/Timer/index.d.ts",
|
|
545
|
-
"default": "./dist/Timer/index.js"
|
|
546
|
-
},
|
|
547
542
|
"./Timestamp": {
|
|
548
543
|
"source": "./src/Timestamp/index.ts",
|
|
549
544
|
"types": "./dist/Timestamp/index.d.ts",
|
|
@@ -692,8 +687,6 @@
|
|
|
692
687
|
"react-dom": ">=19.0.0"
|
|
693
688
|
},
|
|
694
689
|
"devDependencies": {
|
|
695
|
-
"@astryxdesign/a11y-spec": "0.6.3-canary.ea2f048",
|
|
696
|
-
"@astryxdesign/cli": "0.6.3-canary.ea2f048",
|
|
697
690
|
"@babel/cli": "^7.29.7",
|
|
698
691
|
"@babel/core": "^7.29.7",
|
|
699
692
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -703,7 +696,9 @@
|
|
|
703
696
|
"@testing-library/dom": "^10.0.0",
|
|
704
697
|
"@testing-library/jest-dom": "^6.6.0",
|
|
705
698
|
"@testing-library/react": "^16.3.2",
|
|
706
|
-
"@types/babel__core": "^7.20.5"
|
|
699
|
+
"@types/babel__core": "^7.20.5",
|
|
700
|
+
"@astryxdesign/a11y-spec": "0.0.0",
|
|
701
|
+
"@astryxdesign/cli": "0.6.3"
|
|
707
702
|
},
|
|
708
703
|
"dependencies": {
|
|
709
704
|
"intl-messageformat": "^11.2.9"
|
|
@@ -6,7 +6,7 @@ export const docs = {
|
|
|
6
6
|
name: 'ChatLayout',
|
|
7
7
|
subComponentOf: 'Chat',
|
|
8
8
|
displayName: 'Chat Layout',
|
|
9
|
-
description: 'Layout shell for full chat interfaces. Messages flow in normal page flow, composer is fixed to the bottom with a frosted glass dock.
|
|
9
|
+
description: 'Layout shell for full chat interfaces. Messages flow in normal page flow, composer is fixed to the bottom with a frosted glass dock. Adapts density (compact/balanced/spacious) automatically via container width observation. Includes built-in auto-scroll, a "New messages" scroll-to-bottom button, and a frosted glass blur layer behind the composer. By default the layout root is the scroll container; pass scrollRef to delegate scrolling to a parent element or the document body.',
|
|
10
10
|
props: [
|
|
11
11
|
{
|
|
12
12
|
name: 'children',
|
|
@@ -53,15 +53,9 @@ export const docs = {
|
|
|
53
53
|
type: 'React.RefObject<HTMLElement | null>',
|
|
54
54
|
description: 'External scroll container ref. When provided, auto-scroll and scroll-to-bottom target this element instead of the layout root. Use when the chat is embedded in a page where a parent element or the document body scrolls.',
|
|
55
55
|
},
|
|
56
|
-
{
|
|
57
|
-
name: 'density',
|
|
58
|
-
type: "'compact' | 'balanced' | 'spacious'",
|
|
59
|
-
description: 'Visual density: controls dock padding, message-area max-width and inline padding, and the height of the frosted glass blur layer.',
|
|
60
|
-
default: "'balanced'",
|
|
61
|
-
},
|
|
62
56
|
],
|
|
63
57
|
usage: {
|
|
64
|
-
description: 'ChatLayout is the layout shell for full-page chat interfaces. It renders messages in normal page flow and docks the composer to the bottom with a frosted glass blur layer.
|
|
58
|
+
description: 'ChatLayout is the layout shell for full-page chat interfaces. It renders messages in normal page flow and docks the composer to the bottom with a frosted glass blur layer. Density adapts automatically via container width observation. Use it to wrap ChatMessageList and ChatComposer for a complete chat experience with built-in auto-scroll and a scroll-to-bottom button.',
|
|
65
59
|
bestPractices: [
|
|
66
60
|
{
|
|
67
61
|
guidance: true,
|
|
@@ -117,21 +111,20 @@ export const docs = {
|
|
|
117
111
|
export const docsZh = {
|
|
118
112
|
name: 'ChatLayout',
|
|
119
113
|
displayName: 'Chat Layout',
|
|
120
|
-
description: '
|
|
114
|
+
description: '完整聊天界面的布局外壳。消息在页面中自然流动,编写器固定在底部,带有毛玻璃效果。通过容器宽度自动适配密度。',
|
|
121
115
|
propDescriptions: {
|
|
122
116
|
children: '消息内容,通常是 ChatMessageList。在页面中自然流动。',
|
|
123
117
|
composer: '编写器元素,通常是 ChatComposer。固定在底部,带有毛玻璃底座。',
|
|
124
118
|
emptyState: '子元素为空时显示的内容。',
|
|
125
119
|
scrollButton: '编写器上方的滚动到底部按钮。默认使用 ChatLayoutScrollButton。传入 null 隐藏。',
|
|
126
120
|
scrollRef: '外部滚动容器引用。提供时,自动滚动和滚动到底部将目标指向此元素。',
|
|
127
|
-
density: '视觉密度:控制底座内边距、消息区最大宽度和毛玻璃层高度。',
|
|
128
121
|
},
|
|
129
122
|
};
|
|
130
123
|
|
|
131
124
|
export const docsDense = {
|
|
132
125
|
name: 'ChatLayout',
|
|
133
126
|
displayName: 'Chat Layout',
|
|
134
|
-
description: 'layout shell for full chat; msgs in page flow, composer fixed bottom w/ frosted glass dock; density
|
|
127
|
+
description: 'layout shell for full chat; msgs in page flow, composer fixed bottom w/ frosted glass dock; auto density via container width; scrollRef delegates to parent/body',
|
|
135
128
|
usage: {
|
|
136
129
|
bestPractices: [
|
|
137
130
|
{guidance: true, description: 'Pass ChatMessageList as children and ChatComposer as composer prop for complete chat.'},
|
|
@@ -147,6 +140,5 @@ export const docsDense = {
|
|
|
147
140
|
emptyState: 'content when children empty',
|
|
148
141
|
scrollButton: 'scroll-to-bottom btn; defaults to ChatLayoutScrollButton; pass null to hide',
|
|
149
142
|
scrollRef: 'external scroll container ref; targets parent/body instead of layout root',
|
|
150
|
-
density: 'visual density; dock padding, message max-width, blur height',
|
|
151
143
|
},
|
|
152
144
|
};
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
4
4
|
import {act, render, screen} from '@testing-library/react';
|
|
5
|
-
import userEvent from '@testing-library/user-event';
|
|
6
5
|
import {ChatLayout} from './ChatLayout';
|
|
7
6
|
import {ChatMessageList} from './ChatMessageList';
|
|
8
7
|
import {ChatMessage} from './ChatMessage';
|
|
@@ -104,33 +103,6 @@ describe('ChatLayout', () => {
|
|
|
104
103
|
});
|
|
105
104
|
});
|
|
106
105
|
|
|
107
|
-
// ---------------------------------------------------------------------------
|
|
108
|
-
// Keyboard reachability of the default scroll-to-bottom button
|
|
109
|
-
//
|
|
110
|
-
// At rest the layout is neither scrolled up nor holding new messages, so the
|
|
111
|
-
// default ChatLayoutScrollButton renders in its hidden state. It is still in
|
|
112
|
-
// the DOM, and it is the first control in the dock — ahead of the composer.
|
|
113
|
-
// A control nobody can see must not be a tab stop: WCAG 2.2 SC 2.4.7 requires
|
|
114
|
-
// a visible focus indicator wherever focus can land, and the hidden pill paints
|
|
115
|
-
// nothing. `opacity: 0` and `pointer-events: none` do not remove an element
|
|
116
|
-
// from sequential focus navigation; only visibility/display/inert do.
|
|
117
|
-
// ---------------------------------------------------------------------------
|
|
118
|
-
|
|
119
|
-
describe('ChatLayout — default scroll button keyboard reachability', () => {
|
|
120
|
-
it('does not make the resting scroll-to-bottom button the first tab stop', async () => {
|
|
121
|
-
const user = userEvent.setup();
|
|
122
|
-
render(
|
|
123
|
-
<ChatLayout composer={<button type="button">Send</button>}>
|
|
124
|
-
<div>msg</div>
|
|
125
|
-
</ChatLayout>,
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
await user.tab();
|
|
129
|
-
|
|
130
|
-
expect(screen.getByRole('button', {name: 'Send'})).toHaveFocus();
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
106
|
// ---------------------------------------------------------------------------
|
|
135
107
|
// Self-scroll layout contract (#2573)
|
|
136
108
|
//
|
package/src/Chat/ChatLayout.tsx
CHANGED
|
@@ -268,25 +268,6 @@ function hasVisibleContent(children: ReactNode): boolean {
|
|
|
268
268
|
// Component
|
|
269
269
|
// =============================================================================
|
|
270
270
|
|
|
271
|
-
/**
|
|
272
|
-
* Layout shell for a full chat interface: messages in page flow, composer
|
|
273
|
-
* docked to the bottom behind a frosted glass layer, with auto-scroll and a
|
|
274
|
-
* scroll-to-bottom button wired in.
|
|
275
|
-
*
|
|
276
|
-
* @example
|
|
277
|
-
* ```
|
|
278
|
-
* <ChatLayout
|
|
279
|
-
* density="spacious"
|
|
280
|
-
* composer={<ChatComposer onSubmit={send} />}
|
|
281
|
-
* emptyState={<EmptyState title="No messages yet" />}>
|
|
282
|
-
* <ChatMessageList>
|
|
283
|
-
* <ChatMessage sender="assistant">
|
|
284
|
-
* <ChatMessageBubble>How can I help?</ChatMessageBubble>
|
|
285
|
-
* </ChatMessage>
|
|
286
|
-
* </ChatMessageList>
|
|
287
|
-
* </ChatLayout>
|
|
288
|
-
* ```
|
|
289
|
-
*/
|
|
290
271
|
export function ChatLayout({
|
|
291
272
|
children,
|
|
292
273
|
composer,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import {describe, it, expect} from 'vitest';
|
|
4
4
|
import {render, screen} from '@testing-library/react';
|
|
5
|
-
import userEvent from '@testing-library/user-event';
|
|
6
5
|
import {ChatLayoutScrollButton} from './ChatLayoutScrollButton';
|
|
7
6
|
|
|
8
7
|
describe('ChatLayoutScrollButton', () => {
|
|
@@ -53,34 +52,4 @@ describe('ChatLayoutScrollButton', () => {
|
|
|
53
52
|
expect(root).toHaveAttribute('data-custom', 'x');
|
|
54
53
|
expect(root).toHaveAttribute('id', 'scroll-1');
|
|
55
54
|
});
|
|
56
|
-
|
|
57
|
-
// The hidden state paints nothing, so focus landing on it would have no
|
|
58
|
-
// visible indicator (WCAG 2.2 SC 2.4.7). `opacity: 0` and
|
|
59
|
-
// `pointer-events: none` suppress paint and the pointer but leave the button
|
|
60
|
-
// in sequential focus navigation, so the hidden state must also stop being
|
|
61
|
-
// focusable — without costing the visible state its keyboard access.
|
|
62
|
-
it('is keyboard reachable while visible', async () => {
|
|
63
|
-
const user = userEvent.setup();
|
|
64
|
-
render(<ChatLayoutScrollButton isVisible onClick={() => {}} />);
|
|
65
|
-
|
|
66
|
-
await user.tab();
|
|
67
|
-
|
|
68
|
-
expect(
|
|
69
|
-
screen.getByRole('button', {name: 'Scroll to bottom'}),
|
|
70
|
-
).toHaveFocus();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('is not keyboard reachable while hidden', async () => {
|
|
74
|
-
const user = userEvent.setup();
|
|
75
|
-
render(
|
|
76
|
-
<>
|
|
77
|
-
<ChatLayoutScrollButton isVisible={false} onClick={() => {}} />
|
|
78
|
-
<button type="button">After</button>
|
|
79
|
-
</>,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
await user.tab();
|
|
83
|
-
|
|
84
|
-
expect(screen.getByRole('button', {name: 'After'})).toHaveFocus();
|
|
85
|
-
});
|
|
86
55
|
});
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
spacingVars,
|
|
24
24
|
radiusVars,
|
|
25
25
|
shadowVars,
|
|
26
|
-
sizeVars,
|
|
27
26
|
durationVars,
|
|
28
27
|
easeVars,
|
|
29
28
|
} from '../theme/tokens.stylex';
|
|
@@ -68,14 +67,8 @@ const styles = stylex.create({
|
|
|
68
67
|
borderRadius: radiusVars['--radius-full'],
|
|
69
68
|
backgroundColor: colorVars['--color-background-popover'],
|
|
70
69
|
boxShadow: shadowVars['--shadow-med'],
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// that retunes the element scale.
|
|
74
|
-
height: sizeVars['--size-element-md'],
|
|
75
|
-
// `visibility` rides the same transition so the fade-out still plays:
|
|
76
|
-
// it flips to `visible` immediately on the way in and only at the end
|
|
77
|
-
// of the duration on the way out.
|
|
78
|
-
transitionProperty: 'opacity, transform, max-width, visibility',
|
|
70
|
+
height: '32px',
|
|
71
|
+
transitionProperty: 'opacity, transform, max-width',
|
|
79
72
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
80
73
|
transitionDuration: {
|
|
81
74
|
default: durationVars['--duration-fast-max'],
|
|
@@ -85,19 +78,14 @@ const styles = stylex.create({
|
|
|
85
78
|
hidden: {
|
|
86
79
|
opacity: 0,
|
|
87
80
|
pointerEvents: 'none',
|
|
88
|
-
|
|
89
|
-
// visible indicator (WCAG 2.2 SC 2.4.7). `opacity` and `pointer-events`
|
|
90
|
-
// leave the button in sequential focus navigation; `visibility` removes it.
|
|
91
|
-
visibility: 'hidden',
|
|
92
|
-
maxWidth: sizeVars['--size-element-md'],
|
|
81
|
+
maxWidth: '32px',
|
|
93
82
|
},
|
|
94
83
|
visible: {
|
|
95
84
|
opacity: 1,
|
|
96
85
|
pointerEvents: 'auto',
|
|
97
|
-
visibility: 'visible',
|
|
98
86
|
},
|
|
99
87
|
collapsed: {
|
|
100
|
-
maxWidth:
|
|
88
|
+
maxWidth: '32px',
|
|
101
89
|
},
|
|
102
90
|
expanded: {
|
|
103
91
|
maxWidth: '200px',
|
package/src/index.ts
CHANGED
package/src/tailwind-theme.css
CHANGED
|
@@ -182,6 +182,12 @@
|
|
|
182
182
|
--text-4xl: var(--font-size-4xl);
|
|
183
183
|
--text-5xl: var(--font-size-5xl);
|
|
184
184
|
|
|
185
|
+
/* --- Font weights --- */
|
|
186
|
+
--font-weight-normal: var(--font-weight-normal);
|
|
187
|
+
--font-weight-medium: var(--font-weight-medium);
|
|
188
|
+
--font-weight-semibold: var(--font-weight-semibold);
|
|
189
|
+
--font-weight-bold: var(--font-weight-bold);
|
|
190
|
+
|
|
185
191
|
/* =========================================================================
|
|
186
192
|
* Border radius
|
|
187
193
|
*
|
package/dist/Timer/Timer.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { BaseProps } from '../BaseProps';
|
|
2
|
-
import type { TextColor, TextSize, TextType, TextWeight } from '../theme/types';
|
|
3
|
-
export type TimerFormat = 'elapsed' | 'clock';
|
|
4
|
-
export interface TimerProps extends Omit<BaseProps<HTMLTimeElement>, 'dateTime'> {
|
|
5
|
-
/** Ref forwarded to the rendered `<time>` element. */
|
|
6
|
-
ref?: React.Ref<HTMLTimeElement>;
|
|
7
|
-
/**
|
|
8
|
-
* Unix time in milliseconds when the measured operation began. Omit it to
|
|
9
|
-
* start counting from this Timer's mount.
|
|
10
|
-
*/
|
|
11
|
-
startTime?: number;
|
|
12
|
-
/**
|
|
13
|
-
* Standard duration representation.
|
|
14
|
-
* @default 'elapsed'
|
|
15
|
-
*/
|
|
16
|
-
format?: TimerFormat;
|
|
17
|
-
/**
|
|
18
|
-
* Semantic text type. Matches Timestamp typography behavior.
|
|
19
|
-
* @default 'supporting'
|
|
20
|
-
*/
|
|
21
|
-
type?: TextType;
|
|
22
|
-
/** Explicit font size override. Overrides the size from `type`. */
|
|
23
|
-
size?: TextSize;
|
|
24
|
-
/**
|
|
25
|
-
* Text color.
|
|
26
|
-
* @default 'secondary'
|
|
27
|
-
*/
|
|
28
|
-
color?: TextColor;
|
|
29
|
-
/** Font weight override. */
|
|
30
|
-
weight?: TextWeight;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Displays a standardized elapsed duration without scheduling React tick renders.
|
|
34
|
-
*
|
|
35
|
-
* Timer writes changing text and its ISO 8601 duration directly to the owned
|
|
36
|
-
* `<time>` node. Use `elapsed` for compact duration text or `clock` for a
|
|
37
|
-
* stopwatch-like reading.
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```
|
|
41
|
-
* <Timer />
|
|
42
|
-
* <Timer format="clock" />
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export declare function Timer({ startTime, format, type, size, color, weight, ref, xstyle, className, style, ...rest }: TimerProps): import("react").JSX.Element;
|
|
46
|
-
export declare namespace Timer {
|
|
47
|
-
var displayName: string;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=Timer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/Timer/Timer.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAsB9E,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AA8E9C,MAAM,WAAW,UAAW,SAAQ,IAAI,CACtC,SAAS,CAAC,eAAe,CAAC,EAC1B,UAAU,CACX;IACC,sDAAsD;IACtD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,mEAAmE;IACnE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,MAAkB,EAClB,IAAmB,EACnB,IAAI,EACJ,KAAmB,EACnB,MAAM,EACN,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,UAAU,+BA0EZ;yBAtFe,KAAK"}
|
package/dist/Timer/Timer.js
DELETED
|
@@ -1,158 +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
|
-
import { useEffect, useRef, useState } from 'react';
|
|
20
|
-
import * as stylex from '@stylexjs/stylex';
|
|
21
|
-
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
22
|
-
import { Text } from "../Text/index.js";
|
|
23
|
-
import { mergeProps } from "../utils/index.js";
|
|
24
|
-
import { themeProps } from "../utils/themeProps.js";
|
|
25
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
26
|
-
const ONE_SECOND_MS = 1000;
|
|
27
|
-
const ONE_MINUTE_MS = 60 * ONE_SECOND_MS;
|
|
28
|
-
const ONE_HOUR_SECONDS = 60 * 60;
|
|
29
|
-
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
30
|
-
function pad(value) {
|
|
31
|
-
return String(value).padStart(2, '0');
|
|
32
|
-
}
|
|
33
|
-
function resolveFormat(format) {
|
|
34
|
-
return format === 'clock' ? 'clock' : 'elapsed';
|
|
35
|
-
}
|
|
36
|
-
function getElapsedMilliseconds(now, startTime) {
|
|
37
|
-
return Math.max(0, now - startTime);
|
|
38
|
-
}
|
|
39
|
-
function getPresentation(elapsedMilliseconds, format) {
|
|
40
|
-
const elapsedSeconds = Math.floor(elapsedMilliseconds / ONE_SECOND_MS);
|
|
41
|
-
if (format === 'clock') {
|
|
42
|
-
const hours = Math.floor(elapsedSeconds / ONE_HOUR_SECONDS);
|
|
43
|
-
const minutes = Math.floor(elapsedSeconds % ONE_HOUR_SECONDS / 60);
|
|
44
|
-
const seconds = elapsedSeconds % 60;
|
|
45
|
-
return {
|
|
46
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
47
|
-
text: hours > 0 ? `${String(hours)}:${pad(minutes)}:${pad(seconds)}` : `${String(minutes)}:${pad(seconds)}`
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
if (elapsedSeconds < 60) {
|
|
51
|
-
return {
|
|
52
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
53
|
-
text: `${String(elapsedSeconds)}s`
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
const totalMinutes = Math.floor(elapsedSeconds / 60);
|
|
57
|
-
if (totalMinutes < 60) {
|
|
58
|
-
return {
|
|
59
|
-
dateTime: `PT${elapsedSeconds}S`,
|
|
60
|
-
text: `${String(totalMinutes)}m ${pad(elapsedSeconds % 60)}s`
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const representedSeconds = totalMinutes * 60;
|
|
64
|
-
return {
|
|
65
|
-
dateTime: `PT${representedSeconds}S`,
|
|
66
|
-
text: `${String(Math.floor(totalMinutes / 60))}h ${pad(totalMinutes % 60)}m`
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
function getMillisecondsUntilNextChange(now, startTime, elapsedMilliseconds, format) {
|
|
70
|
-
if (now < startTime) {
|
|
71
|
-
return Math.min(startTime - now + ONE_SECOND_MS, MAX_TIMEOUT_MS);
|
|
72
|
-
}
|
|
73
|
-
const precision = format === 'elapsed' && elapsedMilliseconds >= ONE_HOUR_SECONDS * ONE_SECOND_MS ? ONE_MINUTE_MS : ONE_SECOND_MS;
|
|
74
|
-
return precision - elapsedMilliseconds % precision;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Displays a standardized elapsed duration without scheduling React tick renders.
|
|
78
|
-
*
|
|
79
|
-
* Timer writes changing text and its ISO 8601 duration directly to the owned
|
|
80
|
-
* `<time>` node. Use `elapsed` for compact duration text or `clock` for a
|
|
81
|
-
* stopwatch-like reading.
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```
|
|
85
|
-
* <Timer />
|
|
86
|
-
* <Timer format="clock" />
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
export function Timer({
|
|
90
|
-
startTime,
|
|
91
|
-
format = 'elapsed',
|
|
92
|
-
type = 'supporting',
|
|
93
|
-
size,
|
|
94
|
-
color = 'secondary',
|
|
95
|
-
weight,
|
|
96
|
-
ref,
|
|
97
|
-
xstyle,
|
|
98
|
-
className,
|
|
99
|
-
style,
|
|
100
|
-
...rest
|
|
101
|
-
}) {
|
|
102
|
-
const [mountTime] = useState(() => Date.now());
|
|
103
|
-
const timerRef = useRef(null);
|
|
104
|
-
const mergedRef = useMergedRefs(ref, timerRef);
|
|
105
|
-
const resolvedFormat = resolveFormat(format);
|
|
106
|
-
const initialPresentation = getPresentation(0, resolvedFormat);
|
|
107
|
-
useEffect(() => {
|
|
108
|
-
const resolvedStartTime = startTime !== undefined && Number.isFinite(startTime) ? startTime : mountTime;
|
|
109
|
-
let timeoutID;
|
|
110
|
-
let previousDateTime;
|
|
111
|
-
let previousText;
|
|
112
|
-
const tick = () => {
|
|
113
|
-
const now = Date.now();
|
|
114
|
-
const elapsedMilliseconds = getElapsedMilliseconds(now, resolvedStartTime);
|
|
115
|
-
const presentation = getPresentation(elapsedMilliseconds, resolvedFormat);
|
|
116
|
-
const node = timerRef.current;
|
|
117
|
-
if (node != null) {
|
|
118
|
-
if (presentation.text !== previousText) {
|
|
119
|
-
node.textContent = presentation.text;
|
|
120
|
-
previousText = presentation.text;
|
|
121
|
-
}
|
|
122
|
-
if (presentation.dateTime !== previousDateTime) {
|
|
123
|
-
node.dateTime = presentation.dateTime;
|
|
124
|
-
previousDateTime = presentation.dateTime;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
timeoutID = setTimeout(tick, getMillisecondsUntilNextChange(now, resolvedStartTime, elapsedMilliseconds, resolvedFormat));
|
|
128
|
-
};
|
|
129
|
-
tick();
|
|
130
|
-
return () => {
|
|
131
|
-
if (timeoutID !== undefined) {
|
|
132
|
-
clearTimeout(timeoutID);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
}, [mountTime, resolvedFormat, startTime]);
|
|
136
|
-
const timerProps = mergeProps(themeProps('timer'), {
|
|
137
|
-
className,
|
|
138
|
-
style
|
|
139
|
-
});
|
|
140
|
-
return /*#__PURE__*/_jsx(Text, {
|
|
141
|
-
type: type,
|
|
142
|
-
size: size,
|
|
143
|
-
color: color,
|
|
144
|
-
weight: weight,
|
|
145
|
-
xstyle: xstyle,
|
|
146
|
-
...timerProps,
|
|
147
|
-
children: /*#__PURE__*/_jsx("time", {
|
|
148
|
-
...rest,
|
|
149
|
-
ref: mergedRef,
|
|
150
|
-
dateTime: "PT0S",
|
|
151
|
-
...{
|
|
152
|
-
className: "x1heor9g xt0psk2 xjb2p0i x1qlqyl8 x1j61x8r xss6m8b x1pd3egz x15bjb6t"
|
|
153
|
-
},
|
|
154
|
-
children: initialPresentation.text
|
|
155
|
-
})
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
Timer.displayName = 'Timer';
|