1
1
import { Identifier , ItemStack } from 'deepslate'
2
2
import type { ComponentChild , ComponentChildren } from 'preact'
3
3
import { useEffect , useRef , useState } from 'preact/hooks'
4
- import { safeJsonParse } from '../../Utils.js'
4
+ import { clamp , safeJsonParse } from '../../Utils.js'
5
5
import { ItemDisplay } from '../ItemDisplay.jsx'
6
6
import { TextComponent } from '../TextComponent.jsx'
7
7
import type { PreviewProps } from './index.js'
@@ -62,22 +62,20 @@ function DialogBody({ body }: { body: any }) {
62
62
{ body ?. map ( ( b : any ) => {
63
63
const type = b . type ?. replace ( / ^ m i n e c r a f t : / , '' )
64
64
if ( type === 'plain_message' ) {
65
- // TODO: make this text wrap
66
- return < div style = { `max-width: ${ px ( b . width ?? 200 ) } ; padding: ${ px ( 4 ) } ` } >
65
+ return < div class = "dialog-body" style = { `max-width: ${ px ( clamp ( b . width ?? 200 , 1 , 1024 ) ) } ; padding: ${ px ( 4 ) } ` } >
67
66
< TextComponent component = { b . contents } />
68
67
</ div >
69
68
}
70
69
if ( type == 'item' ) {
71
70
// TODO: add item components
72
71
const item = new ItemStack ( Identifier . parse ( b . item ?. id ?? 'air' ) , b . show_decorations ? ( b . item ?. count ?? 1 ) : 1 )
73
- console . log ( item )
74
72
return < div style = { `display: flex; gap: ${ px ( 2 ) } ; align-items: center; gap: ${ px ( 4 ) } ` } >
75
- < div style = { `width: ${ px ( b . width ?? 16 ) } ; height: ${ px ( b . height ?? 16 ) } ` } >
73
+ < div style = { `width: ${ px ( clamp ( b . width ?? 16 , 1 , 256 ) ) } ; height: ${ px ( clamp ( b . height ?? 16 , 1 , 256 ) ) } ` } >
76
74
< div style = { `width: ${ px ( 16 ) } ; height: ${ px ( 16 ) } ` } >
77
75
< ItemDisplay item = { item } tooltip = { b . show_tooltip ?? true } />
78
76
</ div >
79
77
</ div >
80
- { b . description && < div style = { `max-width: ${ px ( b . description . width ?? 200 ) } ;` } >
78
+ { b . description && < div style = { `max-width: ${ px ( clamp ( b . description . width ?? 200 , 1 , 1024 ) ) } ;` } >
81
79
< TextComponent component = { b . description . contents } />
82
80
</ div > }
83
81
</ div >
@@ -121,7 +119,7 @@ function DialogContent({ dialog }: { dialog: any }) {
121
119
if ( type === 'multi_action_input_form' ) {
122
120
return < >
123
121
{ dialog . inputs ?. map ( ( i : any ) => < InputControl input = { i } /> ) }
124
- < ColumnsGrid columns = { 2 } >
122
+ < ColumnsGrid columns = { dialog . columns ?? 2 } >
125
123
{ dialog . actions ?. map ( ( a : any ) =>
126
124
< Button label = { a . label } width = { a . width ?? 150 } tooltip = { a . tooltip } />
127
125
) ?? [ ] }
@@ -186,6 +184,7 @@ function DialogFooter({ dialog }: { dialog: any }) {
186
184
187
185
function InputControl ( { input } : { input : any } ) {
188
186
const type = input . type ?. replace ( / ^ m i n e c r a f t : / , '' )
187
+ // TODO: make interactive
189
188
190
189
if ( type === 'boolean' ) {
191
190
return < div style = { `display: flex; gap: ${ px ( 4 ) } ; align-items: center;` } >
@@ -195,8 +194,9 @@ function InputControl({ input }: { input: any }) {
195
194
}
196
195
197
196
if ( type === 'number_range' ) {
198
- const label = { translate : input . label_format ?? 'options.generic_value' , with : [ input . label ?? '' , input . start ?? 0 ] }
199
- return < div class = "dialog-slider" style = { `width: ${ px ( input . width ?? 200 ) } ; height: ${ px ( 20 ) } ;` } >
197
+ const initial = input . initial ?? ( ( ( input . start ?? 0 ) + ( input . end ?? 0 ) ) / 2 )
198
+ const label = { translate : input . label_format ?? 'options.generic_value' , with : [ input . label ?? '' , initial ] }
199
+ return < div class = "dialog-slider" style = { `width: ${ px ( clamp ( input . width ?? 200 , 1 , 1024 ) ) } ; height: ${ px ( 20 ) } ;` } >
200
200
< div class = "dialog-slider-track" > </ div >
201
201
< div class = "dialog-slider-handle" > </ div >
202
202
< div class = "dialog-slider-text" >
@@ -209,13 +209,18 @@ function InputControl({ input }: { input: any }) {
209
209
const initial = input . options ?. find ( ( o : any ) => o . initial ) ?? input . options ?. [ 0 ]
210
210
const initialLabel = typeof initial === 'string' ? initial : initial ?. display ?? initial ?. id ?? ''
211
211
const label = input . label_visible === false ? initialLabel : { translate : 'options.generic_value' , with : [ input . label ?? '' , initialLabel ] }
212
- return < Button label = { label } width = { input . width ?? 200 } />
212
+ return < Button label = { label } width = { clamp ( input . width ?? 200 , 1 , 1024 ) } />
213
213
}
214
214
215
215
if ( type === 'text' ) {
216
+ const height = input . multiline
217
+ ? ( input . multiline . height
218
+ ? clamp ( input . multiline . height , 1 , 512 )
219
+ : ( 9 * Math . max ( input . multiline . max_lines ?? 4 , 1 ) + 8 ) )
220
+ : 20
216
221
return < div style = { `display: flex; flex-direction: column; gap: ${ px ( 4 ) } ;` } >
217
222
{ input . label_visible !== false && < TextComponent component = { input . label } /> }
218
- < div class = "dialog-edit-box" style = { `width: ${ px ( input . width ?? 200 ) } ; height: ${ px ( 20 ) } ;` } >
223
+ < div class = "dialog-edit-box" style = { `width: ${ px ( clamp ( input . width ?? 200 , 1 , 1024 ) ) } ; height: ${ px ( height ) } ;` } >
219
224
{ input . initial && < TextComponent component = { input . initial } /> }
220
225
</ div >
221
226
</ div >
@@ -233,7 +238,7 @@ function ColumnsGrid({ columns, children }: ColumnsGridProps) {
233
238
const gridCount = Math . floor ( totalCount / columns ) * columns
234
239
return < div style = { `padding-top: ${ px ( 4 ) } ; display: grid; grid-template-columns: repeat(${ columns } , minmax(0, 1fr)); gap: ${ px ( 2 ) } ; justify-content: center;` } >
235
240
{ children . slice ( 0 , gridCount ) }
236
- { totalCount > gridCount && < div style = { `grid-column: span ${ columns } ; display: flex; gap: ${ px ( 2 ) } ; justify-content: center; padding-top: ${ px ( 2 ) } /* MC-297977 */; ` } >
241
+ { totalCount > gridCount && < div style = { `grid-column: span ${ columns } ; display: flex; gap: ${ px ( 2 ) } ; justify-content: center;` } >
237
242
{ children . slice ( gridCount ) }
238
243
</ div > }
239
244
</ div >
@@ -246,7 +251,7 @@ interface ButtonProps {
246
251
}
247
252
function Button ( { label, width, tooltip } : ButtonProps ) {
248
253
return < WithTooltip tooltip = { tooltip } >
249
- < div class = "dialog-button" style = { `width: ${ px ( width ) } ; height: ${ px ( 20 ) } ;` } >
254
+ < div class = "dialog-button" style = { `width: ${ px ( clamp ( width , 1 , 1024 ) ) } ; height: ${ px ( 20 ) } ;` } >
250
255
< TextComponent component = { label } oneline />
251
256
</ div >
252
257
</ WithTooltip >
0 commit comments