@fugood/bricks-project 2.24.0-beta.36 → 2.24.0-beta.39

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 (83) hide show
  1. package/compile/index.ts +14 -6
  2. package/package.json +3 -3
  3. package/tools/preview-main.mjs +129 -2
  4. package/tools/preview.ts +29 -1
  5. package/types/bricks/Camera.ts +10 -5
  6. package/types/bricks/Chart.ts +5 -2
  7. package/types/bricks/GenerativeMedia.ts +20 -7
  8. package/types/bricks/Icon.ts +1 -0
  9. package/types/bricks/Image.ts +2 -1
  10. package/types/bricks/Items.ts +17 -6
  11. package/types/bricks/Lottie.ts +7 -2
  12. package/types/bricks/Maps.ts +8 -3
  13. package/types/bricks/QrCode.ts +1 -0
  14. package/types/bricks/Rect.ts +39 -3
  15. package/types/bricks/RichText.ts +1 -0
  16. package/types/bricks/Rive.ts +15 -8
  17. package/types/bricks/Slideshow.ts +12 -5
  18. package/types/bricks/Svg.ts +1 -0
  19. package/types/bricks/Text.ts +1 -0
  20. package/types/bricks/TextInput.ts +8 -5
  21. package/types/bricks/Video.ts +3 -2
  22. package/types/bricks/VideoStreaming.ts +1 -0
  23. package/types/bricks/WebRtcStream.ts +1 -0
  24. package/types/bricks/WebView.ts +4 -3
  25. package/types/common.ts +10 -8
  26. package/types/generators/AlarmClock.ts +7 -4
  27. package/types/generators/Assistant.ts +7 -4
  28. package/types/generators/BleCentral.ts +14 -5
  29. package/types/generators/BlePeripheral.ts +1 -0
  30. package/types/generators/CanvasMap.ts +2 -1
  31. package/types/generators/CastlesPay.ts +7 -2
  32. package/types/generators/DataBank.ts +8 -3
  33. package/types/generators/File.ts +41 -14
  34. package/types/generators/GraphQl.ts +4 -1
  35. package/types/generators/Http.ts +1 -0
  36. package/types/generators/HttpServer.ts +9 -4
  37. package/types/generators/Information.ts +2 -1
  38. package/types/generators/Intent.ts +3 -2
  39. package/types/generators/Iterator.ts +5 -4
  40. package/types/generators/Keyboard.ts +4 -3
  41. package/types/generators/LlmAnthropicCompat.ts +11 -4
  42. package/types/generators/LlmAppleBuiltin.ts +8 -3
  43. package/types/generators/LlmGgml.ts +12 -5
  44. package/types/generators/LlmMediaTekNeuroPilot.ts +11 -4
  45. package/types/generators/LlmMlx.ts +11 -4
  46. package/types/generators/LlmOnnx.ts +11 -4
  47. package/types/generators/LlmOpenAiCompat.ts +11 -4
  48. package/types/generators/LlmQualcommAiEngine.ts +9 -4
  49. package/types/generators/Mcp.ts +38 -15
  50. package/types/generators/McpServer.ts +15 -6
  51. package/types/generators/MediaFlow.ts +8 -3
  52. package/types/generators/MqttBroker.ts +14 -5
  53. package/types/generators/MqttClient.ts +3 -2
  54. package/types/generators/Question.ts +2 -1
  55. package/types/generators/RealtimeTranscription.ts +22 -7
  56. package/types/generators/RerankerGgml.ts +5 -2
  57. package/types/generators/SerialPort.ts +7 -2
  58. package/types/generators/SoundPlayer.ts +4 -1
  59. package/types/generators/SoundRecorder.ts +3 -2
  60. package/types/generators/SpeechToTextGgml.ts +8 -3
  61. package/types/generators/SpeechToTextOnnx.ts +5 -2
  62. package/types/generators/SpeechToTextPlatform.ts +7 -2
  63. package/types/generators/SqLite.ts +5 -2
  64. package/types/generators/Step.ts +2 -1
  65. package/types/generators/SttAppleBuiltin.ts +5 -2
  66. package/types/generators/Tcp.ts +3 -2
  67. package/types/generators/TcpServer.ts +8 -5
  68. package/types/generators/TextToSpeechAppleBuiltin.ts +5 -2
  69. package/types/generators/TextToSpeechGgml.ts +5 -2
  70. package/types/generators/TextToSpeechOnnx.ts +5 -2
  71. package/types/generators/TextToSpeechOpenAiLike.ts +5 -2
  72. package/types/generators/ThermalPrinter.ts +2 -1
  73. package/types/generators/Tick.ts +3 -2
  74. package/types/generators/Udp.ts +3 -2
  75. package/types/generators/VadGgml.ts +8 -3
  76. package/types/generators/VadOnnx.ts +6 -3
  77. package/types/generators/VadTraditional.ts +8 -3
  78. package/types/generators/VectorStore.ts +2 -1
  79. package/types/generators/Watchdog.ts +3 -2
  80. package/types/generators/WebCrawler.ts +1 -0
  81. package/types/generators/WebRtc.ts +8 -3
  82. package/types/generators/WebSocket.ts +2 -1
  83. package/utils/event-props.ts +833 -1059
package/compile/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  /* eslint-disable no-underscore-dangle -- Uses __typename, __actionName, etc. for type system */
2
+ import camelCase from 'lodash/camelCase'
3
+ import upperFirst from 'lodash/upperFirst'
2
4
  import snakeCase from 'lodash/snakeCase'
3
5
  import omit from 'lodash/omit'
4
6
  import { parse as parseAST } from 'acorn'
@@ -110,14 +112,20 @@ const compileScriptCalculationCode = (code = '') => {
110
112
  }
111
113
  }
112
114
 
115
+ const getTemplateName = (key: string) =>
116
+ upperFirst(camelCase(key.replace(/^(BRICK|GENERATOR)_/, '')))
117
+
113
118
  const compileEventActionValue = (templateKey, eventKey, value, errorReference) => {
114
- const tmplEventProperties = templateEventPropsMap[templateKey]
119
+ const tmplEventProperties = templateEventPropsMap[getTemplateName(templateKey)]
115
120
  const props = tmplEventProperties?.[eventKey]
116
121
  if (!props) return compileProperty(value, errorReference)
117
- if (props.includes(value)) return value
118
- if (typeof value === 'string' && value?.startsWith(templateKey)) {
122
+ if (typeof value === 'string' && value in props) {
123
+ const expectedType = props[value]
124
+ if (expectedType) return value
125
+ }
126
+ if (typeof value === 'string' && /^(BRICK|GENERATOR)_/.test(value)) {
119
127
  console.warn(
120
- `[Warning] Value start with template key but there is no event property: ${value} ${errorReference}`,
128
+ `[Warning] Event property "${value}" is not compatible with event "${eventKey}" of ${templateKey} ${errorReference}`,
121
129
  )
122
130
  }
123
131
  return compileProperty(value, errorReference)
@@ -188,7 +196,7 @@ const compileEvents = (
188
196
  if (!handlerKey) throw new Error(`Invalid handler: ${handler} ${errorReference}`)
189
197
 
190
198
  const parameterList: Array<object> = []
191
- if (Object.hasOwn(action, 'params')) {
199
+ if (Object.prototype.hasOwnProperty.call(action, 'params')) {
192
200
  const actionDef = action as ActionWithParams
193
201
  ;(actionDef.params || []).forEach(({ input, value, mapping }) => {
194
202
  const param = {
@@ -201,7 +209,7 @@ const compileEvents = (
201
209
  if (mapping) param[camelCase ? 'resultDataMapping' : 'result_data_mapping'] = true
202
210
  parameterList.push(param)
203
211
  })
204
- } else if (Object.hasOwn(action, 'dataParams')) {
212
+ } else if (Object.prototype.hasOwnProperty.call(action, 'dataParams')) {
205
213
  const actionDef = action as ActionWithDataParams
206
214
  ;(actionDef.dataParams || []).forEach(({ input, value, mapping }) => {
207
215
  if (!input) return
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@fugood/bricks-project",
3
- "version": "2.24.0-beta.36",
3
+ "version": "2.24.0-beta.39",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "typecheck": "tsc --noEmit",
7
7
  "build": "bun scripts/build.js"
8
8
  },
9
9
  "dependencies": {
10
- "@fugood/bricks-cli": "^2.24.0-beta.35",
10
+ "@fugood/bricks-cli": "^2.24.0-beta.39",
11
11
  "@huggingface/gguf": "^0.3.2",
12
12
  "@iarna/toml": "^3.0.0",
13
13
  "@modelcontextprotocol/sdk": "^1.15.0",
@@ -24,5 +24,5 @@
24
24
  "peerDependencies": {
25
25
  "oxfmt": "^0.36.0"
26
26
  },
27
- "gitHead": "1146a2d19b4f6efca4055e6c788f5ad50658cc40"
27
+ "gitHead": "f74322101339ff5efb796a89fcd8f0a52c2465ce"
28
28
  }
@@ -2,6 +2,7 @@
2
2
  import { app, BrowserWindow } from 'electron'
3
3
  import { readFile, writeFile } from 'fs/promises'
4
4
  import { watchFile } from 'fs'
5
+ import { createServer } from 'http'
5
6
  import { parseArgs } from 'util'
6
7
  import * as TOON from '@toon-format/toon'
7
8
 
@@ -14,6 +15,7 @@ const { values } = parseArgs({
14
15
  'test-id': { type: 'string' },
15
16
  'test-title-like': { type: 'string' },
16
17
  'no-keep-open': { type: 'boolean' },
18
+ 'cdp-port': { type: 'string' },
17
19
  },
18
20
  strict: true,
19
21
  allowPositionals: true,
@@ -70,6 +72,127 @@ const previewUrlMap = {
70
72
  const previewUrl = previewUrlMap[stage]
71
73
  if (!previewUrl) throw new Error(`Invalid BRICKS_STAGE: ${stage}`)
72
74
 
75
+ // --- CDP WebSocket Server ---
76
+ // Bridges external CDP clients to the preview's postMessage-based CDP bridge.
77
+ // Usage: --cdp-port 9222
78
+
79
+ const startCdpServer = async (mainWindow, port) => {
80
+ const { WebSocketServer } = await import('ws')
81
+ const clients = new Set()
82
+
83
+ // Inject a listener in the preview that forwards CDP responses/events via console
84
+ const injectCdpRelay = () =>
85
+ mainWindow.webContents.executeJavaScript(`
86
+ if (!window.__cdpRelayInstalled) {
87
+ window.__cdpRelayInstalled = true
88
+ window.addEventListener('message', (evt) => {
89
+ try {
90
+ const d = typeof evt.data === 'string' ? JSON.parse(evt.data) : evt.data
91
+ if (d && (d.type === 'cdp-response' || d.type === 'cdp-event'))
92
+ console.log('[CDP]' + JSON.stringify(d))
93
+ } catch {}
94
+ })
95
+ }
96
+ `)
97
+
98
+ // Capture CDP messages from the preview's console output
99
+ mainWindow.webContents.on('console-message', (_event, ...rest) => {
100
+ const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
101
+ if (!message?.startsWith('[CDP]')) return
102
+ try {
103
+ const data = JSON.parse(message.slice(5))
104
+ // Translate to standard CDP wire format (strip internal type field)
105
+ const wireMsg =
106
+ data.type === 'cdp-response'
107
+ ? { id: data.id, result: data.result, error: data.error }
108
+ : { method: data.method, params: data.params }
109
+ if (data.sessionId) wireMsg.sessionId = data.sessionId
110
+ const payload = JSON.stringify(wireMsg)
111
+ for (const c of clients) if (c.readyState === 1) c.send(payload)
112
+ } catch {}
113
+ })
114
+
115
+ // HTTP discovery endpoints (chrome://inspect, Playwright, etc.)
116
+ const httpServer = createServer((req, res) => {
117
+ if (req.url === '/json/list' || req.url === '/json') {
118
+ res.writeHead(200, { 'Content-Type': 'application/json' })
119
+ res.end(
120
+ JSON.stringify([
121
+ {
122
+ description: 'BRICKS Preview',
123
+ id: 'bricks-preview',
124
+ title: 'BRICKS Preview',
125
+ type: 'page',
126
+ url: previewUrl,
127
+ webSocketDebuggerUrl: `ws://localhost:${port}/ws`,
128
+ },
129
+ ]),
130
+ )
131
+ return
132
+ }
133
+ if (req.url === '/json/version') {
134
+ res.writeHead(200, { 'Content-Type': 'application/json' })
135
+ res.end(JSON.stringify({ Browser: 'BRICKS Preview', 'Protocol-Version': '1.3' }))
136
+ return
137
+ }
138
+ // bricks-cli discovery endpoint
139
+ if (req.url === '/devtools/info') {
140
+ res.writeHead(200, { 'Content-Type': 'application/json' })
141
+ res.end(
142
+ JSON.stringify({
143
+ name: 'BRICKS Preview',
144
+ port,
145
+ protocols: ['cdp'],
146
+ hasPasscode: false,
147
+ }),
148
+ )
149
+ return
150
+ }
151
+ res.writeHead(404)
152
+ res.end()
153
+ })
154
+
155
+ const wss = new WebSocketServer({ server: httpServer, path: '/ws' })
156
+ wss.on('connection', (ws) => {
157
+ clients.add(ws)
158
+ injectCdpRelay()
159
+
160
+ ws.on('message', (raw) => {
161
+ try {
162
+ const req = JSON.parse(raw.toString())
163
+ const cdpReq = JSON.stringify({
164
+ type: 'cdp-request',
165
+ id: req.id,
166
+ method: req.method,
167
+ params: req.params || {},
168
+ sessionId: req.sessionId,
169
+ })
170
+ mainWindow.webContents.executeJavaScript(`window.postMessage(${JSON.stringify(cdpReq)})`)
171
+ } catch {}
172
+ })
173
+
174
+ ws.on('close', () => clients.delete(ws))
175
+ })
176
+
177
+ // Try ports starting from the requested one until one is available
178
+ const listen = (p) =>
179
+ new Promise((resolve, reject) => {
180
+ httpServer.once('error', (err) => {
181
+ if (err.code === 'EADDRINUSE' && p < port + 100) {
182
+ resolve(listen(p + 1))
183
+ } else {
184
+ reject(err)
185
+ }
186
+ })
187
+ httpServer.listen(p, () => {
188
+ console.log(`CDP server: ws://localhost:${p}/ws`)
189
+ console.log(`Inspect: devtools://devtools/bundled/inspector.html?ws=localhost:${p}/ws`)
190
+ resolve(p)
191
+ })
192
+ })
193
+ await listen(port)
194
+ }
195
+
73
196
  app.on('ready', () => {
74
197
  let show = true
75
198
  if (takeScreenshotConfig && !takeScreenshotConfig.noHeadless) show = false
@@ -124,12 +247,16 @@ app.on('ready', () => {
124
247
  })
125
248
  `)
126
249
  }
250
+ // Start CDP WebSocket server if requested
251
+ const cdpPort = values['cdp-port'] ? parseInt(values['cdp-port'], 10) : null
252
+ if (cdpPort) startCdpServer(mainWindow, cdpPort)
127
253
  })
128
254
 
129
255
  // Capture console messages from the preview
130
256
  if (testId) {
131
- mainWindow.webContents.on('console-message', (_, { message }) => {
132
- if (message.startsWith('[TEST_RESULT]')) {
257
+ mainWindow.webContents.on('console-message', (_event, ...rest) => {
258
+ const message = typeof rest[0] === 'object' ? rest[0].message : rest[1]
259
+ if (message?.startsWith('[TEST_RESULT]')) {
133
260
  const data = JSON.parse(message.replace('[TEST_RESULT]', ''))
134
261
  console.log(`[TEST_RESULT_TOON]${TOON.encode(data.result)}`)
135
262
  if (!takeScreenshotConfig && noKeepOpen) app.quit()
package/tools/preview.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { $ } from 'bun'
2
- import { watch } from 'fs'
2
+ import { watch, unlinkSync } from 'fs'
3
3
  import type { FSWatcher } from 'fs'
4
4
  import { parseArgs } from 'util'
5
5
  import debounce from 'lodash/debounce'
@@ -19,6 +19,8 @@ const { values } = parseArgs({
19
19
  'test-id': { type: 'string' },
20
20
  'test-title-like': { type: 'string' },
21
21
  'no-keep-open': { type: 'boolean' },
22
+ 'cdp-port': { type: 'string' },
23
+ 'no-cdp': { type: 'boolean' },
22
24
  },
23
25
  strict: true,
24
26
  allowPositionals: true,
@@ -62,6 +64,11 @@ if (values['no-keep-open']) {
62
64
  args.push('--no-keep-open')
63
65
  }
64
66
 
67
+ if (!values['no-cdp']) {
68
+ const cdpPort = parseInt(values['cdp-port'] || '', 10) || 19852
69
+ args.push('--cdp-port', String(cdpPort))
70
+ }
71
+
65
72
  const useTypecheck = !values['skip-typecheck']
66
73
 
67
74
  const compile = async () => {
@@ -80,6 +87,14 @@ if (needWatcher) {
80
87
  })
81
88
  }
82
89
 
90
+ const devtoolsInfoPath = `${cwd}/.bricks/devtools.json`
91
+
92
+ const cleanupDevtoolsInfo = () => {
93
+ try {
94
+ unlinkSync(devtoolsInfoPath)
95
+ } catch {}
96
+ }
97
+
83
98
  const proc = Bun.spawn(['bunx', '--bun', 'electron', `${__dirname}/preview-main.mjs`, ...args], {
84
99
  env: { ...process.env, BRICKS_STAGE: app.stage || 'production' },
85
100
  stdout: 'pipe',
@@ -102,6 +117,18 @@ const processOutput = async () => {
102
117
  const toonData = line.replace('[TEST_RESULT_TOON]', '')
103
118
  console.log(toonData)
104
119
  } else if (line) {
120
+ // Detect CDP server startup from preview-main output
121
+ const cdpMatch = line.match(/^CDP server: ws:\/\/localhost:(\d+)/)
122
+ if (cdpMatch) {
123
+ const info = {
124
+ port: parseInt(cdpMatch[1], 10),
125
+ pid: proc.pid,
126
+ address: 'localhost',
127
+ name: app.name || 'BRICKS Preview',
128
+ startedAt: new Date().toISOString(),
129
+ }
130
+ Bun.write(devtoolsInfoPath, JSON.stringify(info, null, 2))
131
+ }
105
132
  console.log(line)
106
133
  }
107
134
  })
@@ -112,4 +139,5 @@ const processOutput = async () => {
112
139
  await processOutput()
113
140
  await proc.exited
114
141
 
142
+ cleanupDevtoolsInfo()
115
143
  if (watcher) watcher.close()
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* Take picture on the Camera */
20
21
  export type BrickCameraActionTakePicture = ActionWithParams & {
@@ -154,19 +155,23 @@ Default property:
154
155
  }
155
156
  events?: BrickBasicEvents & {
156
157
  /* Event of the Camera state change */
157
- stateChange?: Array<EventAction>
158
+ stateChange?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['stateChange']>>
158
159
  /* Event of the Camera record start */
159
160
  recordStart?: Array<EventAction>
160
161
  /* Event of the Camera record end */
161
162
  recordEnd?: Array<EventAction>
162
163
  /* Event of the Camera barcode read */
163
- barcodeRead?: Array<EventAction>
164
+ barcodeRead?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['barcodeRead']>>
164
165
  /* Event of the Camera picture taken */
165
- pictureTaken?: Array<EventAction>
166
+ pictureTaken?: Array<
167
+ EventAction<string & keyof TemplateEventPropsMap['Camera']['pictureTaken']>
168
+ >
166
169
  /* Event of the Camera record finished */
167
- recordFinish?: Array<EventAction>
170
+ recordFinish?: Array<
171
+ EventAction<string & keyof TemplateEventPropsMap['Camera']['recordFinish']>
172
+ >
168
173
  /* Event of the Camera mount error */
169
- mountError?: Array<EventAction>
174
+ mountError?: Array<EventAction<string & keyof TemplateEventPropsMap['Camera']['mountError']>>
170
175
  }
171
176
  outlets?: {
172
177
  /* Camera device and format information */
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* Data highlight */
20
21
  export type BrickChartActionDataHighlight = ActionWithParams & {
@@ -335,9 +336,11 @@ Default property:
335
336
  /* Event of chart render */
336
337
  onRender?: Array<EventAction>
337
338
  /* Event of data point on press */
338
- onPress?: Array<EventAction>
339
+ onPress?: Array<EventAction<string & keyof TemplateEventPropsMap['Chart']['onPress']>>
339
340
  /* Event of legend select changed */
340
- onLegendSelectChanged?: Array<EventAction>
341
+ onLegendSelectChanged?: Array<
342
+ EventAction<string & keyof TemplateEventPropsMap['Chart']['onLegendSelectChanged']>
343
+ >
341
344
  }
342
345
  animation?: AnimationBasicEvents & {
343
346
  onRender?: Animation
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface GenerativeMediaDef {
20
21
  /*
@@ -194,21 +195,33 @@ Default property:
194
195
  /* Event of the brick blur (Use TV Device with controller) */
195
196
  generativeMediaOnBlur?: Array<EventAction>
196
197
  /* Event when media generation succeeds */
197
- onSuccess?: Array<EventAction>
198
+ onSuccess?: Array<
199
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['onSuccess']>
200
+ >
198
201
  /* Event when media generation fails */
199
- onError?: Array<EventAction>
202
+ onError?: Array<EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['onError']>>
200
203
  /* Event when media prompt request starts */
201
- promptStart?: Array<EventAction>
204
+ promptStart?: Array<
205
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['promptStart']>
206
+ >
202
207
  /* Event when media prompt request succeeds */
203
- promptSuccess?: Array<EventAction>
208
+ promptSuccess?: Array<
209
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['promptSuccess']>
210
+ >
204
211
  /* Event when media prompt request fails */
205
- promptError?: Array<EventAction>
212
+ promptError?: Array<
213
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['promptError']>
214
+ >
206
215
  /* Event when media loading starts */
207
216
  loadStart?: Array<EventAction>
208
217
  /* Event when media loading succeeds */
209
- loadSuccess?: Array<EventAction>
218
+ loadSuccess?: Array<
219
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['loadSuccess']>
220
+ >
210
221
  /* Event when media loading fails */
211
- loadError?: Array<EventAction>
222
+ loadError?: Array<
223
+ EventAction<string & keyof TemplateEventPropsMap['GenerativeMedia']['loadError']>
224
+ >
212
225
  }
213
226
  outlets?: {
214
227
  /* Brick is pressing */
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface BrickIconDef {
20
21
  /*
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface BrickImageDef {
20
21
  /*
@@ -70,7 +71,7 @@ Default property:
70
71
  /* Event of the image on load */
71
72
  onLoad?: Array<EventAction>
72
73
  /* Event of the image on error */
73
- onError?: Array<EventAction>
74
+ onError?: Array<EventAction<string & keyof TemplateEventPropsMap['Image']['onError']>>
74
75
  }
75
76
  outlets?: {
76
77
  /* Brick is pressing */
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* prev page */
20
21
  export type BrickItemsActionPrevPage = Action & {
@@ -400,17 +401,27 @@ Default property:
400
401
  | DataLink
401
402
  events?: BrickBasicEventsForItem & {
402
403
  /* Event on page render finished */
403
- onPageRender?: Array<EventActionForItem>
404
+ onPageRender?: Array<
405
+ EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onPageRender']>
406
+ >
404
407
  /* Event on page change. */
405
- onPageChange?: Array<EventActionForItem>
408
+ onPageChange?: Array<
409
+ EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onPageChange']>
410
+ >
406
411
  /* Event on page index out of bound. */
407
- onPageOutOfBound?: Array<EventActionForItem>
412
+ onPageOutOfBound?: Array<
413
+ EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onPageOutOfBound']>
414
+ >
408
415
  /* Event on into `detail` mode */
409
- onIntoDetailMode?: Array<EventActionForItem>
416
+ onIntoDetailMode?: Array<
417
+ EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onIntoDetailMode']>
418
+ >
410
419
  /* Event on into `list` mode. */
411
- onIntoListMode?: Array<EventActionForItem>
420
+ onIntoListMode?: Array<
421
+ EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onIntoListMode']>
422
+ >
412
423
  /* Event on render error */
413
- onError?: Array<EventActionForItem>
424
+ onError?: Array<EventActionForItem<string & keyof TemplateEventPropsMap['Items']['onError']>>
414
425
  }
415
426
  outlets?: {
416
427
  /* Catched error message */
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* Play animation */
20
21
  export type BrickLottieActionPlay = ActionWithParams & {
@@ -115,9 +116,13 @@ Default property:
115
116
  /* Event of the brick blur (Use TV Device with controller) */
116
117
  onBlur?: Array<EventAction>
117
118
  /* Event of the animation finished */
118
- onAnimationFinish?: Array<EventAction>
119
+ onAnimationFinish?: Array<
120
+ EventAction<string & keyof TemplateEventPropsMap['Lottie']['onAnimationFinish']>
121
+ >
119
122
  /* Event of the uri on load failed */
120
- onAnimationFailure?: Array<EventAction>
123
+ onAnimationFailure?: Array<
124
+ EventAction<string & keyof TemplateEventPropsMap['Lottie']['onAnimationFailure']>
125
+ >
121
126
  /* Event of the animation on loop */
122
127
  onAnimationLoop?: Array<EventAction>
123
128
  }
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* Zoom in the map */
20
21
  export type BrickMapsActionZoomIn = Action & {
@@ -206,11 +207,15 @@ Default property:
206
207
  /* Event of the brick blur (Use TV Device with controller) */
207
208
  onBlur?: Array<EventAction>
208
209
  /* Event when a marker is pressed */
209
- onMarkerPress?: Array<EventAction>
210
+ onMarkerPress?: Array<
211
+ EventAction<string & keyof TemplateEventPropsMap['Maps']['onMarkerPress']>
212
+ >
210
213
  /* Event when the map is pressed */
211
- onMapPress?: Array<EventAction>
214
+ onMapPress?: Array<EventAction<string & keyof TemplateEventPropsMap['Maps']['onMapPress']>>
212
215
  /* Event when the map region changes */
213
- onRegionChange?: Array<EventAction>
216
+ onRegionChange?: Array<
217
+ EventAction<string & keyof TemplateEventPropsMap['Maps']['onRegionChange']>
218
+ >
214
219
  /* Event when the map is ready */
215
220
  onReady?: Array<EventAction>
216
221
  }
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface BrickQrcodeDef {
20
21
  /*
@@ -1,6 +1,6 @@
1
1
  /* Auto generated by build script
2
2
  *
3
- * Rectangle shape with customizable fill, border, radius, and shadow
3
+ * Rectangle shape with customizable fill, border, radius, shadow, and blur
4
4
  */
5
5
  import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
6
6
  import type { Data, DataLink } from '../data'
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface BrickRectDef {
20
21
  /*
@@ -36,7 +37,16 @@ Default property:
36
37
  "linearGradientLocations": [
37
38
  0,
38
39
  1
39
- ]
40
+ ],
41
+ "blurEnabled": false,
42
+ "blurVariant": "blur",
43
+ "blurType": "light",
44
+ "blurAmount": 10,
45
+ "blurDirection": "blurredTopClearBottom",
46
+ "blurStartOffset": 0,
47
+ "blurGlassType": "regular",
48
+ "blurGlassOpacity": 0.5,
49
+ "blurGlassInteractive": false
40
50
  }
41
51
  */
42
52
  property?: BrickBasicProperty & {
@@ -60,6 +70,32 @@ Default property:
60
70
  }
61
71
  /* An optional array of numbers defining the location of each gradient color stop */
62
72
  linearGradientLocations?: Array<number | DataLink> | DataLink
73
+ /* Enable blur effect.
74
+ Not supported on Desktop (Electron) and Web.
75
+ Avoid using opacity prop with blur — use alpha backgroundColor (e.g. rgba) instead. */
76
+ blurEnabled?: boolean | DataLink
77
+ /* Blur variant */
78
+ blurVariant?: 'blur' | 'progressiveBlur' | 'liquidGlass' | DataLink
79
+ /* Blur type (blur variant) */
80
+ blurType?: 'xlight' | 'light' | 'dark' | 'regular' | 'prominent' | DataLink
81
+ /* Blur amount (0 ~ 100, blur variant) */
82
+ blurAmount?: number | DataLink
83
+ /* Progressive blur direction (progressiveBlur variant) */
84
+ blurDirection?:
85
+ | 'blurredTopClearBottom'
86
+ | 'blurredBottomClearTop'
87
+ | 'blurredCenterClearTopAndBottom'
88
+ | DataLink
89
+ /* Progressive blur start offset (0 ~ 1, progressiveBlur variant) */
90
+ blurStartOffset?: number | DataLink
91
+ /* Glass type (liquidGlass variant, iOS 26+) */
92
+ blurGlassType?: 'clear' | 'regular' | DataLink
93
+ /* Glass tint color (liquidGlass variant) */
94
+ blurGlassTintColor?: string | DataLink
95
+ /* Glass opacity (0 ~ 1, liquidGlass variant) */
96
+ blurGlassOpacity?: number | DataLink
97
+ /* Enable glass interaction (liquidGlass variant) */
98
+ blurGlassInteractive?: boolean | DataLink
63
99
  }
64
100
  events?: BrickBasicEvents & {
65
101
  /* Event of the brick press */
@@ -91,7 +127,7 @@ Default property:
91
127
  }
92
128
  }
93
129
 
94
- /* Rectangle shape with customizable fill, border, radius, and shadow */
130
+ /* Rectangle shape with customizable fill, border, radius, shadow, and blur */
95
131
  export type BrickRect = Brick &
96
132
  BrickRectDef & {
97
133
  templateKey: 'BRICK_RECT'
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  interface BrickRichTextDef {
20
21
  /*
@@ -15,6 +15,7 @@ import type {
15
15
  EventProperty,
16
16
  } from '../common'
17
17
  import type { BrickBasicProperty, BrickBasicEvents, BrickBasicEventsForItem } from '../brick-base'
18
+ import type { TemplateEventPropsMap } from '../../utils/event-props'
18
19
 
19
20
  /* Play animation */
20
21
  export type BrickRiveActionPlay = ActionWithParams & {
@@ -162,21 +163,27 @@ Default property:
162
163
  }
163
164
  events?: BrickBasicEvents & {
164
165
  /* Event of animation play */
165
- onPlay?: Array<EventAction>
166
+ onPlay?: Array<EventAction<string & keyof TemplateEventPropsMap['Rive']['onPlay']>>
166
167
  /* Event of animation pause */
167
- onPause?: Array<EventAction>
168
+ onPause?: Array<EventAction<string & keyof TemplateEventPropsMap['Rive']['onPause']>>
168
169
  /* Event of animation stop */
169
- onStop?: Array<EventAction>
170
+ onStop?: Array<EventAction<string & keyof TemplateEventPropsMap['Rive']['onStop']>>
170
171
  /* Event of animation loop end */
171
- onLoopEnd?: Array<EventAction>
172
+ onLoopEnd?: Array<EventAction<string & keyof TemplateEventPropsMap['Rive']['onLoopEnd']>>
172
173
  /* Event of state changed */
173
- onStateChanged?: Array<EventAction>
174
+ onStateChanged?: Array<
175
+ EventAction<string & keyof TemplateEventPropsMap['Rive']['onStateChanged']>
176
+ >
174
177
  /* Event of error */
175
- onError?: Array<EventAction>
178
+ onError?: Array<EventAction<string & keyof TemplateEventPropsMap['Rive']['onError']>>
176
179
  /* Event of Rive general event received */
177
- onRiveGeneralEvent?: Array<EventAction>
180
+ onRiveGeneralEvent?: Array<
181
+ EventAction<string & keyof TemplateEventPropsMap['Rive']['onRiveGeneralEvent']>
182
+ >
178
183
  /* Event of Rive open-url event received */
179
- onRiveOpenUrlEvent?: Array<EventAction>
184
+ onRiveOpenUrlEvent?: Array<
185
+ EventAction<string & keyof TemplateEventPropsMap['Rive']['onRiveOpenUrlEvent']>
186
+ >
180
187
  }
181
188
  animation?: AnimationBasicEvents & {
182
189
  onPlay?: Animation