1+ import { z } from 'zod' ;
2+
13import type { AdaptiveCard } from '../types' ;
24
35export type AdaptiveContainerStyle = 'default' | 'accent' | 'good' | 'warning' | 'attention' ;
@@ -12,6 +14,11 @@ interface FactEntry {
1214
1315const relativeTimeFormatter = new Intl . RelativeTimeFormat ( 'en' , { numeric : 'auto' } ) ;
1416
17+ export const IsoTimestampSchema = z . union ( [
18+ z . string ( ) . datetime ( { offset : true } ) ,
19+ z . string ( ) . datetime ( ) ,
20+ ] ) ;
21+
1522function toCategoryTextColor ( style : AdaptiveContainerStyle ) : AdaptiveTextColor {
1623 switch ( style ) {
1724 case 'good' :
@@ -31,12 +38,7 @@ export function toTextColor(style: AdaptiveContainerStyle): AdaptiveTextColor {
3138 return toCategoryTextColor ( style ) ;
3239}
3340
34- export function createCardFrame (
35- style : AdaptiveContainerStyle ,
36- items : Array < Record < string , unknown > > ,
37- ) : Record < string , unknown > {
38- void style ;
39-
41+ export function createCardFrame ( items : Array < Record < string , unknown > > ) : Record < string , unknown > {
4042 return {
4143 type : 'ColumnSet' ,
4244 columns : [
@@ -50,122 +52,6 @@ export function createCardFrame(
5052 } ;
5153}
5254
53- export interface HeaderContainerOptions {
54- topLine ?: string ;
55- extraItems ?: Array < Record < string , unknown > > ;
56- actions ?: Array < Record < string , unknown > > ;
57- }
58-
59- export function createHeaderContainer (
60- title : string ,
61- style : AdaptiveContainerStyle ,
62- subtitle ?: string ,
63- category ?: string ,
64- badge ?: string ,
65- options ?: HeaderContainerOptions ,
66- ) : Record < string , unknown > {
67- const contentItems : Array < Record < string , unknown > > = [ ] ;
68-
69- if ( options ?. topLine ) {
70- contentItems . push ( {
71- type : 'TextBlock' ,
72- text : options . topLine ,
73- size : 'Small' ,
74- isSubtle : true ,
75- spacing : 'None' ,
76- } ) ;
77- }
78-
79- if ( category || badge ) {
80- const columns : Array < Record < string , unknown > > = [ ] ;
81-
82- if ( category ) {
83- columns . push ( {
84- type : 'Column' ,
85- width : 'stretch' ,
86- items : [
87- {
88- type : 'TextBlock' ,
89- text : category ,
90- size : 'Small' ,
91- weight : 'Bolder' ,
92- color : toCategoryTextColor ( style ) ,
93- wrap : true ,
94- spacing : 'None' ,
95- } ,
96- ] ,
97- } ) ;
98- } else {
99- columns . push ( {
100- type : 'Column' ,
101- width : 'stretch' ,
102- items : [ { type : 'TextBlock' , text : ' ' , spacing : 'None' } ] ,
103- } ) ;
104- }
105-
106- if ( badge ) {
107- columns . push ( {
108- type : 'Column' ,
109- width : 'auto' ,
110- items : [
111- {
112- type : 'TextBlock' ,
113- text : badge ,
114- size : 'Small' ,
115- isSubtle : true ,
116- horizontalAlignment : 'Right' ,
117- wrap : false ,
118- spacing : 'None' ,
119- } ,
120- ] ,
121- } ) ;
122- }
123-
124- contentItems . push ( {
125- type : 'ColumnSet' ,
126- spacing : 'None' ,
127- columns,
128- } ) ;
129- }
130-
131- contentItems . push ( {
132- type : 'TextBlock' ,
133- text : title ,
134- weight : 'Bolder' ,
135- wrap : true ,
136- size : 'Large' ,
137- spacing : category || badge ? 'Small' : 'None' ,
138- } ) ;
139-
140- if ( subtitle ) {
141- contentItems . push ( {
142- type : 'TextBlock' ,
143- text : subtitle ,
144- size : 'Small' ,
145- isSubtle : true ,
146- wrap : true ,
147- spacing : 'None' ,
148- } ) ;
149- }
150-
151- if ( options ?. extraItems ) {
152- contentItems . push ( ...options . extraItems ) ;
153- }
154-
155- if ( options ?. actions && options . actions . length > 0 ) {
156- contentItems . push ( {
157- type : 'ActionSet' ,
158- spacing : 'Medium' ,
159- actions : options . actions ,
160- } ) ;
161- }
162-
163- return {
164- type : 'Container' ,
165- items : contentItems ,
166- } ;
167- }
168-
16955export function createFactSet ( entries : FactEntry [ ] ) : Record < string , unknown > | null {
17056 const facts = entries
17157 . filter ( ( entry ) => entry . value !== undefined && entry . value !== null && entry . value !== '' )
0 commit comments