appshot-cli 0.1.0

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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +381 -0
  3. package/bin/appshot.js +5 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +31 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/build.d.ts +3 -0
  9. package/dist/commands/build.d.ts.map +1 -0
  10. package/dist/commands/build.js +200 -0
  11. package/dist/commands/build.js.map +1 -0
  12. package/dist/commands/caption.d.ts +3 -0
  13. package/dist/commands/caption.d.ts.map +1 -0
  14. package/dist/commands/caption.js +118 -0
  15. package/dist/commands/caption.js.map +1 -0
  16. package/dist/commands/check.d.ts +3 -0
  17. package/dist/commands/check.d.ts.map +1 -0
  18. package/dist/commands/check.js +121 -0
  19. package/dist/commands/check.js.map +1 -0
  20. package/dist/commands/clean.d.ts +3 -0
  21. package/dist/commands/clean.d.ts.map +1 -0
  22. package/dist/commands/clean.js +133 -0
  23. package/dist/commands/clean.js.map +1 -0
  24. package/dist/commands/init.d.ts +3 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +84 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/localize.d.ts +3 -0
  29. package/dist/commands/localize.d.ts.map +1 -0
  30. package/dist/commands/localize.js +31 -0
  31. package/dist/commands/localize.js.map +1 -0
  32. package/dist/commands/presets.d.ts +3 -0
  33. package/dist/commands/presets.d.ts.map +1 -0
  34. package/dist/commands/presets.js +135 -0
  35. package/dist/commands/presets.js.map +1 -0
  36. package/dist/commands/specs.d.ts +3 -0
  37. package/dist/commands/specs.d.ts.map +1 -0
  38. package/dist/commands/specs.js +69 -0
  39. package/dist/commands/specs.js.map +1 -0
  40. package/dist/commands/validate.d.ts +3 -0
  41. package/dist/commands/validate.d.ts.map +1 -0
  42. package/dist/commands/validate.js +183 -0
  43. package/dist/commands/validate.js.map +1 -0
  44. package/dist/core/app-store-specs.d.ts +55 -0
  45. package/dist/core/app-store-specs.d.ts.map +1 -0
  46. package/dist/core/app-store-specs.js +457 -0
  47. package/dist/core/app-store-specs.js.map +1 -0
  48. package/dist/core/compose.d.ts +30 -0
  49. package/dist/core/compose.d.ts.map +1 -0
  50. package/dist/core/compose.js +420 -0
  51. package/dist/core/compose.js.map +1 -0
  52. package/dist/core/devices.d.ts +50 -0
  53. package/dist/core/devices.d.ts.map +1 -0
  54. package/dist/core/devices.js +404 -0
  55. package/dist/core/devices.js.map +1 -0
  56. package/dist/core/files.d.ts +5 -0
  57. package/dist/core/files.d.ts.map +1 -0
  58. package/dist/core/files.js +35 -0
  59. package/dist/core/files.js.map +1 -0
  60. package/dist/core/frames-analyzer.d.ts +24 -0
  61. package/dist/core/frames-analyzer.d.ts.map +1 -0
  62. package/dist/core/frames-analyzer.js +97 -0
  63. package/dist/core/frames-analyzer.js.map +1 -0
  64. package/dist/core/frames-loader.d.ts +113 -0
  65. package/dist/core/frames-loader.d.ts.map +1 -0
  66. package/dist/core/frames-loader.js +440 -0
  67. package/dist/core/frames-loader.js.map +1 -0
  68. package/dist/core/mask-generator.d.ts +10 -0
  69. package/dist/core/mask-generator.d.ts.map +1 -0
  70. package/dist/core/mask-generator.js +99 -0
  71. package/dist/core/mask-generator.js.map +1 -0
  72. package/dist/core/render.d.ts +10 -0
  73. package/dist/core/render.d.ts.map +1 -0
  74. package/dist/core/render.js +92 -0
  75. package/dist/core/render.js.map +1 -0
  76. package/dist/core/text-renderer.d.ts +18 -0
  77. package/dist/core/text-renderer.d.ts.map +1 -0
  78. package/dist/core/text-renderer.js +148 -0
  79. package/dist/core/text-renderer.js.map +1 -0
  80. package/dist/types.d.ts +57 -0
  81. package/dist/types.d.ts.map +1 -0
  82. package/dist/types.js +2 -0
  83. package/dist/types.js.map +1 -0
  84. package/dist/utils/caption-history.d.ts +35 -0
  85. package/dist/utils/caption-history.d.ts.map +1 -0
  86. package/dist/utils/caption-history.js +233 -0
  87. package/dist/utils/caption-history.js.map +1 -0
  88. package/frames/Frames.json +308 -0
  89. package/frames/MacBook Air 2020.png +0 -0
  90. package/frames/MacBook Air 2022.png +0 -0
  91. package/frames/MacBook Pro 13.png +0 -0
  92. package/frames/MacBook Pro 2021 14.png +0 -0
  93. package/frames/MacBook Pro 2021 16.png +0 -0
  94. package/frames/Watch Series 10 42.png +0 -0
  95. package/frames/Watch Series 10 42_mask.png +0 -0
  96. package/frames/Watch Series 10 46.png +0 -0
  97. package/frames/Watch Series 10 46_mask.png +0 -0
  98. package/frames/Watch Series 4 40.png +0 -0
  99. package/frames/Watch Series 4 44.png +0 -0
  100. package/frames/Watch Series 7 41.png +0 -0
  101. package/frames/Watch Series 7 45.png +0 -0
  102. package/frames/Watch Ultra 2024.png +0 -0
  103. package/frames/iMac 2021.png +0 -0
  104. package/frames/iPad 2021 Landscape.png +0 -0
  105. package/frames/iPad 2021 Portrait.png +0 -0
  106. package/frames/iPad Air 2020 Landscape.png +0 -0
  107. package/frames/iPad Air 2020 Portrait.png +0 -0
  108. package/frames/iPad Pro 2018-2021 11 Landscape.png +0 -0
  109. package/frames/iPad Pro 2018-2021 11 Portrait.png +0 -0
  110. package/frames/iPad Pro 2018-2021 Landscape.png +0 -0
  111. package/frames/iPad Pro 2018-2021 Portrait.png +0 -0
  112. package/frames/iPad Pro 2024 11 Landscape.png +0 -0
  113. package/frames/iPad Pro 2024 11 Portrait.png +0 -0
  114. package/frames/iPad Pro 2024 13 Landscape.png +0 -0
  115. package/frames/iPad Pro 2024 13 Portrait.png +0 -0
  116. package/frames/iPad mini 2021 Landscape.png +0 -0
  117. package/frames/iPad mini 2021 Portrait.png +0 -0
  118. package/frames/iPhone 11 Landscape.png +0 -0
  119. package/frames/iPhone 11 Portrait.png +0 -0
  120. package/frames/iPhone 11 Pro Max Landscape.png +0 -0
  121. package/frames/iPhone 11 Pro Max Portrait.png +0 -0
  122. package/frames/iPhone 11 Pro Portrait.png +0 -0
  123. package/frames/iPhone 12-13 Pro Landscape.png +0 -0
  124. package/frames/iPhone 12-13 Pro Max Landscape.png +0 -0
  125. package/frames/iPhone 12-13 Pro Max Landscape_mask.png +0 -0
  126. package/frames/iPhone 12-13 Pro Max Portrait.png +0 -0
  127. package/frames/iPhone 12-13 Pro Max Portrait_mask.png +0 -0
  128. package/frames/iPhone 12-13 Pro Portrait.png +0 -0
  129. package/frames/iPhone 12-13 mini Landscape.png +0 -0
  130. package/frames/iPhone 12-13 mini Portrait.png +0 -0
  131. package/frames/iPhone 16 Landscape.png +0 -0
  132. package/frames/iPhone 16 Landscape_frame_no_island.png +0 -0
  133. package/frames/iPhone 16 Landscape_mask.png +0 -0
  134. package/frames/iPhone 16 Plus Landscape.png +0 -0
  135. package/frames/iPhone 16 Plus Landscape_frame_no_island.png +0 -0
  136. package/frames/iPhone 16 Plus Landscape_mask.png +0 -0
  137. package/frames/iPhone 16 Plus Portrait.png +0 -0
  138. package/frames/iPhone 16 Plus Portrait_frame_no_island.png +0 -0
  139. package/frames/iPhone 16 Plus Portrait_mask.png +0 -0
  140. package/frames/iPhone 16 Portrait.png +0 -0
  141. package/frames/iPhone 16 Portrait_frame_no_island.png +0 -0
  142. package/frames/iPhone 16 Portrait_mask.png +0 -0
  143. package/frames/iPhone 16 Pro Landscape.png +0 -0
  144. package/frames/iPhone 16 Pro Landscape_frame_no_island.png +0 -0
  145. package/frames/iPhone 16 Pro Landscape_mask.png +0 -0
  146. package/frames/iPhone 16 Pro Max Landscape.png +0 -0
  147. package/frames/iPhone 16 Pro Max Landscape_frame_no_island.png +0 -0
  148. package/frames/iPhone 16 Pro Max Landscape_mask.png +0 -0
  149. package/frames/iPhone 16 Pro Max Portrait.png +0 -0
  150. package/frames/iPhone 16 Pro Max Portrait_frame_no_island.png +0 -0
  151. package/frames/iPhone 16 Pro Max Portrait_mask.png +0 -0
  152. package/frames/iPhone 16 Pro Portrait.png +0 -0
  153. package/frames/iPhone 16 Pro Portrait_frame_no_island.png +0 -0
  154. package/frames/iPhone 16 Pro Portrait_mask.png +0 -0
  155. package/frames/iPhone 8 Plus Landscape.png +0 -0
  156. package/frames/iPhone 8 Plus Portrait.png +0 -0
  157. 2020 SE.png +0 -0
  158. package/frames/version.txt +1 -0
  159. package/package.json +61 -0
@@ -0,0 +1,233 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ const HISTORY_FILE = '.appshot/caption-history.json';
4
+ const MAX_SUGGESTIONS = 100; // Maximum suggestions per category
5
+ const MAX_FREQUENCY_ENTRIES = 200; // Maximum tracked frequencies
6
+ /**
7
+ * Load caption history from file
8
+ */
9
+ export async function loadCaptionHistory() {
10
+ const historyPath = path.join(process.cwd(), HISTORY_FILE);
11
+ try {
12
+ const content = await fs.readFile(historyPath, 'utf8');
13
+ return JSON.parse(content);
14
+ }
15
+ catch {
16
+ // Return default history if file doesn't exist
17
+ return {
18
+ suggestions: {
19
+ global: [
20
+ 'Control Your Audit Flow',
21
+ 'Track Your Progress',
22
+ 'Manage Your Tasks',
23
+ 'Stay Organized',
24
+ 'Beautiful Interface',
25
+ 'Powerful Features',
26
+ 'Simple and Intuitive',
27
+ 'Track Everything',
28
+ 'Get Things Done',
29
+ 'Your Personal Assistant'
30
+ ]
31
+ },
32
+ frequency: {},
33
+ patterns: [
34
+ 'Track your *',
35
+ 'Manage your *',
36
+ 'Control your *',
37
+ 'View your *',
38
+ 'Monitor your *',
39
+ 'Organize your *'
40
+ ],
41
+ lastUpdated: new Date().toISOString()
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * Save caption history to file
47
+ */
48
+ export async function saveCaptionHistory(history) {
49
+ const historyPath = path.join(process.cwd(), HISTORY_FILE);
50
+ const historyDir = path.dirname(historyPath);
51
+ // Ensure directory exists
52
+ await fs.mkdir(historyDir, { recursive: true });
53
+ // Limit the size of stored data
54
+ const trimmedHistory = trimHistory(history);
55
+ trimmedHistory.lastUpdated = new Date().toISOString();
56
+ await fs.writeFile(historyPath, JSON.stringify(trimmedHistory, null, 2), 'utf8');
57
+ }
58
+ /**
59
+ * Update frequency count for a caption
60
+ */
61
+ export function updateFrequency(history, caption) {
62
+ if (!caption || caption.trim() === '')
63
+ return;
64
+ const trimmed = caption.trim();
65
+ history.frequency[trimmed] = (history.frequency[trimmed] || 0) + 1;
66
+ }
67
+ /**
68
+ * Add a caption to suggestions if it's new
69
+ */
70
+ export function addToSuggestions(history, caption, device) {
71
+ if (!caption || caption.trim() === '')
72
+ return;
73
+ const trimmed = caption.trim();
74
+ // Add to global suggestions
75
+ if (!history.suggestions.global.includes(trimmed)) {
76
+ history.suggestions.global.push(trimmed);
77
+ }
78
+ // Add to device-specific suggestions if device is provided
79
+ if (device) {
80
+ if (!history.suggestions[device]) {
81
+ history.suggestions[device] = [];
82
+ }
83
+ const deviceSuggestions = history.suggestions[device];
84
+ if (deviceSuggestions && !deviceSuggestions.includes(trimmed)) {
85
+ deviceSuggestions.push(trimmed);
86
+ }
87
+ }
88
+ }
89
+ /**
90
+ * Extract patterns from a caption
91
+ * e.g., "Track your workouts" -> "Track your *"
92
+ */
93
+ export function extractPatterns(caption) {
94
+ const patterns = [];
95
+ // Common patterns
96
+ const commonStarts = [
97
+ 'Track your', 'Manage your', 'Control your', 'View your',
98
+ 'Monitor your', 'Organize your', 'Create your', 'Build your',
99
+ 'Design your', 'Customize your', 'Share your', 'Sync your'
100
+ ];
101
+ for (const start of commonStarts) {
102
+ if (caption.toLowerCase().startsWith(start.toLowerCase())) {
103
+ patterns.push(`${start} *`);
104
+ break;
105
+ }
106
+ }
107
+ return patterns;
108
+ }
109
+ /**
110
+ * Learn from existing caption files
111
+ */
112
+ export async function learnFromExistingCaptions(history) {
113
+ const captionsDir = path.join(process.cwd(), '.appshot', 'captions');
114
+ try {
115
+ const files = await fs.readdir(captionsDir);
116
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
117
+ for (const file of jsonFiles) {
118
+ const device = file.replace('.json', '');
119
+ const content = await fs.readFile(path.join(captionsDir, file), 'utf8');
120
+ const captions = JSON.parse(content);
121
+ for (const [, captionData] of Object.entries(captions)) {
122
+ if (typeof captionData === 'string') {
123
+ addToSuggestions(history, captionData, device);
124
+ updateFrequency(history, captionData);
125
+ const patterns = extractPatterns(captionData);
126
+ for (const pattern of patterns) {
127
+ if (!history.patterns.includes(pattern)) {
128
+ history.patterns.push(pattern);
129
+ }
130
+ }
131
+ }
132
+ else if (captionData && typeof captionData === 'object') {
133
+ for (const caption of Object.values(captionData)) {
134
+ addToSuggestions(history, caption, device);
135
+ updateFrequency(history, caption);
136
+ const patterns = extractPatterns(caption);
137
+ for (const pattern of patterns) {
138
+ if (!history.patterns.includes(pattern)) {
139
+ history.patterns.push(pattern);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ catch {
148
+ // Captions directory doesn't exist yet, that's okay
149
+ }
150
+ }
151
+ /**
152
+ * Get suggestions for autocomplete
153
+ */
154
+ export function getSuggestions(history, device, currentInput) {
155
+ const suggestions = [];
156
+ const seen = new Set();
157
+ // Helper to add unique suggestions
158
+ const addUnique = (items) => {
159
+ for (const item of items) {
160
+ if (!seen.has(item)) {
161
+ seen.add(item);
162
+ suggestions.push(item);
163
+ }
164
+ }
165
+ };
166
+ // Sort suggestions by frequency
167
+ const sortByFrequency = (items) => {
168
+ return items.sort((a, b) => {
169
+ const freqA = history.frequency[a] || 0;
170
+ const freqB = history.frequency[b] || 0;
171
+ return freqB - freqA;
172
+ });
173
+ };
174
+ // Add device-specific suggestions first (sorted by frequency)
175
+ if (device && history.suggestions[device]) {
176
+ const deviceSuggestions = history.suggestions[device];
177
+ if (deviceSuggestions) {
178
+ addUnique(sortByFrequency([...deviceSuggestions]));
179
+ }
180
+ }
181
+ // Add global suggestions (sorted by frequency)
182
+ addUnique(sortByFrequency([...history.suggestions.global]));
183
+ // If there's current input, also suggest pattern completions
184
+ if (currentInput && currentInput.length > 3) {
185
+ for (const pattern of history.patterns) {
186
+ const patternStart = pattern.replace(' *', '');
187
+ if (currentInput.toLowerCase().startsWith(patternStart.toLowerCase())) {
188
+ // Don't add pattern suggestions, they're just for reference
189
+ // The actual suggestions are already in the list
190
+ }
191
+ }
192
+ }
193
+ return suggestions.slice(0, 15); // Return top 15 suggestions
194
+ }
195
+ /**
196
+ * Trim history to prevent it from growing too large
197
+ */
198
+ function trimHistory(history) {
199
+ // Trim suggestions
200
+ const trimmedSuggestions = {
201
+ global: history.suggestions.global.slice(-MAX_SUGGESTIONS)
202
+ };
203
+ for (const [device, suggestions] of Object.entries(history.suggestions)) {
204
+ if (device !== 'global' && suggestions) {
205
+ trimmedSuggestions[device] = suggestions.slice(-MAX_SUGGESTIONS);
206
+ }
207
+ }
208
+ // Trim frequency entries (keep most frequent)
209
+ const freqEntries = Object.entries(history.frequency);
210
+ freqEntries.sort((a, b) => b[1] - a[1]);
211
+ const trimmedFrequency = Object.fromEntries(freqEntries.slice(0, MAX_FREQUENCY_ENTRIES));
212
+ // Trim patterns
213
+ const trimmedPatterns = history.patterns.slice(-50);
214
+ return {
215
+ suggestions: trimmedSuggestions,
216
+ frequency: trimmedFrequency,
217
+ patterns: trimmedPatterns,
218
+ lastUpdated: history.lastUpdated
219
+ };
220
+ }
221
+ /**
222
+ * Clear caption history
223
+ */
224
+ export async function clearCaptionHistory() {
225
+ const historyPath = path.join(process.cwd(), HISTORY_FILE);
226
+ try {
227
+ await fs.unlink(historyPath);
228
+ }
229
+ catch {
230
+ // File doesn't exist, that's okay
231
+ }
232
+ }
233
+ //# sourceMappingURL=caption-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caption-history.js","sourceRoot":"","sources":["../../src/utils/caption-history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,308 @@
1
+ {
2
+ "Mac": {
3
+ "2020 MacBook Air": {
4
+ "x": "620",
5
+ "y": "652",
6
+ "name": "MacBook Air 2020"
7
+ },
8
+ "2021 iMac": {
9
+ "x": "141",
10
+ "y": "161",
11
+ "name": "iMac 2021"
12
+ },
13
+ "2021 MacBook Pro": {
14
+ "14": {
15
+ "x": "460",
16
+ "y": "300",
17
+ "name": "MacBook Pro 2021 14"
18
+ },
19
+ "16": {
20
+ "x": "442",
21
+ "y": "313",
22
+ "name": "MacBook Pro 2021 16"
23
+ }
24
+ },
25
+ "2022 MacBook Air": {
26
+ "x": "330",
27
+ "y": "218",
28
+ "name": "MacBook Air 2022"
29
+ },
30
+ "MacBook Pro 13": {
31
+ "x": "620",
32
+ "y": "261",
33
+ "name": "MacBook Pro 13"
34
+ }
35
+ },
36
+ "iPhone": {
37
+ "16 and 16 Pro": {
38
+ "Pro": {
39
+ "Landscape": {
40
+ "y": "72",
41
+ "x": "69",
42
+ "name": "iPhone 16 Pro Landscape"
43
+ },
44
+ "Portrait": {
45
+ "y": "69",
46
+ "x": "72",
47
+ "name": "iPhone 16 Pro Portrait"
48
+ }
49
+ },
50
+ "Plus": {
51
+ "Landscape": {
52
+ "y": "90",
53
+ "x": "87",
54
+ "name": "iPhone 16 Plus Landscape"
55
+ },
56
+ "Portrait": {
57
+ "y": "87",
58
+ "x": "90",
59
+ "name": "iPhone 16 Plus Portrait"
60
+ }
61
+ },
62
+ "16": {
63
+ "Portrait": {
64
+ "x": "90",
65
+ "y": "90",
66
+ "name": "iPhone 16 Portrait"
67
+ },
68
+ "Landscape": {
69
+ "x": "90",
70
+ "y": "90",
71
+ "name": "iPhone 16 Landscape"
72
+ }
73
+ },
74
+ "Pro Max": {
75
+ "Portrait": {
76
+ "x": "75",
77
+ "y": "66",
78
+ "name": "iPhone 16 Pro Max Portrait"
79
+ },
80
+ "Landscape": {
81
+ "x": "66",
82
+ "y": "75",
83
+ "name": "iPhone 16 Pro Max Landscape"
84
+ }
85
+ }
86
+ },
87
+ "iPhone 8 and 2020 SE": {
88
+ "Portrait": {
89
+ "x": "125",
90
+ "y": "334",
91
+ "name": "iPhone 8 and 2020 SE"
92
+ }
93
+ },
94
+ "12-13": {
95
+ "mini": {
96
+ "Landscape": {
97
+ "x": "80",
98
+ "y": "80",
99
+ "name": "iPhone 12-13 mini Landscape"
100
+ },
101
+ "Portrait": {
102
+ "x": "80",
103
+ "y": "80",
104
+ "name": "iPhone 12-13 mini Portrait"
105
+ }
106
+ },
107
+ "Pro": {
108
+ "Landscape": {
109
+ "x": "84",
110
+ "y": "115",
111
+ "name": "iPhone 12-13 Pro Landscape"
112
+ },
113
+ "Portrait": {
114
+ "x": "115",
115
+ "y": "84",
116
+ "name": "iPhone 12-13 Pro Portrait"
117
+ }
118
+ },
119
+ "Pro Max": {
120
+ "Landscape": {
121
+ "y": "108",
122
+ "x": "111",
123
+ "name": "iPhone 12-13 Pro Max Landscape"
124
+ },
125
+ "Portrait": {
126
+ "y": "111",
127
+ "x": "108",
128
+ "name": "iPhone 12-13 Pro Max Portrait"
129
+ }
130
+ }
131
+ },
132
+ "11": {
133
+ "Pro Max": {
134
+ "Landscape": {
135
+ "x": "155",
136
+ "y": "179",
137
+ "name": "iPhone 11 Pro Max Landscape"
138
+ },
139
+ "Portrait": {
140
+ "x": "179",
141
+ "y": "155",
142
+ "name": "iPhone 11 Pro Max Portrait"
143
+ }
144
+ },
145
+ "Pro": {
146
+ "Portrait": {
147
+ "x": "238",
148
+ "y": "182",
149
+ "name": "iPhone 11 Pro Portrait"
150
+ }
151
+ },
152
+ "11": {
153
+ "Landscape": {
154
+ "x": "104",
155
+ "y": "86",
156
+ "name": "iPhone 11 Landscape"
157
+ },
158
+ "Portrait": {
159
+ "x": "86",
160
+ "y": "104",
161
+ "name": "iPhone 11 Portrait"
162
+ }
163
+ }
164
+ },
165
+ "8 Plus": {
166
+ "Portrait": {
167
+ "x": "100",
168
+ "y": "310",
169
+ "name": "iPhone 8 Plus Portrait"
170
+ },
171
+ "Landscape": {
172
+ "x": "310",
173
+ "y": "100",
174
+ "name": "iPhone 8 Plus Landscape"
175
+ }
176
+ }
177
+ },
178
+ "iPad": {
179
+ "2021 iPad mini": {
180
+ "Landscape": {
181
+ "x": "142",
182
+ "y": "146",
183
+ "name": "iPad mini 2021 Landscape"
184
+ },
185
+ "Portrait": {
186
+ "x": "146",
187
+ "y": "142",
188
+ "name": "iPad mini 2021 Portrait"
189
+ }
190
+ },
191
+ "2021 iPad": {
192
+ "Landscape": {
193
+ "x": "250",
194
+ "y": "110",
195
+ "name": "iPad 2021 Landscape"
196
+ },
197
+ "Portrait": {
198
+ "x": "110",
199
+ "y": "250",
200
+ "name": "iPad 2021 Portrait"
201
+ }
202
+ },
203
+ "2020 iPad Air": {
204
+ "Landscape": {
205
+ "x": "140",
206
+ "y": "139",
207
+ "name": "iPad Air 2020 Landscape"
208
+ },
209
+ "Portrait": {
210
+ "x": "139",
211
+ "y": "140",
212
+ "name": "iPad Air 2020 Portrait"
213
+ }
214
+ },
215
+ "2018-2021 iPad Pro 11": {
216
+ "Landscape": {
217
+ "x": "120",
218
+ "y": "120",
219
+ "name": "iPad Pro 2018-2021 11 Landscape"
220
+ },
221
+ "Portrait": {
222
+ "x": "120",
223
+ "y": "120",
224
+ "name": "iPad Pro 2018-2021 11 Portrait"
225
+ }
226
+ },
227
+ "2018-2021 iPad Pro": {
228
+ "Landscape": {
229
+ "x": "120",
230
+ "y": "120",
231
+ "name": "iPad Pro 2018-2021 Landscape"
232
+ },
233
+ "Portrait": {
234
+ "x": "120",
235
+ "y": "120",
236
+ "name": "iPad Pro 2018-2021 Portrait"
237
+ }
238
+ },
239
+ "2024 iPad Pro 13": {
240
+ "Landscape": {
241
+ "x": "124",
242
+ "y": "118",
243
+ "name": "iPad Pro 2024 13 Landscape"
244
+ },
245
+ "Portrait": {
246
+ "x": "118",
247
+ "y": "124",
248
+ "name": "iPad Pro 2024 13 Portrait"
249
+ }
250
+ },
251
+ "2024 iPad Pro 11": {
252
+ "Landscape": {
253
+ "x": "110",
254
+ "y": "106",
255
+ "name": "iPad Pro 2024 11 Landscape"
256
+ },
257
+ "Portrait": {
258
+ "x": "95",
259
+ "y": "95",
260
+ "name": "iPad Pro 2024 11 Portrait"
261
+ }
262
+ }
263
+ },
264
+ "Watch": {
265
+ "Ultra": {
266
+ "x": "95",
267
+ "y": "219",
268
+ "name": "Watch Ultra 2024"
269
+ },
270
+ "Series 4": {
271
+ "44": {
272
+ "x": "66",
273
+ "y": "222",
274
+ "name": "Watch Series 4 44"
275
+ },
276
+ "40": {
277
+ "x": "114",
278
+ "y": "308",
279
+ "name": "Watch Series 4 40"
280
+ }
281
+ },
282
+ "Series 7": {
283
+ "45": {
284
+ "x": "72",
285
+ "y": "188",
286
+ "name": "Watch Series 7 45"
287
+ },
288
+ "41": {
289
+ "x": "64",
290
+ "y": "165",
291
+ "name": "Watch Series 7 41"
292
+ }
293
+ },
294
+ "Series 10": {
295
+ "42": {
296
+ "x": "63",
297
+ "y": "167",
298
+ "name": "Watch Series 10 42"
299
+ },
300
+ "46": {
301
+ "x": "72",
302
+ "y": "192",
303
+ "name": "Watch Series 10 46"
304
+ }
305
+ }
306
+ },
307
+ "version": "3.2"
308
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file