1use std::collections::BTreeMap;
14
15use serde::{Deserialize, Serialize};
16
17use crate::source_layout::default_gap;
18pub use crate::source_layout::ExclusionSource;
19pub use crate::source_page::{EdgeSource, PageLayerSource, PageSource};
20pub use crate::source_table::{TableSource, TableStyleRuleSource};
21pub use crate::source_text::TextSourceOptions;
22pub use crate::source_transform::{MirrorSource, TransformSource};
23
24use crate::{
25 Alignment, CollisionBounds, Color, Distribution, ImageOptions, LayoutConstraints, LayoutMode,
26 Length,
27};
28
29#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
31#[serde(rename_all = "snake_case")]
32pub enum ModelKind {
33 Document,
35 Canvas,
37 Dataset,
39}
40
41#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
43#[serde(deny_unknown_fields)]
44pub struct TemplateSourceV1 {
45 pub filemaker: String,
47 pub model: ModelKind,
49 pub id: String,
51 #[serde(default)]
53 pub page: Option<PageSource>,
54 #[serde(default)]
56 pub collision: Option<CollisionSource>,
57 #[serde(default)]
59 pub includes: Vec<IncludeSource>,
60 #[serde(default)]
62 pub components: BTreeMap<String, ComponentSource>,
63 #[serde(default)]
65 pub themes: BTreeMap<String, ThemeSource>,
66 #[serde(default)]
68 pub theme: Option<String>,
69 #[serde(default)]
71 pub style: StyleSource,
72 #[serde(default)]
74 pub styles: BTreeMap<String, StyleSource>,
75 #[serde(default)]
77 pub guides: BTreeMap<String, Length>,
78 #[serde(default)]
80 pub regions: BTreeMap<String, RegionSource>,
81 #[serde(default)]
83 pub exclusions: BTreeMap<String, ExclusionSource>,
84 #[serde(default)]
86 pub data_schema: BTreeMap<String, DataFieldSource>,
87 #[serde(default)]
89 pub elements: Vec<ElementSource>,
90 #[serde(default)]
92 pub ai: Option<AiSourcePolicy>,
93}
94
95#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
97#[serde(deny_unknown_fields)]
98pub struct IncludeSource {
99 pub path: String,
101 #[serde(default)]
103 pub namespace: Option<String>,
104}
105
106#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
108#[serde(deny_unknown_fields)]
109pub struct ComponentSource {
110 #[serde(default)]
112 pub props: BTreeMap<String, serde_json::Value>,
113 #[serde(default)]
115 pub slots: BTreeMap<String, Vec<ElementSource>>,
116 #[serde(default)]
118 pub elements: Vec<ElementSource>,
119}
120
121#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
123#[serde(deny_unknown_fields)]
124pub struct ThemeSource {
125 #[serde(default)]
127 pub extends: Option<String>,
128 #[serde(default)]
130 pub tokens: BTreeMap<String, serde_json::Value>,
131 #[serde(default)]
133 pub style: StyleSource,
134}
135
136#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
138#[serde(default, deny_unknown_fields)]
139pub struct StyleSource {
140 pub fill: Option<ColorSource>,
142 pub stroke: Option<ColorSource>,
144 pub stroke_width: Option<Length>,
146 pub stroke_sides: Option<crate::StrokeSides>,
148 pub opacity: Option<u32>,
150 pub font: Option<String>,
152 pub font_size: Option<Length>,
154 pub line_height: Option<u32>,
156 pub color: Option<ColorSource>,
158 pub underline: Option<bool>,
160}
161
162#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
164#[serde(untagged)]
165pub enum ColorSource {
166 Text(String),
168 Typed(Color),
170}
171
172#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
174#[serde(deny_unknown_fields)]
175pub struct ElementStyleRuleSource {
176 pub when: String,
178 pub style: StyleSource,
180}
181
182#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
184#[serde(deny_unknown_fields)]
185pub struct RegionSource {
186 pub x: Length,
188 pub y: Length,
190 pub width: Length,
192 pub height: Length,
194 #[serde(default)]
196 pub collision: Option<CollisionSource>,
197}
198
199#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
201#[serde(rename_all = "snake_case")]
202pub enum DataTypeSource {
203 String,
205 Integer,
207 Decimal,
209 Boolean,
211 Date,
213 DateTime,
215 Duration,
217 Currency,
219 Array,
221 Object,
223 Null,
225}
226
227#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
229#[serde(deny_unknown_fields)]
230pub struct DataFieldSource {
231 #[serde(rename = "type")]
233 pub data_type: DataTypeSource,
234 #[serde(default)]
236 pub nullable: bool,
237 #[serde(default)]
239 pub computed: Option<String>,
240}
241
242#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
244#[serde(deny_unknown_fields)]
245pub struct ElementSource {
246 pub id: String,
248 #[serde(rename = "type")]
250 pub element_type: String,
251 #[serde(default)]
253 pub component: Option<String>,
254 #[serde(default)]
256 pub props: BTreeMap<String, serde_json::Value>,
257 #[serde(default)]
259 pub slots: BTreeMap<String, Vec<ElementSource>>,
260 #[serde(default)]
262 pub x: Option<Length>,
263 #[serde(default)]
265 pub y: Option<Length>,
266 #[serde(default)]
268 pub width: Option<Length>,
269 #[serde(default)]
271 pub height: Option<Length>,
272 #[serde(default)]
274 pub constraints: LayoutConstraints,
275 #[serde(default)]
277 pub align_x: Option<Alignment>,
278 #[serde(default)]
280 pub align_y: Option<Alignment>,
281 #[serde(default)]
283 pub text: Option<String>,
284 #[serde(default)]
286 pub text_segments: Vec<TextSegmentSource>,
287 #[serde(default)]
289 pub text_options: TextSourceOptions,
290 #[serde(default)]
292 pub table: Option<TableSource>,
293 #[serde(default)]
295 pub asset: Option<String>,
296 #[serde(default)]
298 pub image: ImageOptions,
299 #[serde(default)]
301 pub path: Vec<PathCommandSource>,
302 #[serde(default)]
304 pub styles: Vec<String>,
305 #[serde(default)]
307 pub style: StyleSource,
308 #[serde(default)]
310 pub style_rules: Vec<ElementStyleRuleSource>,
311 #[serde(default)]
313 pub transform: TransformSource,
314 #[serde(default)]
316 pub layout: LayoutMode,
317 #[serde(default)]
319 pub distribute: Distribution,
320 #[serde(default = "default_gap")]
322 pub gap: Length,
323 #[serde(default)]
325 pub binding: Option<String>,
326 #[serde(default)]
328 pub when: Option<String>,
329 #[serde(default)]
331 pub repeat: Option<String>,
332 #[serde(default)]
334 pub anchors: BTreeMap<String, String>,
335 #[serde(default)]
337 pub region: Option<String>,
338 #[serde(default)]
340 pub children: Vec<ElementSource>,
341 #[serde(default)]
343 pub locked: bool,
344 #[serde(default)]
346 pub hidden: bool,
347 #[serde(default)]
350 pub keep_with_next: bool,
351 #[serde(default)]
353 pub layer: String,
354 #[serde(default)]
356 pub z_index: i32,
357 #[serde(default)]
359 pub collision: Option<CollisionSource>,
360 #[serde(skip)]
362 #[doc(hidden)]
363 pub provenance_components: Vec<String>,
364 #[serde(skip)]
366 #[doc(hidden)]
367 pub provenance_source: Option<String>,
368}
369
370#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
372#[serde(deny_unknown_fields)]
373pub struct TextSegmentSource {
374 #[serde(default)]
376 pub text: Option<String>,
377 #[serde(default)]
379 pub binding: Option<String>,
380 #[serde(default = "default_gap")]
382 pub gap_after: Length,
383}
384
385#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
387#[serde(untagged)]
388pub enum CollisionSource {
389 Enabled(bool),
391 Advanced(CollisionAdvancedSource),
393}
394
395impl Default for CollisionSource {
396 fn default() -> Self {
397 Self::Advanced(CollisionAdvancedSource::default())
398 }
399}
400
401#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
403#[serde(default, deny_unknown_fields)]
404pub struct CollisionAdvancedSource {
405 pub enabled: bool,
407 pub group: String,
409 pub collides_with: Vec<String>,
411 pub ignore: Vec<String>,
413 pub priority: i32,
415 pub movable: bool,
417 pub bounds: CollisionBounds,
419 pub policy: String,
421}
422
423impl Default for CollisionAdvancedSource {
424 fn default() -> Self {
425 Self {
426 enabled: true,
427 group: "default".to_owned(),
428 collides_with: Vec::new(),
429 ignore: Vec::new(),
430 priority: 0,
431 movable: true,
432 bounds: CollisionBounds::Layout,
433 policy: "push".to_owned(),
434 }
435 }
436}
437
438#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
440#[serde(tag = "command", rename_all = "snake_case", deny_unknown_fields)]
441pub enum PathCommandSource {
442 Move {
444 x: Length,
446 y: Length,
448 },
449 Line {
451 x: Length,
453 y: Length,
455 },
456 Curve {
458 x1: Length,
460 y1: Length,
462 x2: Length,
464 y2: Length,
466 x: Length,
468 y: Length,
470 },
471 Close,
473}
474
475#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
477#[serde(deny_unknown_fields)]
478pub struct AiSourcePolicy {
479 #[serde(default)]
481 pub purpose: String,
482 #[serde(default)]
484 pub rules: Vec<String>,
485 #[serde(default)]
487 pub editable: Vec<String>,
488 #[serde(default)]
490 pub locked: Vec<String>,
491}