@vyr/engine 0.0.33 → 0.0.34

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 (137) hide show
  1. package/package.json +6 -3
  2. package/src/ArrayUtils.ts +63 -65
  3. package/src/AsyncTask.ts +67 -71
  4. package/src/Category.ts +69 -86
  5. package/src/Color.ts +3 -111
  6. package/src/Engine.ts +12 -24
  7. package/src/Executor.ts +109 -0
  8. package/src/Generate.ts +23 -40
  9. package/src/InputSystem.ts +106 -108
  10. package/src/Listener.ts +58 -59
  11. package/src/ObjectPool.ts +83 -84
  12. package/src/ObjectUtils.ts +97 -49
  13. package/src/Scriptable.ts +82 -0
  14. package/src/Serialization.ts +4 -6
  15. package/src/Traverser.ts +41 -39
  16. package/src/actor/Actor.ts +23 -27
  17. package/src/actor/AnimationUnitActor.ts +22 -36
  18. package/src/actor/DivActor.ts +21 -41
  19. package/src/actor/FragmentActor.ts +1 -5
  20. package/src/actor/HTMLActor.ts +81 -0
  21. package/src/actor/HTMLServiceActor.ts +49 -0
  22. package/src/actor/{HTMTransformControllerActor.ts → HTMLTransformControllerActor.ts} +178 -71
  23. package/src/actor/InputActor.ts +50 -0
  24. package/src/actor/TextActor.ts +51 -0
  25. package/src/actor/index.ts +6 -5
  26. package/src/asset/Asset.ts +23 -68
  27. package/src/asset/AssetGraph.ts +21 -28
  28. package/src/descriptor/AnimationUnit.ts +81 -0
  29. package/src/descriptor/Camera.ts +12 -0
  30. package/src/descriptor/Controller.ts +6 -0
  31. package/src/descriptor/Descriptor.ts +133 -113
  32. package/src/descriptor/Div.ts +29 -0
  33. package/src/descriptor/HTML.ts +22 -0
  34. package/src/descriptor/HTMLService.ts +42 -0
  35. package/src/descriptor/HTMLTransformController.ts +67 -0
  36. package/src/descriptor/Input.ts +29 -0
  37. package/src/descriptor/Interaction.ts +80 -0
  38. package/src/descriptor/Node.ts +98 -0
  39. package/src/descriptor/Scene.ts +110 -0
  40. package/src/descriptor/Service.ts +11 -0
  41. package/src/descriptor/Store.ts +136 -0
  42. package/src/descriptor/Text.ts +36 -0
  43. package/src/descriptor/index.ts +14 -15
  44. package/src/graphics/Collection.ts +1 -5
  45. package/src/graphics/Compilation.ts +15 -19
  46. package/src/graphics/Graphics.ts +41 -54
  47. package/src/graphics/Observer.ts +6 -14
  48. package/src/graphics/Unit.ts +3 -9
  49. package/src/graphics/VariableProxy.ts +11 -15
  50. package/src/index.ts +5 -5
  51. package/src/interpreter/AnimationUnitInterpreter.ts +7 -9
  52. package/src/interpreter/DivInterpreter.ts +10 -13
  53. package/src/interpreter/FragmentInterpreter.ts +2 -6
  54. package/src/interpreter/HTMLServiceInterpreter.ts +25 -15
  55. package/src/interpreter/HTMLTransformControllerInterpreter.ts +9 -12
  56. package/src/interpreter/InputInterpreter.ts +41 -0
  57. package/src/interpreter/Interpreter.ts +3 -4
  58. package/src/interpreter/SceneInterpreter.ts +93 -0
  59. package/src/interpreter/ServiceInterpreter.ts +8 -15
  60. package/src/interpreter/StoreInterpreter.ts +7 -0
  61. package/src/interpreter/TextInterpreter.ts +41 -0
  62. package/src/interpreter/index.ts +5 -7
  63. package/src/locale/Language.ts +1 -5
  64. package/src/locale/LanguageProvider.ts +164 -21
  65. package/src/math/Euler.ts +2 -5
  66. package/src/math/Matrix4.ts +2 -4
  67. package/src/math/Quaternion.ts +2 -4
  68. package/src/math/Vector2.ts +4 -4
  69. package/src/math/Vector3.ts +2 -4
  70. package/src/math/utils.ts +1 -5
  71. package/src/schema/AnimationUnit.ts +68 -0
  72. package/src/schema/Asset.ts +13 -0
  73. package/src/schema/Descriptor.ts +41 -0
  74. package/src/schema/HTML.ts +261 -0
  75. package/src/schema/Interaction.ts +50 -0
  76. package/src/schema/Scene.ts +138 -0
  77. package/src/schema/Store.ts +8 -0
  78. package/src/schema/index.ts +7 -0
  79. package/src/scripts/ConditionScriptable.ts +196 -0
  80. package/src/scripts/FetchScriptable.ts +51 -0
  81. package/src/scripts/FindScriptable.ts +23 -0
  82. package/src/scripts/InvokeScriptable.ts +13 -0
  83. package/src/scripts/SwitchSceneScriptable.ts +18 -0
  84. package/src/scripts/UpdateScriptable.ts +60 -0
  85. package/src/scripts/index.ts +6 -0
  86. package/src/utils/AssetProvider.ts +4 -77
  87. package/src/utils/DOM.ts +37 -0
  88. package/src/utils/HTML.ts +5 -0
  89. package/src/utils/Service.ts +40 -0
  90. package/src/utils/constants.ts +1 -5
  91. package/src/utils/http.ts +2 -21
  92. package/src/utils/index.ts +3 -1
  93. package/src/actor/HTMActor.ts +0 -169
  94. package/src/actor/HTMServiceActor.ts +0 -57
  95. package/src/actor/StyleActor.ts +0 -96
  96. package/src/descriptor/AnimationUnitDescriptor.ts +0 -65
  97. package/src/descriptor/CameraDescriptor.ts +0 -12
  98. package/src/descriptor/ControllerDescriptor.ts +0 -16
  99. package/src/descriptor/DatasetDescriptor.ts +0 -90
  100. package/src/descriptor/DivDescriptor.ts +0 -18
  101. package/src/descriptor/DynamicDescriptor.ts +0 -27
  102. package/src/descriptor/HTMLDescriptor.ts +0 -87
  103. package/src/descriptor/HTMLServiceDescriptor.ts +0 -19
  104. package/src/descriptor/HTMLTransformControllerDescriptor.ts +0 -34
  105. package/src/descriptor/NodeDescriptor.ts +0 -32
  106. package/src/descriptor/PrefabDescriptor.ts +0 -53
  107. package/src/descriptor/PrefabInstanceDescriptor.ts +0 -32
  108. package/src/descriptor/ServiceDescriptor.ts +0 -32
  109. package/src/descriptor/ServiceSchedulerDescriptor.ts +0 -32
  110. package/src/descriptor/StyleDescriptor.ts +0 -213
  111. package/src/interaction/InteractionDescriptor.ts +0 -96
  112. package/src/interaction/InteractionExecutor.ts +0 -84
  113. package/src/interaction/Scriptable.ts +0 -44
  114. package/src/interaction/index.ts +0 -3
  115. package/src/interpreter/DatasetInterpreter.ts +0 -11
  116. package/src/interpreter/DynamicInterpreter.ts +0 -207
  117. package/src/interpreter/PrefaInterpreter.ts +0 -11
  118. package/src/interpreter/PrefabInstanceInterpreter.ts +0 -12
  119. package/src/interpreter/ServiceSchedulerInterpreter.ts +0 -42
  120. package/src/interpreter/StyleInterpreter.ts +0 -66
  121. package/src/preset/execute/dataset/index.ts +0 -1
  122. package/src/preset/execute/dataset/update.ts +0 -51
  123. package/src/preset/execute/graphics/index.ts +0 -1
  124. package/src/preset/execute/graphics/invoke.ts +0 -48
  125. package/src/preset/execute/index.ts +0 -4
  126. package/src/preset/execute/net/http.ts +0 -52
  127. package/src/preset/execute/net/index.ts +0 -1
  128. package/src/preset/execute/scheduler/index.ts +0 -1
  129. package/src/preset/execute/scheduler/switch.ts +0 -46
  130. package/src/preset/index.ts +0 -7
  131. package/src/preset/interaction/graphics/index.ts +0 -1
  132. package/src/preset/interaction/graphics/invoke.ts +0 -27
  133. package/src/preset/interaction/index.ts +0 -2
  134. package/src/preset/interaction/scheduler/index.ts +0 -1
  135. package/src/preset/interaction/scheduler/switch.ts +0 -27
  136. package/src/setup/index.ts +0 -17
  137. package/src/utils/compile.ts +0 -50
@@ -19,7 +19,7 @@ import { Vector3 } from './Vector3';
19
19
  * vector.applyQuaternion( quaternion );
20
20
  * ```
21
21
  */
22
- class Quaternion {
22
+ export class Quaternion {
23
23
  x: number;
24
24
  y: number;
25
25
  z: number;
@@ -732,6 +732,4 @@ class Quaternion {
732
732
  yield this.z;
733
733
  yield this.w;
734
734
  }
735
- }
736
-
737
- export { Quaternion };
735
+ }
@@ -26,7 +26,7 @@ import { clamp } from './utils';
26
26
  * const d = a.distanceTo( b );
27
27
  * ```
28
28
  */
29
- class Vector2 {
29
+ export class Vector2 {
30
30
  static create(v2?: number | DeserializationObject<Vector2>, y?: number) {
31
31
  if (v2 === undefined) return new Vector2()
32
32
 
@@ -60,6 +60,7 @@ class Vector2 {
60
60
 
61
61
  /**
62
62
  * Alias for {@link Vector2#x}.
63
+ * @DSL_HIDDEN
63
64
  */
64
65
  get width(): number {
65
66
  return this.x;
@@ -71,6 +72,7 @@ class Vector2 {
71
72
 
72
73
  /**
73
74
  * Alias for {@link Vector2#y}.
75
+ * @DSL_HIDDEN
74
76
  */
75
77
  get height(): number {
76
78
  return this.y;
@@ -675,6 +677,4 @@ class Vector2 {
675
677
  yield this.x;
676
678
  yield this.y;
677
679
  }
678
- }
679
-
680
- export { Vector2 };
680
+ }
@@ -42,7 +42,7 @@ interface Cylindrical {
42
42
  * const d = a.distanceTo( b );
43
43
  * ```
44
44
  */
45
- class Vector3 {
45
+ export class Vector3 {
46
46
  static create(v3?: number | DeserializationObject<Vector3>, y?: number, z?: number) {
47
47
  if (v3 === undefined) return new Vector3()
48
48
 
@@ -1057,6 +1057,4 @@ class Vector3 {
1057
1057
 
1058
1058
  // 全局辅助变量
1059
1059
  const _vector = /*@__PURE__*/ new Vector3();
1060
- const _quaternion = /*@__PURE__*/ new Quaternion();
1061
-
1062
- export { Vector3 };
1060
+ const _quaternion = /*@__PURE__*/ new Quaternion();
package/src/math/utils.ts CHANGED
@@ -6,12 +6,8 @@
6
6
  * @param {number} max - The max value.
7
7
  * @return {number} The clamped value.
8
8
  */
9
- function clamp(value: number, min: number, max: number) {
9
+ export function clamp(value: number, min: number, max: number) {
10
10
 
11
11
  return Math.max(min, Math.min(max, value));
12
12
 
13
- }
14
-
15
- export {
16
- clamp
17
13
  }
@@ -0,0 +1,68 @@
1
+ import z from "zod";
2
+
3
+ export const NumberFrameDataSchema = z.object({
4
+ type: z.literal('number').default('number'),
5
+ startValue: z.number().default(0),
6
+ endValue: z.number().default(0),
7
+ })
8
+ export type NumberFrameData = z.infer<typeof NumberFrameDataSchema>
9
+
10
+ export const BooleanFrameDataSchema = z.object({
11
+ type: z.literal('boolean').default('boolean'),
12
+ startValue: z.boolean().default(true),
13
+ endValue: z.boolean().default(true),
14
+ })
15
+ export type BooleanFrameData = z.infer<typeof BooleanFrameDataSchema>
16
+
17
+ export const Vector2FrameDataSchema = z.object({
18
+ type: z.literal('vector2').default('vector2'),
19
+ startValue: z.tuple([z.number(), z.number()]).default([0, 0]),
20
+ endValue: z.tuple([z.number(), z.number()]).default([0, 0]),
21
+ })
22
+
23
+ export const Vector3FrameDataSchema = z.object({
24
+ type: z.literal('vector3').default('vector3'),
25
+ startValue: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
26
+ endValue: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
27
+ })
28
+
29
+ export const EulerFrameDataSchema = z.object({
30
+ type: z.literal('euler').default('euler'),
31
+ startValue: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
32
+ endValue: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
33
+ })
34
+ export type VectorFrameData = z.infer<
35
+ typeof Vector2FrameDataSchema |
36
+ typeof Vector3FrameDataSchema |
37
+ typeof EulerFrameDataSchema
38
+ >
39
+
40
+ export const ColorFrameDataSchema = z.object({
41
+ type: z.literal('color').default('color'),
42
+ startValue: z.string().default('#ffffff'),
43
+ endValue: z.string().default('#ffffff'),
44
+ })
45
+ export type ColorFrameData = z.infer<typeof ColorFrameDataSchema>
46
+
47
+ /**
48
+ * 动画帧数据类型联合
49
+ */
50
+ export type AnimationFrameData = NumberFrameData | BooleanFrameData | VectorFrameData | ColorFrameData
51
+
52
+ export const parseFrameData = (data: AnimationFrameData) => {
53
+ switch (data.type) {
54
+ case 'boolean':
55
+ return BooleanFrameDataSchema.parse(data)
56
+ case 'vector2':
57
+ return Vector2FrameDataSchema.parse(data)
58
+ case 'vector3':
59
+ return Vector3FrameDataSchema.parse(data)
60
+ case 'euler':
61
+ return EulerFrameDataSchema.parse(data)
62
+ case 'color':
63
+ return ColorFrameDataSchema.parse(data)
64
+ default:
65
+ return NumberFrameDataSchema.parse(data)
66
+ }
67
+ }
68
+
@@ -0,0 +1,13 @@
1
+ import z from "zod"
2
+ import { Descriptor } from "../descriptor/Descriptor"
3
+
4
+ export type JsonAsset = { [k: string]: any }
5
+ export type RawAsset = HTMLImageElement | ImageBitmap | HTMLAudioElement | AudioBuffer | HTMLVideoElement | string | JsonAsset
6
+ export type StaticFactory = (url: string, forced?: boolean) => Promise<any>
7
+ export type DescriptorProvider = () => Promise<Descriptor>
8
+
9
+ export const AssetPropertySchame = z.object({
10
+ url: z.string().default('')
11
+ })
12
+ export type AssetProperty = z.infer<typeof AssetPropertySchame>
13
+ export type AssetPropertyCollection<T extends AssetProperty = AssetProperty> = T[]
@@ -0,0 +1,41 @@
1
+ import z from "zod"
2
+ import { language } from "../locale"
3
+ import { Descriptor } from "../descriptor/Descriptor"
4
+
5
+ /**描述器祖先节点 */
6
+ export interface DescriptorAncestor<T extends Descriptor = Descriptor> {
7
+ parent: T | null,
8
+ uuids: string[]
9
+ collection: Descriptor[]
10
+ }
11
+
12
+ /**当前描述器节点的邻接关系 */
13
+ export interface DescriptorAdjacency {
14
+ /**当前节点的父节点 */
15
+ parent: string
16
+ /**当前节点的前一个节点 */
17
+ prev: string
18
+ /**当前节点的后一个节点 */
19
+ next: string
20
+ }
21
+
22
+ const pathRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*|\[\d+\])*$/
23
+
24
+ const validatePath = (path: string) => {
25
+ const value = path.trim()
26
+ return value === '' || pathRegex.test(value)
27
+ }
28
+
29
+ export const VariabConfigSchema = z.object({
30
+ type: z.enum(['key', 'custom']).default('key'),
31
+ enabled: z.boolean().default(false),
32
+ value: z.string().default('').refine(
33
+ validatePath,
34
+ language.get('descriptor.variables.config.value')
35
+ )
36
+ })
37
+ export type VariabConfig = z.infer<typeof VariabConfigSchema>
38
+
39
+ export const DescriptorVariablesSchema = z.object().catchall(VariabConfigSchema).default({})
40
+ export type DescriptorVariables = z.infer<typeof DescriptorVariablesSchema>
41
+
@@ -0,0 +1,261 @@
1
+ import z from "zod"
2
+
3
+ export const PositionEnum = z.enum([
4
+ 'static',
5
+ 'relative',
6
+ 'absolute',
7
+ 'fixed',
8
+ 'sticky'
9
+ ])
10
+ export type Position = z.infer<typeof PositionEnum>
11
+
12
+ export const DisplayEnum = z.enum([
13
+ 'block',
14
+ 'inline',
15
+ 'inline-block',
16
+ 'flex',
17
+ 'inline-flex',
18
+ 'grid',
19
+ 'inline-grid',
20
+ 'contents',
21
+ 'flow-root',
22
+ 'table',
23
+ 'table-row',
24
+ 'table-cell',
25
+ 'list-item'
26
+ ])
27
+ export type Display = z.infer<typeof DisplayEnum>
28
+
29
+ export const HTMLStyleSchema = z.object({
30
+ position: PositionEnum.default('static'),
31
+ display: DisplayEnum.default('block'),
32
+ boxSizing: z.literal('border-box').default('border-box'),
33
+ width: z.string().default(''),
34
+ height: z.string().default(''),
35
+ }).catchall(z.string())
36
+
37
+ /**
38
+ * HTML元素行内样式定义
39
+ *
40
+ * 用于定义单个HTML节点的私有样式属性,优先级高于共享CSS样式。
41
+ * 每个属性对应一个CSS样式规则,采用大驼峰命名(CamelCase)。
42
+ *
43
+ * 设计原则:
44
+ * 1. 行内样式具有最高优先级,会覆盖外部样式表中的相同属性
45
+ * 2. 适合定义节点特有的样式,避免与共享样式冲突
46
+ * 3. 对于可复用的样式,建议使用Scene中的共享样式
47
+ * 4. 样式优先级:行内样式(大驼峰) > 共享样式(kebab-case) > 浏览器默认
48
+ *
49
+ * 强制使用border-box的原因:
50
+ * - 确保布局行为的一致性和可预测性
51
+ * - width/height = 内容宽度/高度 + padding + border
52
+ * - 添加padding或border不会改变元素的实际占用空间
53
+ * - 简化响应式布局的计算,精确控制尺寸
54
+ * - 避免组件嵌套时混合盒模型带来的计算复杂度
55
+ */
56
+ export type HTMLStyle = z.infer<typeof HTMLStyleSchema>
57
+
58
+ const ClassNamesSchema = z.array(z.string()).default([])
59
+
60
+ export type ClassNames = z.infer<typeof ClassNamesSchema>
61
+
62
+ export const HtmlAttributesSchema = z.object({
63
+ // ========== 基础通用属性 ==========
64
+ /**
65
+ * 基础样式属性 - 所有HTML元素通用
66
+ */
67
+ style: HTMLStyleSchema,
68
+
69
+ /**
70
+ * CSS类名集合 - 所有HTML元素通用
71
+ */
72
+ classNames: ClassNamesSchema,
73
+
74
+ // ========== Input 元素属性 ==========
75
+
76
+ /**
77
+ * 输入框类型: text, password, email, number, checkbox, radio, file 等
78
+ */
79
+ type: z.string().optional(),
80
+
81
+ /**
82
+ * 输入框的初始值
83
+ */
84
+ value: z.union([z.string(), z.number()]).optional(),
85
+
86
+ /**
87
+ * 输入框为空时的提示文本
88
+ */
89
+ placeholder: z.string().optional(),
90
+
91
+ /**
92
+ * 是否为必填项
93
+ */
94
+ required: z.boolean().optional(),
95
+
96
+ /**
97
+ * 正则表达式验证规则
98
+ */
99
+ pattern: z.string().optional(),
100
+
101
+ /**
102
+ * 最大字符数
103
+ */
104
+ maxlength: z.number().int().positive().optional(),
105
+
106
+ /**
107
+ * 最小字符数
108
+ */
109
+ minlength: z.number().int().positive().optional(),
110
+
111
+ /**
112
+ * 数字/日期的最小允许值
113
+ */
114
+ min: z.union([z.number(), z.string()]).optional(),
115
+
116
+ /**
117
+ * 数字/日期的最大允许值
118
+ */
119
+ max: z.union([z.number(), z.string()]).optional(),
120
+
121
+ /**
122
+ * 数字/日期的增减步长
123
+ */
124
+ step: z.union([z.number(), z.string()]).optional(),
125
+
126
+ /**
127
+ * 是否允许多个值(email/file类型)
128
+ */
129
+ multiple: z.boolean().optional(),
130
+
131
+ /**
132
+ * 是否禁用输入框
133
+ */
134
+ disabled: z.boolean().optional(),
135
+
136
+ /**
137
+ * 是否只读
138
+ */
139
+ readonly: z.boolean().optional(),
140
+
141
+ /**
142
+ * 复选框/单选框的选中状态
143
+ */
144
+ checked: z.boolean().optional(),
145
+
146
+ /**
147
+ * 页面加载时自动获得焦点
148
+ */
149
+ autofocus: z.boolean().optional(),
150
+
151
+ /**
152
+ * 输入框的显示宽度(字符数)
153
+ */
154
+ size: z.number().int().positive().optional(),
155
+
156
+ /**
157
+ * 浏览器自动填充: on/off/具体字段名
158
+ */
159
+ autocomplete: z.string().optional(),
160
+
161
+ /**
162
+ * 文件类型限制,如 "image/*", ".pdf,.doc"
163
+ */
164
+ accept: z.string().optional(),
165
+
166
+ /**
167
+ * 媒体捕获方式: "environment", "user", true, false
168
+ */
169
+ capture: z.union([z.string(), z.boolean()]).optional(),
170
+ }).default({ style: HTMLStyleSchema.parse({}), classNames: ClassNamesSchema.parse([]) })
171
+
172
+ /**
173
+ * HTML属性集合
174
+ *
175
+ * 提供结构化的方式定义和管理HTML元素的所有原生属性。
176
+ * style和classNames为基础通用属性,其余属性按元素类型分类定义。
177
+ *
178
+ * classNames(共享CSS类名列表)
179
+ *
180
+ * 引用在Scene的sharedCSSStyle中定义的共享样式类。
181
+ * 这些类名应用于当前HTML节点,提供可复用的视觉样式效果。
182
+ *
183
+ * 设计原则:
184
+ * 1. 使用共享样式类而不是重复定义相同的样式
185
+ * 2. 组合多个类名实现复杂的视觉效果
186
+ * 3. 类名中定义的样式可以被行内样式(style)覆盖
187
+ *
188
+ * 工作流程:
189
+ * 1. 在Scene的sharedCSSStyle中定义共享样式类
190
+ * 2. 在此属性中引用这些类名
191
+ * 3. 渲染时自动应用对应的样式规则
192
+ *
193
+ * 特性说明:
194
+ * - 支持多个类名组合:['theme-primary', 'shadow-large', 'rounded']
195
+ * - 类名样式可以被行内样式覆盖
196
+ * - 支持伪类状态(如:hover、:active)
197
+ * - 支持动画类名引用animations中定义的动画
198
+ *
199
+ * ✅ 正确使用示例:
200
+ * 1. 应用主题样式:['theme-primary', 'font-heading']
201
+ * 2. 添加视觉效果:['shadow-medium', 'rounded-corner']
202
+ * 3. 应用动画效果:['fade-in-animation']
203
+ * 4. 状态样式组合:['button-base', 'hover-effect', 'active-state']
204
+ *
205
+ * ❌ 错误使用示例:
206
+ * 1. 直接在此处定义样式字符串(应在sharedCSSStyle中定义)
207
+ * 2. 包含布局尺寸的类名(布局应由自身的style控制)
208
+ *
209
+ * style(HTML元素行内样式定义)
210
+ *
211
+ * 用于定义单个HTML节点的私有样式属性,优先级高于共享CSS样式。
212
+ * 每个属性对应一个CSS样式规则,采用大驼峰命名(CamelCase)。
213
+ *
214
+ * 设计原则:
215
+ * 1. 行内样式具有最高优先级,会覆盖外部样式表中的相同属性
216
+ * 2. 适合定义节点特有的样式,避免与共享样式冲突
217
+ * 3. 对于可复用的样式,建议使用Scene中的共享样式
218
+ * 4. 样式优先级:行内样式(大驼峰) > 共享样式(kebab-case) > 浏览器默认
219
+ *
220
+ * @example
221
+ * // Scene中定义的共享样式:
222
+ * sharedCSSStyle: {
223
+ * classNames: {
224
+ * '.theme-primary': {
225
+ * 'background-color': '#007bff',
226
+ * 'color': '#ffffff'
227
+ * },
228
+ * '.shadow-medium': {
229
+ * 'box-shadow': '0 4px 8px rgba(0,0,0,0.1)'
230
+ * },
231
+ * '.fade-in': {
232
+ * 'animation': 'fade-in 0.5s ease-in-out'
233
+ * }
234
+ * },
235
+ * animations: {
236
+ * 'fade-in': {
237
+ * '0%': { 'opacity': '0' },
238
+ * '100%': { 'opacity': '1' }
239
+ * }
240
+ * }
241
+ * }
242
+ *
243
+ * // HTML节点中定义HTML属性集合
244
+ * htmlAttributes: {
245
+ * // 与行内样式组合使用(行内样式优先级更高):
246
+ * classNames: ['theme-primary'], // 共享背景色和文字颜色
247
+ * style: { margin: '8px 0' },
248
+ *
249
+ * // Input元素特有属性
250
+ * type: 'text',
251
+ * value: '张三',
252
+ * placeholder: '请输入用户名',
253
+ * required: true,
254
+ * maxlength: 50,
255
+ * pattern: '^[a-zA-Z0-9_]+$',
256
+ * autocomplete: 'off'
257
+ * }
258
+ *
259
+ */
260
+ export type HtmlAttributes = z.infer<typeof HtmlAttributesSchema>
261
+
@@ -0,0 +1,50 @@
1
+ import z from "zod";
2
+ import { Generate } from "../Generate";
3
+ import { scriptableInputSchame } from "../Scriptable";
4
+ import { ConditionScriptable } from "../scripts";
5
+ import { AssetPropertySchame } from './Asset'
6
+
7
+ export const InteractionMapperSchame = z.object({
8
+ source: z.string().default(''),
9
+ target: z.string().default(''),
10
+ })
11
+ export type InteractionMapper = z.infer<typeof InteractionMapperSchame>
12
+ export const InteractionMapperArraySchame = z.array(InteractionMapperSchame)
13
+ export type InteractionMapperArray = z.infer<typeof InteractionMapperArraySchame>
14
+
15
+ export const BaseInteractionNodeSchame = z.object({
16
+ id: z.string().default(Generate.uuid()),
17
+ label: z.string().default(''),
18
+ position: z.object({ x: z.number(), y: z.number() }),
19
+ })
20
+ export const InteractionExecuteNodeSchame = BaseInteractionNodeSchame.extend({
21
+ type: z.literal('Execute').default('Execute'),
22
+ script: z.string().default(''),
23
+ input: scriptableInputSchame,
24
+ })
25
+ export const InteractionConditionNodeSchame = BaseInteractionNodeSchame.extend({
26
+ type: z.literal('Condition').default('Condition'),
27
+ script: z.literal('condition').default('condition'),
28
+ input: ConditionScriptable.inputSchame,
29
+ })
30
+ export const InteractionNodeSchame = z.union([
31
+ InteractionExecuteNodeSchame,
32
+ InteractionConditionNodeSchame
33
+ ])
34
+ export type InteractionNode = z.infer<typeof InteractionNodeSchame>
35
+
36
+ export const InteractionNodeArraySchame = z.array(InteractionNodeSchame).default([])
37
+ export type InteractionNodeArray = z.infer<typeof InteractionNodeArraySchame>
38
+
39
+ export const InteractionNodeInputCollectionSchame = z.object().catchall(scriptableInputSchame).default({})
40
+ export type InteractionNodeInputCollection = z.infer<typeof InteractionNodeInputCollectionSchame>
41
+
42
+ export const InteractionPropertySchame = AssetPropertySchame.extend({
43
+ uuid: z.string().default(''),
44
+ type: z.string().default(''),
45
+ nodes: InteractionNodeInputCollectionSchame,
46
+ })
47
+ export type InteractionProperty = z.infer<typeof InteractionPropertySchame>
48
+
49
+ export const InteractionPropertyArraySchame = z.array(InteractionPropertySchame).default([])
50
+ export type InteractionPropertyArray = z.infer<typeof InteractionPropertyArraySchame>
@@ -0,0 +1,138 @@
1
+ import { z } from 'zod';
2
+ import { language } from '../locale';
3
+
4
+ /**
5
+ * 验证CSS属性名格式(连字符格式)
6
+ * 例如:'background-color', 'font-size', 'border-radius'
7
+ */
8
+ export const CssPropertyNameSchema = z.string().regex(
9
+ /^[a-zA-Z][a-zA-Z0-9-]*$/,
10
+ language.get('scene.cssPropertyName.invalid')
11
+ );
12
+
13
+ /**
14
+ * 验证CSS属性值格式
15
+ * 不允许为空字符串,且不能包含 potentially dangerous 内容
16
+ */
17
+ export const CssPropertyValueSchema = z.string().min(1, language.get('scene.cssPropertyValue.empty')).refine(
18
+ (val) => !val.includes('<') && !val.includes('>') && !val.includes('javascript:'),
19
+ language.get('scene.cssPropertyValue.unsafe')
20
+ );
21
+
22
+ /**
23
+ * CSS样式属性对象模式
24
+ * 键为CSS属性名(连字符格式),值为属性值的字符串
25
+ */
26
+ export const CssPropertyObjectSchema = z.record(
27
+ CssPropertyNameSchema,
28
+ CssPropertyValueSchema
29
+ ).refine(
30
+ (obj) => Object.keys(obj).length > 0,
31
+ language.get('scene.cssPropertyObject.empty')
32
+ );
33
+
34
+ /**
35
+ * 验证CSS选择器格式
36
+ * 支持基本的选择器类型:类选择器、ID选择器、元素选择器、伪类、组合选择器
37
+ */
38
+ export const CssSelectorSchema = z.string().regex(
39
+ /^[.#]?[a-zA-Z][a-zA-Z0-9_-]*(?::[a-zA-Z-]+)?(?:[ >+~][.#]?[a-zA-Z][a-zA-Z0-9_-]*(?::[a-zA-Z-]+)?)*$/,
40
+ language.get('scene.cssSelector.invalid')
41
+ ).refine(
42
+ (selector) => selector.trim().length > 0,
43
+ language.get('scene.cssSelector.empty')
44
+ );
45
+
46
+ /**
47
+ * CSS类选择器样式定义模式
48
+ * 键为CSS选择器字符串,值为对应的样式规则对象
49
+ */
50
+ export const ClassNamesSchema = z.record(
51
+ CssSelectorSchema,
52
+ CssPropertyObjectSchema
53
+ )
54
+
55
+ /**
56
+ * 验证关键帧百分比格式
57
+ * 支持:0% - 100%,以及 from/to 关键字
58
+ */
59
+ export const KeyframePercentageSchema = z.string().refine(
60
+ (val) => {
61
+ if (val === 'from' || val === 'to') return true;
62
+ const percentage = parseInt(val);
63
+ return /^\d{1,2}%$|^100%$/.test(val) && percentage >= 0 && percentage <= 100;
64
+ },
65
+ language.get('scene.keyframe.invalid')
66
+ );
67
+
68
+ /**
69
+ * CSS关键帧动画定义模式
70
+ * 键为动画名称,值为包含关键帧百分比和对应样式规则的对象
71
+ */
72
+ export const AnimationsSchema = z.record(
73
+ z.string().regex(
74
+ /^[a-zA-Z][a-zA-Z0-9_-]*$/,
75
+ language.get('scene.animation.name.invalid')
76
+ ),
77
+ z.record(
78
+ KeyframePercentageSchema,
79
+ CssPropertyObjectSchema
80
+ ).refine(
81
+ (obj) => {
82
+ const keys = Object.keys(obj);
83
+ return keys.length >= 2 && (keys.includes('from') || keys.includes('0%')) && (keys.includes('to') || keys.includes('100%'));
84
+ },
85
+ language.get('scene.animation.missingStartEnd')
86
+ )
87
+ )
88
+
89
+ export const SharedCSSStyleSchema = z.object({
90
+ classNames: ClassNamesSchema.optional().default({}),
91
+ animations: AnimationsSchema.optional().default({}),
92
+ })
93
+
94
+ /**
95
+ * 共享CSS样式
96
+ *
97
+ * 提供对HTML节点的样式自定义能力,支持CSS类名样式定义和关键帧动画。
98
+ * 所有样式定义遵循标准CSS语法规则,但使用JavaScript对象表示法。
99
+ *
100
+ * 核心设计原则:
101
+ * 这里定义的样式应该是影响多个节点的共享样式,即可被多个HTML节点共用的className。
102
+ * 这些样式通常定义的是视觉表现而非布局,如颜色、字体、动画等公共视觉效果。
103
+ *
104
+ * ✅ 正确使用示例(共享样式):
105
+ * 1. 主题颜色类: `.primary-color`, `.secondary-color`
106
+ * 2. 字体样式类: `.heading-font`, `.body-text`
107
+ * 3. 动画效果类: `.fade-in`, `.slide-up`
108
+ * 4. 状态样式类: `.disabled`, `.active-state`
109
+ * 5. 通用效果类: `.shadow`, `.rounded-corners`
110
+ *
111
+ * ❌ 错误使用示例(避免使用的样式):
112
+ * 1. 布局相关: 如 `width: '100px'`, `height: '50px'`, `position: 'absolute'`
113
+ * 2. 位置相关: 如 `top: '10px'`, `left: '20px'`, `margin: '15px'`
114
+ * 3. 尺寸相关: 如 `min-width: '200px'`, `max-height: '300px'`
115
+ * 4. 节点特定的布局属性(这些应由节点的transform控制)
116
+ *
117
+ * @example
118
+ * const sharedStyles = {
119
+ * classNames: {
120
+ * '.theme-primary': {
121
+ * 'background-color': '#007bff',
122
+ * 'color': '#ffffff'
123
+ * },
124
+ * '.hover-lift:hover': {
125
+ * 'transform': 'translateY(-2px)',
126
+ * 'shadow': '0 4px 12px rgba(0,0,0,0.15)'
127
+ * }
128
+ * },
129
+ * animations: {
130
+ * 'fade-in': {
131
+ * '0%': { 'opacity': '0', 'transform': 'translateY(10px)' },
132
+ * '100%': { 'opacity': '1', 'transform': 'translateY(0)' }
133
+ * }
134
+ * }
135
+ * };
136
+ */
137
+ export type SharedCSSStyle = z.infer<typeof SharedCSSStyleSchema>;
138
+
@@ -0,0 +1,8 @@
1
+ import z from "zod";
2
+
3
+ export const StoreDataSchema = z.union([
4
+ z.object().catchall(z.any()),
5
+ z.array(z.any()),
6
+ ]).default({})
7
+
8
+ export type StoreData = z.infer<typeof StoreDataSchema>
@@ -0,0 +1,7 @@
1
+ export * from './Asset'
2
+ export * from './Descriptor'
3
+ export * from './Store'
4
+ export * from './Interaction'
5
+ export * from './HTML'
6
+ export * from './AnimationUnit'
7
+ export * from './Scene'