@tscircuit/circuit-json-util 0.0.41

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.
package/dist/index.js ADDED
@@ -0,0 +1,1286 @@
1
+ // lib/cju.ts
2
+ import * as Soup from "circuit-json";
3
+ var cju = (soup, options = {}) => {
4
+ let internalStore = soup._internal_store;
5
+ if (!internalStore) {
6
+ internalStore = {
7
+ counts: {}
8
+ };
9
+ soup._internal_store = internalStore;
10
+ for (const elm of soup) {
11
+ const type = elm.type;
12
+ const idVal = elm[`${type}_id`];
13
+ if (!idVal)
14
+ continue;
15
+ const idNum = Number.parseInt(idVal.split("_").pop());
16
+ if (!Number.isNaN(idNum)) {
17
+ internalStore.counts[type] = Math.max(
18
+ internalStore.counts[type] ?? 0,
19
+ idNum
20
+ );
21
+ }
22
+ }
23
+ }
24
+ const su2 = new Proxy(
25
+ {},
26
+ {
27
+ get: (proxy_target, component_type) => {
28
+ if (component_type === "toArray") {
29
+ return () => soup;
30
+ }
31
+ return {
32
+ get: (id) => soup.find(
33
+ (e) => e.type === component_type && e[`${component_type}_id`] === id
34
+ ),
35
+ getUsing: (using) => {
36
+ const keys = Object.keys(using);
37
+ if (keys.length !== 1) {
38
+ throw new Error(
39
+ "getUsing requires exactly one key, e.g. { pcb_component_id }"
40
+ );
41
+ }
42
+ const join_key = keys[0];
43
+ const join_type = join_key.replace("_id", "");
44
+ const joiner = soup.find(
45
+ (e) => e.type === join_type && e[join_key] === using[join_key]
46
+ );
47
+ if (!joiner)
48
+ return null;
49
+ return soup.find(
50
+ (e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]
51
+ );
52
+ },
53
+ getWhere: (where) => {
54
+ const keys = Object.keys(where);
55
+ return soup.find(
56
+ (e) => e.type === component_type && keys.every((key) => e[key] === where[key])
57
+ );
58
+ },
59
+ list: (where) => {
60
+ const keys = !where ? [] : Object.keys(where);
61
+ return soup.filter(
62
+ (e) => e.type === component_type && keys.every((key) => e[key] === where[key])
63
+ );
64
+ },
65
+ insert: (elm) => {
66
+ internalStore.counts[component_type] ??= -1;
67
+ internalStore.counts[component_type]++;
68
+ const index = internalStore.counts[component_type];
69
+ const newElm = {
70
+ type: component_type,
71
+ [`${component_type}_id`]: `${component_type}_${index}`,
72
+ ...elm
73
+ };
74
+ if (options.validateInserts) {
75
+ const parser = Soup[component_type] ?? Soup.any_soup_element;
76
+ parser.parse(newElm);
77
+ }
78
+ soup.push(newElm);
79
+ return newElm;
80
+ },
81
+ delete: (id) => {
82
+ const elm = soup.find(
83
+ (e) => e[`${component_type}_id`] === id
84
+ );
85
+ if (!elm)
86
+ return;
87
+ soup.splice(soup.indexOf(elm), 1);
88
+ },
89
+ update: (id, newProps) => {
90
+ const elm = soup.find(
91
+ (e) => e.type === component_type && e[`${component_type}_id`] === id
92
+ );
93
+ if (!elm)
94
+ return;
95
+ Object.assign(elm, newProps);
96
+ return elm;
97
+ },
98
+ select: (selector) => {
99
+ if (component_type === "source_component") {
100
+ return soup.find(
101
+ (e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")
102
+ );
103
+ } else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
104
+ const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
105
+ const source_component = soup.find(
106
+ (e) => e.type === "source_component" && e.name === component_name
107
+ );
108
+ if (!source_component)
109
+ return null;
110
+ const source_port = soup.find(
111
+ (e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector))
112
+ );
113
+ if (!source_port)
114
+ return null;
115
+ if (component_type === "source_port")
116
+ return source_port;
117
+ if (component_type === "pcb_port") {
118
+ return soup.find(
119
+ (e) => e.type === "pcb_port" && e.source_port_id === source_port.source_port_id
120
+ );
121
+ } else if (component_type === "schematic_port") {
122
+ return soup.find(
123
+ (e) => e.type === "schematic_port" && e.source_port_id === source_port.source_port_id
124
+ );
125
+ }
126
+ }
127
+ }
128
+ };
129
+ }
130
+ }
131
+ );
132
+ return su2;
133
+ };
134
+ cju.unparsed = cju;
135
+ var su = cju;
136
+ var cju_default = cju;
137
+
138
+ // lib/cju-indexed.ts
139
+ import * as Soup2 from "circuit-json";
140
+ function createIdKey(element) {
141
+ const type = element.type;
142
+ return `${type}:${element[`${type}_id`]}`;
143
+ }
144
+ var cjuIndexed = (soup, options = {}) => {
145
+ let internalStore = soup._internal_store_indexed;
146
+ if (!internalStore) {
147
+ internalStore = {
148
+ counts: {},
149
+ indexes: {}
150
+ };
151
+ for (const elm of soup) {
152
+ const type = elm.type;
153
+ const idVal = elm[`${type}_id`];
154
+ if (!idVal)
155
+ continue;
156
+ const idNum = Number.parseInt(idVal.split("_").pop() || "");
157
+ if (!Number.isNaN(idNum)) {
158
+ internalStore.counts[type] = Math.max(
159
+ internalStore.counts[type] ?? 0,
160
+ idNum
161
+ );
162
+ }
163
+ }
164
+ const indexConfig = options.indexConfig || {};
165
+ const indexes = internalStore.indexes;
166
+ if (indexConfig.byId) {
167
+ indexes.byId = /* @__PURE__ */ new Map();
168
+ }
169
+ if (indexConfig.byType) {
170
+ indexes.byType = /* @__PURE__ */ new Map();
171
+ }
172
+ if (indexConfig.byRelation) {
173
+ indexes.byRelation = /* @__PURE__ */ new Map();
174
+ }
175
+ if (indexConfig.bySubcircuit) {
176
+ indexes.bySubcircuit = /* @__PURE__ */ new Map();
177
+ }
178
+ if (indexConfig.byCustomField && indexConfig.byCustomField.length > 0) {
179
+ indexes.byCustomField = /* @__PURE__ */ new Map();
180
+ for (const field of indexConfig.byCustomField) {
181
+ indexes.byCustomField.set(field, /* @__PURE__ */ new Map());
182
+ }
183
+ }
184
+ for (const element of soup) {
185
+ if (indexConfig.byId) {
186
+ const idKey = createIdKey(element);
187
+ indexes.byId.set(idKey, element);
188
+ }
189
+ if (indexConfig.byType) {
190
+ const elementsOfType = indexes.byType.get(element.type) || [];
191
+ elementsOfType.push(element);
192
+ indexes.byType.set(element.type, elementsOfType);
193
+ }
194
+ if (indexConfig.byRelation) {
195
+ const elementEntries = Object.entries(element);
196
+ for (const [key, value] of elementEntries) {
197
+ if (key.endsWith("_id") && key !== `${element.type}_id` && typeof value === "string") {
198
+ const relationTypeMap = indexes.byRelation.get(key) || /* @__PURE__ */ new Map();
199
+ const relatedElements = relationTypeMap.get(value) || [];
200
+ relatedElements.push(element);
201
+ relationTypeMap.set(value, relatedElements);
202
+ indexes.byRelation.set(key, relationTypeMap);
203
+ }
204
+ }
205
+ }
206
+ if (indexConfig.bySubcircuit && "subcircuit_id" in element) {
207
+ const subcircuitId = element.subcircuit_id;
208
+ if (subcircuitId && typeof subcircuitId === "string") {
209
+ const subcircuitElements = indexes.bySubcircuit.get(subcircuitId) || [];
210
+ subcircuitElements.push(element);
211
+ indexes.bySubcircuit.set(subcircuitId, subcircuitElements);
212
+ }
213
+ }
214
+ if (indexConfig.byCustomField && indexes.byCustomField) {
215
+ for (const field of indexConfig.byCustomField) {
216
+ if (field in element) {
217
+ const fieldValue = element[field];
218
+ if (fieldValue !== void 0 && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
219
+ const fieldValueStr = String(fieldValue);
220
+ const fieldMap = indexes.byCustomField.get(field);
221
+ const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
222
+ elementsWithFieldValue.push(element);
223
+ fieldMap.set(fieldValueStr, elementsWithFieldValue);
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ ;
230
+ soup._internal_store_indexed = internalStore;
231
+ }
232
+ const suIndexed = new Proxy(
233
+ {},
234
+ {
235
+ get: (proxy_target, component_type) => {
236
+ if (component_type === "toArray") {
237
+ return () => soup;
238
+ }
239
+ return {
240
+ get: (id) => {
241
+ const indexConfig = options.indexConfig || {};
242
+ if (indexConfig.byId && internalStore.indexes.byId) {
243
+ return internalStore.indexes.byId.get(
244
+ `${component_type}:${id}`
245
+ ) || null;
246
+ }
247
+ if (indexConfig.byType && internalStore.indexes.byType) {
248
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
249
+ return elementsOfType.find(
250
+ (e) => e[`${component_type}_id`] === id
251
+ ) || null;
252
+ }
253
+ return soup.find(
254
+ (e) => e.type === component_type && e[`${component_type}_id`] === id
255
+ ) || null;
256
+ },
257
+ getUsing: (using) => {
258
+ const indexConfig = options.indexConfig || {};
259
+ const keys = Object.keys(using);
260
+ if (keys.length !== 1) {
261
+ throw new Error(
262
+ "getUsing requires exactly one key, e.g. { pcb_component_id }"
263
+ );
264
+ }
265
+ const join_key = keys[0];
266
+ const join_type = join_key.replace("_id", "");
267
+ if (indexConfig.byRelation && internalStore.indexes.byRelation) {
268
+ const relationMap = internalStore.indexes.byRelation.get(join_key);
269
+ if (relationMap) {
270
+ const relatedElements = relationMap.get(using[join_key]) || [];
271
+ const joiner2 = relatedElements.find((e) => e.type === join_type);
272
+ if (!joiner2)
273
+ return null;
274
+ const joinerId = joiner2[`${component_type}_id`];
275
+ if (indexConfig.byId && internalStore.indexes.byId) {
276
+ return internalStore.indexes.byId.get(
277
+ `${component_type}:${joinerId}`
278
+ ) || null;
279
+ }
280
+ if (indexConfig.byType && internalStore.indexes.byType) {
281
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
282
+ return elementsOfType.find(
283
+ (e) => e[`${component_type}_id`] === joinerId
284
+ ) || null;
285
+ }
286
+ return soup.find(
287
+ (e) => e.type === component_type && e[`${component_type}_id`] === joinerId
288
+ ) || null;
289
+ }
290
+ }
291
+ const joiner = soup.find(
292
+ (e) => e.type === join_type && e[join_key] === using[join_key]
293
+ );
294
+ if (!joiner)
295
+ return null;
296
+ return soup.find(
297
+ (e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]
298
+ ) || null;
299
+ },
300
+ getWhere: (where) => {
301
+ const indexConfig = options.indexConfig || {};
302
+ const keys = Object.keys(where);
303
+ if (keys.length === 1 && indexConfig.byCustomField && internalStore.indexes.byCustomField) {
304
+ const field = keys[0];
305
+ const fieldMap = internalStore.indexes.byCustomField.get(field);
306
+ if (fieldMap) {
307
+ const fieldValue = String(where[field]);
308
+ const elementsWithFieldValue = fieldMap.get(fieldValue) || [];
309
+ return elementsWithFieldValue.find(
310
+ (e) => e.type === component_type
311
+ ) || null;
312
+ }
313
+ }
314
+ if ("subcircuit_id" in where && indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit) {
315
+ const subcircuitId = where.subcircuit_id;
316
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
317
+ return subcircuitElements.find(
318
+ (e) => e.type === component_type && keys.every((key) => e[key] === where[key])
319
+ ) || null;
320
+ }
321
+ if (indexConfig.byType && internalStore.indexes.byType) {
322
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
323
+ return elementsOfType.find(
324
+ (e) => keys.every((key) => e[key] === where[key])
325
+ ) || null;
326
+ }
327
+ return soup.find(
328
+ (e) => e.type === component_type && keys.every((key) => e[key] === where[key])
329
+ ) || null;
330
+ },
331
+ list: (where) => {
332
+ const indexConfig = options.indexConfig || {};
333
+ const keys = !where ? [] : Object.keys(where);
334
+ if (keys.length === 0 && indexConfig.byType && internalStore.indexes.byType) {
335
+ return internalStore.indexes.byType.get(component_type) || [];
336
+ }
337
+ if (keys.length === 1 && keys[0] === "subcircuit_id" && indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit) {
338
+ const subcircuitId = where.subcircuit_id;
339
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
340
+ return subcircuitElements.filter(
341
+ (e) => e.type === component_type
342
+ );
343
+ }
344
+ let elementsToFilter;
345
+ if (indexConfig.byType && internalStore.indexes.byType) {
346
+ elementsToFilter = internalStore.indexes.byType.get(component_type) || [];
347
+ } else {
348
+ elementsToFilter = soup.filter((e) => e.type === component_type);
349
+ }
350
+ if (keys.length > 0) {
351
+ return elementsToFilter.filter(
352
+ (e) => keys.every((key) => e[key] === where[key])
353
+ );
354
+ }
355
+ return elementsToFilter;
356
+ },
357
+ insert: (elm) => {
358
+ internalStore.counts[component_type] ??= -1;
359
+ internalStore.counts[component_type]++;
360
+ const index = internalStore.counts[component_type];
361
+ const newElm = {
362
+ type: component_type,
363
+ [`${component_type}_id`]: `${component_type}_${index}`,
364
+ ...elm
365
+ };
366
+ if (options.validateInserts) {
367
+ const parser = Soup2[component_type] ?? Soup2.any_soup_element;
368
+ parser.parse(newElm);
369
+ }
370
+ soup.push(newElm);
371
+ const indexConfig = options.indexConfig || {};
372
+ if (indexConfig.byId && internalStore.indexes.byId) {
373
+ const idKey = createIdKey(newElm);
374
+ internalStore.indexes.byId.set(idKey, newElm);
375
+ }
376
+ if (indexConfig.byType && internalStore.indexes.byType) {
377
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
378
+ elementsOfType.push(newElm);
379
+ internalStore.indexes.byType.set(component_type, elementsOfType);
380
+ }
381
+ if (indexConfig.byRelation && internalStore.indexes.byRelation) {
382
+ const elementEntries = Object.entries(newElm);
383
+ for (const [key, value] of elementEntries) {
384
+ if (key.endsWith("_id") && key !== `${newElm.type}_id` && typeof value === "string") {
385
+ const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map();
386
+ const relatedElements = relationTypeMap.get(value) || [];
387
+ relatedElements.push(newElm);
388
+ relationTypeMap.set(value, relatedElements);
389
+ internalStore.indexes.byRelation.set(key, relationTypeMap);
390
+ }
391
+ }
392
+ }
393
+ if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in newElm) {
394
+ const subcircuitId = newElm.subcircuit_id;
395
+ if (subcircuitId && typeof subcircuitId === "string") {
396
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
397
+ subcircuitElements.push(newElm);
398
+ internalStore.indexes.bySubcircuit.set(
399
+ subcircuitId,
400
+ subcircuitElements
401
+ );
402
+ }
403
+ }
404
+ if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
405
+ for (const field of indexConfig.byCustomField) {
406
+ if (field in newElm) {
407
+ const fieldValue = newElm[field];
408
+ if (fieldValue !== void 0 && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
409
+ const fieldValueStr = String(fieldValue);
410
+ const fieldMap = internalStore.indexes.byCustomField.get(field);
411
+ const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
412
+ elementsWithFieldValue.push(newElm);
413
+ fieldMap.set(fieldValueStr, elementsWithFieldValue);
414
+ }
415
+ }
416
+ }
417
+ }
418
+ return newElm;
419
+ },
420
+ delete: (id) => {
421
+ const indexConfig = options.indexConfig || {};
422
+ let elm;
423
+ if (indexConfig.byId && internalStore.indexes.byId) {
424
+ elm = internalStore.indexes.byId.get(`${component_type}:${id}`);
425
+ } else if (indexConfig.byType && internalStore.indexes.byType) {
426
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
427
+ elm = elementsOfType.find(
428
+ (e) => e[`${component_type}_id`] === id
429
+ );
430
+ } else {
431
+ elm = soup.find((e) => e[`${component_type}_id`] === id);
432
+ }
433
+ if (!elm)
434
+ return;
435
+ const elmIndex = soup.indexOf(elm);
436
+ if (elmIndex >= 0) {
437
+ soup.splice(elmIndex, 1);
438
+ }
439
+ if (indexConfig.byId && internalStore.indexes.byId) {
440
+ const idKey = createIdKey(elm);
441
+ internalStore.indexes.byId.delete(idKey);
442
+ }
443
+ if (indexConfig.byType && internalStore.indexes.byType) {
444
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
445
+ const filteredElements = elementsOfType.filter(
446
+ (e) => e[`${component_type}_id`] !== id
447
+ );
448
+ internalStore.indexes.byType.set(component_type, filteredElements);
449
+ }
450
+ if (indexConfig.byRelation && internalStore.indexes.byRelation) {
451
+ for (const [
452
+ relationKey,
453
+ relationMap
454
+ ] of internalStore.indexes.byRelation.entries()) {
455
+ for (const [relationValue, elements] of relationMap.entries()) {
456
+ const updatedElements = elements.filter((e) => e !== elm);
457
+ if (updatedElements.length === 0) {
458
+ relationMap.delete(relationValue);
459
+ } else {
460
+ relationMap.set(relationValue, updatedElements);
461
+ }
462
+ }
463
+ }
464
+ }
465
+ if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm) {
466
+ const subcircuitId = elm.subcircuit_id;
467
+ if (subcircuitId) {
468
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
469
+ const updatedElements = subcircuitElements.filter(
470
+ (e) => e !== elm
471
+ );
472
+ if (updatedElements.length === 0) {
473
+ internalStore.indexes.bySubcircuit.delete(subcircuitId);
474
+ } else {
475
+ internalStore.indexes.bySubcircuit.set(
476
+ subcircuitId,
477
+ updatedElements
478
+ );
479
+ }
480
+ }
481
+ }
482
+ if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
483
+ for (const fieldMap of internalStore.indexes.byCustomField.values()) {
484
+ for (const [fieldValue, elements] of fieldMap.entries()) {
485
+ const updatedElements = elements.filter((e) => e !== elm);
486
+ if (updatedElements.length === 0) {
487
+ fieldMap.delete(fieldValue);
488
+ } else {
489
+ fieldMap.set(fieldValue, updatedElements);
490
+ }
491
+ }
492
+ }
493
+ }
494
+ },
495
+ update: (id, newProps) => {
496
+ const indexConfig = options.indexConfig || {};
497
+ let elm;
498
+ if (indexConfig.byId && internalStore.indexes.byId) {
499
+ elm = internalStore.indexes.byId.get(`${component_type}:${id}`);
500
+ } else if (indexConfig.byType && internalStore.indexes.byType) {
501
+ const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
502
+ elm = elementsOfType.find(
503
+ (e) => e[`${component_type}_id`] === id
504
+ );
505
+ } else {
506
+ elm = soup.find(
507
+ (e) => e.type === component_type && e[`${component_type}_id`] === id
508
+ );
509
+ }
510
+ if (!elm)
511
+ return null;
512
+ if (indexConfig.byRelation && internalStore.indexes.byRelation) {
513
+ const elementEntries = Object.entries(elm);
514
+ for (const [key, value] of elementEntries) {
515
+ if (key.endsWith("_id") && key !== `${elm.type}_id` && typeof value === "string") {
516
+ if (key in newProps && newProps[key] !== value) {
517
+ const relationTypeMap = internalStore.indexes.byRelation.get(key);
518
+ if (relationTypeMap) {
519
+ const relatedElements = relationTypeMap.get(value) || [];
520
+ const updatedElements = relatedElements.filter(
521
+ (e) => e !== elm
522
+ );
523
+ if (updatedElements.length === 0) {
524
+ relationTypeMap.delete(value);
525
+ } else {
526
+ relationTypeMap.set(value, updatedElements);
527
+ }
528
+ }
529
+ }
530
+ }
531
+ }
532
+ }
533
+ if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm && "subcircuit_id" in newProps) {
534
+ const oldSubcircuitId = elm.subcircuit_id;
535
+ const newSubcircuitId = newProps.subcircuit_id;
536
+ if (oldSubcircuitId !== newSubcircuitId) {
537
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(oldSubcircuitId) || [];
538
+ const updatedElements = subcircuitElements.filter(
539
+ (e) => e !== elm
540
+ );
541
+ if (updatedElements.length === 0) {
542
+ internalStore.indexes.bySubcircuit.delete(oldSubcircuitId);
543
+ } else {
544
+ internalStore.indexes.bySubcircuit.set(
545
+ oldSubcircuitId,
546
+ updatedElements
547
+ );
548
+ }
549
+ }
550
+ }
551
+ if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
552
+ for (const field of indexConfig.byCustomField) {
553
+ if (field in elm && field in newProps && elm[field] !== newProps[field]) {
554
+ const fieldMap = internalStore.indexes.byCustomField.get(field);
555
+ if (fieldMap) {
556
+ const oldValue = String(elm[field]);
557
+ const elements = fieldMap.get(oldValue) || [];
558
+ const updatedElements = elements.filter((e) => e !== elm);
559
+ if (updatedElements.length === 0) {
560
+ fieldMap.delete(oldValue);
561
+ } else {
562
+ fieldMap.set(oldValue, updatedElements);
563
+ }
564
+ }
565
+ }
566
+ }
567
+ }
568
+ Object.assign(elm, newProps);
569
+ if (indexConfig.byRelation && internalStore.indexes.byRelation) {
570
+ const elementEntries = Object.entries(elm);
571
+ for (const [key, value] of elementEntries) {
572
+ if (key.endsWith("_id") && key !== `${elm.type}_id` && typeof value === "string") {
573
+ if (key in newProps) {
574
+ const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map();
575
+ const relatedElements = relationTypeMap.get(value) || [];
576
+ if (!relatedElements.includes(elm)) {
577
+ relatedElements.push(elm);
578
+ relationTypeMap.set(value, relatedElements);
579
+ internalStore.indexes.byRelation.set(key, relationTypeMap);
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm && "subcircuit_id" in newProps) {
586
+ const subcircuitId = elm.subcircuit_id;
587
+ if (subcircuitId && typeof subcircuitId === "string") {
588
+ const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
589
+ if (!subcircuitElements.includes(elm)) {
590
+ subcircuitElements.push(elm);
591
+ internalStore.indexes.bySubcircuit.set(
592
+ subcircuitId,
593
+ subcircuitElements
594
+ );
595
+ }
596
+ }
597
+ }
598
+ if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
599
+ for (const field of indexConfig.byCustomField) {
600
+ if (field in elm && field in newProps) {
601
+ const fieldValue = elm[field];
602
+ if (fieldValue !== void 0 && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
603
+ const fieldValueStr = String(fieldValue);
604
+ const fieldMap = internalStore.indexes.byCustomField.get(field);
605
+ const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
606
+ if (!elementsWithFieldValue.includes(elm)) {
607
+ elementsWithFieldValue.push(elm);
608
+ fieldMap.set(fieldValueStr, elementsWithFieldValue);
609
+ }
610
+ }
611
+ }
612
+ }
613
+ }
614
+ return elm;
615
+ },
616
+ select: (selector) => {
617
+ if (component_type === "source_component") {
618
+ return soup.find(
619
+ (e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")
620
+ ) || null;
621
+ } else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
622
+ const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
623
+ const source_component = soup.find(
624
+ (e) => e.type === "source_component" && e.name === component_name
625
+ );
626
+ if (!source_component)
627
+ return null;
628
+ const source_port = soup.find(
629
+ (e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector))
630
+ );
631
+ if (!source_port)
632
+ return null;
633
+ if (component_type === "source_port")
634
+ return source_port;
635
+ if (component_type === "pcb_port") {
636
+ return soup.find(
637
+ (e) => e.type === "pcb_port" && e.source_port_id === source_port.source_port_id
638
+ ) || null;
639
+ } else if (component_type === "schematic_port") {
640
+ return soup.find(
641
+ (e) => e.type === "schematic_port" && e.source_port_id === source_port.source_port_id
642
+ ) || null;
643
+ }
644
+ }
645
+ return null;
646
+ }
647
+ };
648
+ }
649
+ }
650
+ );
651
+ return suIndexed;
652
+ };
653
+ cjuIndexed.unparsed = cjuIndexed;
654
+ var cju_indexed_default = cjuIndexed;
655
+
656
+ // lib/transform-soup-elements.ts
657
+ import { applyToPoint, decomposeTSR } from "transformation-matrix";
658
+
659
+ // lib/direction-to-vec.ts
660
+ var directionToVec = (direction) => {
661
+ if (direction === "up")
662
+ return { x: 0, y: 1 };
663
+ else if (direction === "down")
664
+ return { x: 0, y: -1 };
665
+ else if (direction === "left")
666
+ return { x: -1, y: 0 };
667
+ else if (direction === "right")
668
+ return { x: 1, y: 0 };
669
+ else
670
+ throw new Error("Invalid direction");
671
+ };
672
+ var vecToDirection = ({ x, y }) => {
673
+ if (x > y)
674
+ y = 0;
675
+ if (y > x)
676
+ x = 0;
677
+ if (x > 0 && y === 0)
678
+ return "right";
679
+ else if (x < 0 && y === 0)
680
+ return "left";
681
+ else if (x === 0 && y > 0)
682
+ return "up";
683
+ else if (x === 0 && y < 0)
684
+ return "down";
685
+ else
686
+ throw new Error(`Invalid vector for direction conversion (${x}, ${y})`);
687
+ };
688
+ var rotateClockwise = (direction) => {
689
+ if (direction === "up")
690
+ return "right";
691
+ else if (direction === "right")
692
+ return "down";
693
+ else if (direction === "down")
694
+ return "left";
695
+ else if (direction === "left")
696
+ return "up";
697
+ throw new Error(`Invalid direction: ${direction}`);
698
+ };
699
+ var rotateCounterClockwise = (direction) => {
700
+ if (direction === "up")
701
+ return "left";
702
+ else if (direction === "left")
703
+ return "down";
704
+ else if (direction === "down")
705
+ return "right";
706
+ else if (direction === "right")
707
+ return "up";
708
+ throw new Error(`Invalid direction: ${direction}`);
709
+ };
710
+ var rotateDirection = (direction, num90DegreeClockwiseTurns) => {
711
+ while (num90DegreeClockwiseTurns > 0) {
712
+ direction = rotateClockwise(direction);
713
+ num90DegreeClockwiseTurns--;
714
+ }
715
+ while (num90DegreeClockwiseTurns < 0) {
716
+ direction = rotateCounterClockwise(direction);
717
+ num90DegreeClockwiseTurns++;
718
+ }
719
+ return direction;
720
+ };
721
+ var oppositeDirection = (direction) => {
722
+ if (direction === "up")
723
+ return "down";
724
+ else if (direction === "down")
725
+ return "up";
726
+ else if (direction === "left")
727
+ return "right";
728
+ else if (direction === "right")
729
+ return "left";
730
+ throw new Error(`Invalid direction: ${direction}`);
731
+ };
732
+ var oppositeSide = (sideOrDir) => {
733
+ if (sideOrDir === "top" || sideOrDir === "up")
734
+ return "bottom";
735
+ else if (sideOrDir === "bottom" || sideOrDir === "down")
736
+ return "top";
737
+ else if (sideOrDir === "left")
738
+ return "right";
739
+ else if (sideOrDir === "right")
740
+ return "left";
741
+ throw new Error(`Invalid sideOrDir: ${sideOrDir}`);
742
+ };
743
+
744
+ // lib/transform-soup-elements.ts
745
+ var transformSchematicElement = (elm, matrix) => {
746
+ if (elm.type === "schematic_component") {
747
+ elm.center = applyToPoint(matrix, elm.center);
748
+ } else if (elm.type === "schematic_port") {
749
+ elm.center = applyToPoint(matrix, elm.center);
750
+ if (elm.facing_direction) {
751
+ elm.facing_direction = rotateDirection(
752
+ elm.facing_direction,
753
+ -(Math.atan2(matrix.b, matrix.a) / Math.PI) * 2
754
+ );
755
+ }
756
+ } else if (elm.type === "schematic_text") {
757
+ elm.position = applyToPoint(matrix, elm.position);
758
+ } else if (elm.type === "schematic_trace") {
759
+ } else if (elm.type === "schematic_box") {
760
+ const { x, y } = applyToPoint(matrix, { x: elm.x, y: elm.y });
761
+ elm.x = x;
762
+ elm.y = y;
763
+ } else if (elm.type === "schematic_line") {
764
+ const { x: x1, y: y1 } = applyToPoint(matrix, { x: elm.x1, y: elm.y1 });
765
+ const { x: x2, y: y2 } = applyToPoint(matrix, { x: elm.x2, y: elm.y2 });
766
+ elm.x1 = x1;
767
+ elm.y1 = y1;
768
+ elm.x2 = x2;
769
+ elm.y2 = y2;
770
+ }
771
+ return elm;
772
+ };
773
+ var transformSchematicElements = (elms, matrix) => {
774
+ return elms.map((elm) => transformSchematicElement(elm, matrix));
775
+ };
776
+ var transformPCBElement = (elm, matrix) => {
777
+ if (elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "pcb_via" || elm.type === "pcb_smtpad" || elm.type === "pcb_port") {
778
+ const { x, y } = applyToPoint(matrix, { x: elm.x, y: elm.y });
779
+ elm.x = x;
780
+ elm.y = y;
781
+ } else if (elm.type === "pcb_keepout" || elm.type === "pcb_board") {
782
+ elm.center = applyToPoint(matrix, elm.center);
783
+ } else if (elm.type === "pcb_silkscreen_text" || elm.type === "pcb_fabrication_note_text") {
784
+ elm.anchor_position = applyToPoint(matrix, elm.anchor_position);
785
+ } else if (elm.type === "pcb_silkscreen_circle" || elm.type === "pcb_silkscreen_rect" || elm.type === "pcb_component") {
786
+ elm.center = applyToPoint(matrix, elm.center);
787
+ } else if (elm.type === "pcb_silkscreen_path" || elm.type === "pcb_trace" || elm.type === "pcb_fabrication_note_path") {
788
+ elm.route = elm.route.map((rp) => {
789
+ const tp = applyToPoint(matrix, rp);
790
+ rp.x = tp.x;
791
+ rp.y = tp.y;
792
+ return rp;
793
+ });
794
+ } else if (elm.type === "pcb_silkscreen_line") {
795
+ const p1 = { x: elm.x1, y: elm.y1 };
796
+ const p2 = { x: elm.x2, y: elm.y2 };
797
+ const p1t = applyToPoint(matrix, p1);
798
+ const p2t = applyToPoint(matrix, p2);
799
+ elm.x1 = p1t.x;
800
+ elm.y1 = p1t.y;
801
+ elm.x2 = p2t.x;
802
+ elm.y2 = p2t.y;
803
+ } else if (elm.type === "cad_component") {
804
+ const newPos = applyToPoint(matrix, {
805
+ x: elm.position.x,
806
+ y: elm.position.y
807
+ });
808
+ elm.position.x = newPos.x;
809
+ elm.position.y = newPos.y;
810
+ }
811
+ return elm;
812
+ };
813
+ var transformPCBElements = (elms, matrix) => {
814
+ const tsr = decomposeTSR(matrix);
815
+ const flipPadWidthHeight = Math.round(tsr.rotation.angle / (Math.PI / 2)) % 2 === 1;
816
+ let transformedElms = elms.map((elm) => transformPCBElement(elm, matrix));
817
+ if (flipPadWidthHeight) {
818
+ transformedElms = transformedElms.map((elm) => {
819
+ if (elm.type === "pcb_smtpad" && elm.shape === "rect") {
820
+ ;
821
+ [elm.width, elm.height] = [elm.height, elm.width];
822
+ }
823
+ return elm;
824
+ });
825
+ }
826
+ return transformedElms;
827
+ };
828
+
829
+ // lib/apply-selector.ts
830
+ import * as parsel from "parsel-js";
831
+
832
+ // lib/convert-abbreviation-to-soup-element-type.ts
833
+ var convertAbbrToType = (abbr) => {
834
+ switch (abbr) {
835
+ case "port":
836
+ return "source_port";
837
+ case "net":
838
+ return "source_net";
839
+ case "power":
840
+ return "simple_power_source";
841
+ }
842
+ return abbr;
843
+ };
844
+
845
+ // lib/apply-selector.ts
846
+ var filterByType = (elements, type) => {
847
+ type = convertAbbrToType(type);
848
+ return elements.filter(
849
+ (elm) => "ftype" in elm && elm.ftype === type || elm.type === type
850
+ );
851
+ };
852
+ var applySelector = (elements, selectorRaw) => {
853
+ const selectorAST = parsel.parse(selectorRaw);
854
+ return applySelectorAST(elements, selectorAST);
855
+ };
856
+ var doesElmMatchClassName = (elm, className) => "name" in elm && elm.name === className || "port_hints" in elm && elm.port_hints?.includes(className);
857
+ var applySelectorAST = (elements, selectorAST) => {
858
+ switch (selectorAST.type) {
859
+ case "complex": {
860
+ switch (selectorAST.combinator) {
861
+ case " ":
862
+ case ">": {
863
+ const { left, right } = selectorAST;
864
+ if (left.type === "class" || left.type === "type") {
865
+ let matchElms;
866
+ if (left.type === "class") {
867
+ matchElms = elements.filter(
868
+ (elm) => doesElmMatchClassName(elm, left.name)
869
+ );
870
+ } else if (left.type === "type") {
871
+ matchElms = filterByType(elements, left.name);
872
+ } else {
873
+ matchElms = [];
874
+ }
875
+ const childrenOfMatchingElms = matchElms.flatMap(
876
+ (matchElm) => elements.filter(
877
+ (elm) => elm[`${matchElm.type}_id`] === matchElm[`${matchElm.type}_id`] && elm !== matchElm
878
+ )
879
+ );
880
+ return applySelectorAST(childrenOfMatchingElms, right);
881
+ } else {
882
+ throw new Error(`unsupported selector type "${left.type}" `);
883
+ }
884
+ }
885
+ default: {
886
+ throw new Error(
887
+ `Couldn't apply selector AST for complex combinator "${selectorAST.combinator}"`
888
+ );
889
+ }
890
+ }
891
+ return [];
892
+ }
893
+ case "compound": {
894
+ const conditionsToMatch = selectorAST.list.map((part) => {
895
+ switch (part.type) {
896
+ case "class": {
897
+ return (elm) => doesElmMatchClassName(elm, part.name);
898
+ }
899
+ case "type": {
900
+ const name = convertAbbrToType(part.name);
901
+ return (elm) => elm.type === name;
902
+ }
903
+ }
904
+ });
905
+ return elements.filter(
906
+ (elm) => conditionsToMatch.every((condFn) => condFn?.(elm))
907
+ );
908
+ }
909
+ case "type": {
910
+ return filterByType(elements, selectorAST.name);
911
+ }
912
+ case "class": {
913
+ return elements.filter(
914
+ (elm) => doesElmMatchClassName(elm, selectorAST.name)
915
+ );
916
+ }
917
+ default: {
918
+ throw new Error(
919
+ `Couldn't apply selector AST for type: "${selectorAST.type}" ${JSON.stringify(selectorAST, null, " ")}`
920
+ );
921
+ }
922
+ }
923
+ };
924
+
925
+ // lib/get-element-id.ts
926
+ var getElementId = (elm) => {
927
+ const type = elm.type;
928
+ const id = elm[`${type}_id`];
929
+ return id;
930
+ };
931
+
932
+ // lib/get-element-by-id.ts
933
+ var getElementById = (soup, id) => {
934
+ return soup.find((elm) => getElementId(elm) === id) ?? null;
935
+ };
936
+
937
+ // lib/readable-name-functions/get-readable-name-for-pcb-trace.ts
938
+ function getReadableNameForPcbTrace(soup, pcb_trace_id) {
939
+ const pcbTrace = cju(soup).pcb_trace.get(pcb_trace_id);
940
+ if (!pcbTrace) {
941
+ return `trace[${pcb_trace_id}]`;
942
+ }
943
+ const connectedPcbPortIds = pcbTrace.route.flatMap((point) => [point.start_pcb_port_id, point.end_pcb_port_id]).filter(Boolean);
944
+ if (connectedPcbPortIds.length === 0) {
945
+ return `trace[${pcb_trace_id}]`;
946
+ }
947
+ function getComponentAndPortInfo(pcb_port_id) {
948
+ const pcbPort = cju(soup).pcb_port.get(pcb_port_id);
949
+ if (!pcbPort)
950
+ return null;
951
+ const pcbComponent = cju(soup).pcb_component.get(pcbPort.pcb_component_id);
952
+ if (!pcbComponent)
953
+ return null;
954
+ const sourceComponent = cju(soup).source_component.get(
955
+ pcbComponent.source_component_id
956
+ );
957
+ if (!sourceComponent)
958
+ return null;
959
+ const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id);
960
+ const portHint = sourcePort?.port_hints ? sourcePort.port_hints[1] : "";
961
+ return {
962
+ componentName: sourceComponent.name,
963
+ portHint
964
+ };
965
+ }
966
+ const selectorParts = connectedPcbPortIds.map((portId) => {
967
+ const info = getComponentAndPortInfo(portId);
968
+ if (info) {
969
+ return `.${info.componentName} > port.${info.portHint}`;
970
+ }
971
+ return `port[${portId}]`;
972
+ });
973
+ return `trace[${selectorParts.join(", ")}]`;
974
+ }
975
+
976
+ // lib/readable-name-functions/get-readable-name-for-pcb-port.ts
977
+ var getReadableNameForPcbPort = (soup, pcb_port_id) => {
978
+ const pcbPort = cju(soup).pcb_port.get(pcb_port_id);
979
+ if (!pcbPort) {
980
+ return `pcb_port[#${pcb_port_id}]`;
981
+ }
982
+ const pcbComponent = cju(soup).pcb_component.get(pcbPort?.pcb_component_id);
983
+ if (!pcbComponent) {
984
+ return `pcb_port[#${pcb_port_id}]`;
985
+ }
986
+ const sourceComponent = cju(soup).source_component.get(
987
+ pcbComponent.source_component_id
988
+ );
989
+ if (!sourceComponent) {
990
+ return `pcb_port[#${pcb_port_id}]`;
991
+ }
992
+ const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id);
993
+ if (!sourcePort) {
994
+ return `pcb_port[#${pcb_port_id}]`;
995
+ }
996
+ let padIdentifier;
997
+ if (sourcePort?.port_hints && sourcePort.port_hints.length > 0) {
998
+ padIdentifier = sourcePort.port_hints[0];
999
+ } else if (sourcePort.port_hints && sourcePort.port_hints.length > 0) {
1000
+ padIdentifier = sourcePort.port_hints[0];
1001
+ } else {
1002
+ padIdentifier = pcb_port_id;
1003
+ }
1004
+ return `pcb_port[.${sourceComponent.name} > .${padIdentifier}]`;
1005
+ };
1006
+
1007
+ // lib/readable-name-functions/get-readable-name-for-pcb-smtpad.ts
1008
+ function getReadableNameForPcbSmtpad(soup, pcb_smtpad_id) {
1009
+ const pcbSmtpad = cju(soup).pcb_smtpad.get(pcb_smtpad_id);
1010
+ if (!pcbSmtpad || !pcbSmtpad.pcb_port_id) {
1011
+ return `smtpad[${pcb_smtpad_id}]`;
1012
+ }
1013
+ return getReadableNameForPcbPort(soup, pcbSmtpad.pcb_port_id);
1014
+ }
1015
+
1016
+ // lib/readable-name-functions/get-readable-name-for-element.ts
1017
+ var getReadableNameForElement = (soup, elm) => {
1018
+ if (typeof elm === "string") {
1019
+ const elmObj = getElementById(soup, elm);
1020
+ if (!elmObj)
1021
+ `unknown (could not find element with id ${elm})`;
1022
+ return getReadableNameForElement(soup, elmObj);
1023
+ }
1024
+ switch (elm.type) {
1025
+ case "pcb_port":
1026
+ return getReadableNameForPcbPort(soup, elm.pcb_port_id);
1027
+ case "pcb_smtpad":
1028
+ return getReadableNameForPcbSmtpad(soup, elm.pcb_smtpad_id);
1029
+ case "pcb_trace":
1030
+ return getReadableNameForPcbTrace(soup, elm.pcb_trace_id);
1031
+ case "source_component":
1032
+ return `source_component[${elm.name}]`;
1033
+ default:
1034
+ return `${elm.type}[#${getElementId(elm)}]`;
1035
+ }
1036
+ };
1037
+
1038
+ // lib/get-bounds-of-pcb-elements.ts
1039
+ var getBoundsOfPcbElements = (elements) => {
1040
+ let minX = Number.POSITIVE_INFINITY;
1041
+ let minY = Number.POSITIVE_INFINITY;
1042
+ let maxX = Number.NEGATIVE_INFINITY;
1043
+ let maxY = Number.NEGATIVE_INFINITY;
1044
+ for (const elm of elements) {
1045
+ if (!elm.type.startsWith("pcb_"))
1046
+ continue;
1047
+ if ("x" in elm && "y" in elm) {
1048
+ minX = Math.min(minX, elm.x);
1049
+ minY = Math.min(minY, elm.y);
1050
+ maxX = Math.max(maxX, elm.x);
1051
+ maxY = Math.max(maxY, elm.y);
1052
+ if ("width" in elm) {
1053
+ maxX = Math.max(maxX, elm.x + elm.width);
1054
+ }
1055
+ if ("height" in elm) {
1056
+ maxY = Math.max(maxY, elm.y + elm.height);
1057
+ }
1058
+ if ("radius" in elm) {
1059
+ minX = Math.min(minX, elm.x - elm.radius);
1060
+ minY = Math.min(minY, elm.y - elm.radius);
1061
+ maxX = Math.max(maxX, elm.x + elm.radius);
1062
+ maxY = Math.max(maxY, elm.y + elm.radius);
1063
+ }
1064
+ } else if (elm.type === "pcb_trace") {
1065
+ for (const point of elm.route) {
1066
+ minX = Math.min(minX, point.x);
1067
+ minY = Math.min(minY, point.y);
1068
+ maxX = Math.max(maxX, point.x);
1069
+ maxY = Math.max(maxY, point.y);
1070
+ }
1071
+ }
1072
+ }
1073
+ return { minX, minY, maxX, maxY };
1074
+ };
1075
+
1076
+ // lib/utils/string-hash.ts
1077
+ function stringHash(str) {
1078
+ let hash = 0;
1079
+ if (str.length == 0)
1080
+ return hash;
1081
+ for (var i = 0; i < str.length; i++) {
1082
+ var char = str.charCodeAt(i);
1083
+ hash = (hash << 5) - hash + char;
1084
+ hash = hash & hash;
1085
+ }
1086
+ return Math.abs(hash);
1087
+ }
1088
+
1089
+ // lib/utils/get-layout-debug-object.ts
1090
+ var nice_color_palettes = [
1091
+ ["#69d2e7", "#a7dbd8", "#e0e4cc", "#f38630", "#fa6900"],
1092
+ ["#fe4365", "#fc9d9a", "#f9cdad", "#c8c8a9", "#83af9b"],
1093
+ ["#ecd078", "#d95b43", "#c02942", "#542437", "#53777a"],
1094
+ ["#556270", "#4ecdc4", "#c7f464", "#ff6b6b", "#c44d58"],
1095
+ ["#774f38", "#e08e79", "#f1d4af", "#ece5ce", "#c5e0dc"],
1096
+ ["#e8ddcb", "#cdb380", "#036564", "#033649", "#031634"],
1097
+ ["#490a3d", "#bd1550", "#e97f02", "#f8ca00", "#8a9b0f"],
1098
+ ["#594f4f", "#547980", "#45ada8", "#9de0ad", "#e5fcc2"],
1099
+ ["#00a0b0", "#6a4a3c", "#cc333f", "#eb6841", "#edc951"],
1100
+ ["#e94e77", "#d68189", "#c6a49a", "#c6e5d9", "#f4ead5"],
1101
+ ["#3fb8af", "#7fc7af", "#dad8a7", "#ff9e9d", "#ff3d7f"],
1102
+ ["#d9ceb2", "#948c75", "#d5ded9", "#7a6a53", "#99b2b7"],
1103
+ ["#ffffff", "#cbe86b", "#f2e9e1", "#1c140d", "#cbe86b"],
1104
+ ["#efffcd", "#dce9be", "#555152", "#2e2633", "#99173c"],
1105
+ ["#343838", "#005f6b", "#008c9e", "#00b4cc", "#00dffc"],
1106
+ ["#413e4a", "#73626e", "#b38184", "#f0b49e", "#f7e4be"],
1107
+ ["#ff4e50", "#fc913a", "#f9d423", "#ede574", "#e1f5c4"],
1108
+ ["#99b898", "#fecea8", "#ff847c", "#e84a5f", "#2a363b"],
1109
+ ["#655643", "#80bca3", "#f6f7bd", "#e6ac27", "#bf4d28"],
1110
+ ["#00a8c6", "#40c0cb", "#f9f2e7", "#aee239", "#8fbe00"],
1111
+ ["#351330", "#424254", "#64908a", "#e8caa4", "#cc2a41"],
1112
+ ["#554236", "#f77825", "#d3ce3d", "#f1efa5", "#60b99a"],
1113
+ ["#5d4157", "#838689", "#a8caba", "#cad7b2", "#ebe3aa"],
1114
+ ["#8c2318", "#5e8c6a", "#88a65e", "#bfb35a", "#f2c45a"],
1115
+ ["#fad089", "#ff9c5b", "#f5634a", "#ed303c", "#3b8183"],
1116
+ ["#ff4242", "#f4fad2", "#d4ee5e", "#e1edb9", "#f0f2eb"],
1117
+ ["#f8b195", "#f67280", "#c06c84", "#6c5b7b", "#355c7d"],
1118
+ ["#d1e751", "#ffffff", "#000000", "#4dbce9", "#26ade4"],
1119
+ ["#1b676b", "#519548", "#88c425", "#bef202", "#eafde6"],
1120
+ ["#5e412f", "#fcebb6", "#78c0a8", "#f07818", "#f0a830"],
1121
+ ["#bcbdac", "#cfbe27", "#f27435", "#f02475", "#3b2d38"],
1122
+ ["#452632", "#91204d", "#e4844a", "#e8bf56", "#e2f7ce"],
1123
+ ["#eee6ab", "#c5bc8e", "#696758", "#45484b", "#36393b"],
1124
+ ["#f0d8a8", "#3d1c00", "#86b8b1", "#f2d694", "#fa2a00"],
1125
+ ["#2a044a", "#0b2e59", "#0d6759", "#7ab317", "#a0c55f"],
1126
+ ["#f04155", "#ff823a", "#f2f26f", "#fff7bd", "#95cfb7"],
1127
+ ["#b9d7d9", "#668284", "#2a2829", "#493736", "#7b3b3b"],
1128
+ ["#bbbb88", "#ccc68d", "#eedd99", "#eec290", "#eeaa88"],
1129
+ ["#b3cc57", "#ecf081", "#ffbe40", "#ef746f", "#ab3e5b"],
1130
+ ["#a3a948", "#edb92e", "#f85931", "#ce1836", "#009989"],
1131
+ ["#300030", "#480048", "#601848", "#c04848", "#f07241"],
1132
+ ["#67917a", "#170409", "#b8af03", "#ccbf82", "#e33258"],
1133
+ ["#aab3ab", "#c4cbb7", "#ebefc9", "#eee0b7", "#e8caaf"],
1134
+ ["#e8d5b7", "#0e2430", "#fc3a51", "#f5b349", "#e8d5b9"],
1135
+ ["#ab526b", "#bca297", "#c5ceae", "#f0e2a4", "#f4ebc3"],
1136
+ ["#607848", "#789048", "#c0d860", "#f0f0d8", "#604848"],
1137
+ ["#b6d8c0", "#c8d9bf", "#dadabd", "#ecdbbc", "#fedcba"],
1138
+ ["#a8e6ce", "#dcedc2", "#ffd3b5", "#ffaaa6", "#ff8c94"],
1139
+ ["#3e4147", "#fffedf", "#dfba69", "#5a2e2e", "#2a2c31"],
1140
+ ["#fc354c", "#29221f", "#13747d", "#0abfbc", "#fcf7c5"],
1141
+ ["#cc0c39", "#e6781e", "#c8cf02", "#f8fcc1", "#1693a7"],
1142
+ ["#1c2130", "#028f76", "#b3e099", "#ffeaad", "#d14334"],
1143
+ ["#a7c5bd", "#e5ddcb", "#eb7b59", "#cf4647", "#524656"],
1144
+ ["#dad6ca", "#1bb0ce", "#4f8699", "#6a5e72", "#563444"],
1145
+ ["#5c323e", "#a82743", "#e15e32", "#c0d23e", "#e5f04c"],
1146
+ ["#edebe6", "#d6e1c7", "#94c7b6", "#403b33", "#d3643b"],
1147
+ ["#fdf1cc", "#c6d6b8", "#987f69", "#e3ad40", "#fcd036"],
1148
+ ["#230f2b", "#f21d41", "#ebebbc", "#bce3c5", "#82b3ae"],
1149
+ ["#b9d3b0", "#81bda4", "#b28774", "#f88f79", "#f6aa93"],
1150
+ ["#3a111c", "#574951", "#83988e", "#bcdea5", "#e6f9bc"],
1151
+ ["#5e3929", "#cd8c52", "#b7d1a3", "#dee8be", "#fcf7d3"],
1152
+ ["#1c0113", "#6b0103", "#a30006", "#c21a01", "#f03c02"],
1153
+ ["#000000", "#9f111b", "#b11623", "#292c37", "#cccccc"],
1154
+ ["#382f32", "#ffeaf2", "#fcd9e5", "#fbc5d8", "#f1396d"],
1155
+ ["#e3dfba", "#c8d6bf", "#93ccc6", "#6cbdb5", "#1a1f1e"],
1156
+ ["#f6f6f6", "#e8e8e8", "#333333", "#990100", "#b90504"],
1157
+ ["#1b325f", "#9cc4e4", "#e9f2f9", "#3a89c9", "#f26c4f"],
1158
+ ["#a1dbb2", "#fee5ad", "#faca66", "#f7a541", "#f45d4c"],
1159
+ ["#c1b398", "#605951", "#fbeec2", "#61a6ab", "#accec0"],
1160
+ ["#5e9fa3", "#dcd1b4", "#fab87f", "#f87e7b", "#b05574"],
1161
+ ["#951f2b", "#f5f4d7", "#e0dfb1", "#a5a36c", "#535233"],
1162
+ ["#8dccad", "#988864", "#fea6a2", "#f9d6ac", "#ffe9af"],
1163
+ ["#2d2d29", "#215a6d", "#3ca2a2", "#92c7a3", "#dfece6"],
1164
+ ["#413d3d", "#040004", "#c8ff00", "#fa023c", "#4b000f"],
1165
+ ["#eff3cd", "#b2d5ba", "#61ada0", "#248f8d", "#605063"],
1166
+ ["#ffefd3", "#fffee4", "#d0ecea", "#9fd6d2", "#8b7a5e"],
1167
+ ["#cfffdd", "#b4dec1", "#5c5863", "#a85163", "#ff1f4c"],
1168
+ ["#9dc9ac", "#fffec7", "#f56218", "#ff9d2e", "#919167"],
1169
+ ["#4e395d", "#827085", "#8ebe94", "#ccfc8e", "#dc5b3e"],
1170
+ ["#a8a7a7", "#cc527a", "#e8175d", "#474747", "#363636"],
1171
+ ["#f8edd1", "#d88a8a", "#474843", "#9d9d93", "#c5cfc6"],
1172
+ ["#046d8b", "#309292", "#2fb8ac", "#93a42a", "#ecbe13"],
1173
+ ["#f38a8a", "#55443d", "#a0cab5", "#cde9ca", "#f1edd0"],
1174
+ ["#a70267", "#f10c49", "#fb6b41", "#f6d86b", "#339194"],
1175
+ ["#ff003c", "#ff8a00", "#fabe28", "#88c100", "#00c176"],
1176
+ ["#ffedbf", "#f7803c", "#f54828", "#2e0d23", "#f8e4c1"],
1177
+ ["#4e4d4a", "#353432", "#94ba65", "#2790b0", "#2b4e72"],
1178
+ ["#0ca5b0", "#4e3f30", "#fefeeb", "#f8f4e4", "#a5b3aa"],
1179
+ ["#4d3b3b", "#de6262", "#ffb88c", "#ffd0b3", "#f5e0d3"],
1180
+ ["#fffbb7", "#a6f6af", "#66b6ab", "#5b7c8d", "#4f2958"],
1181
+ ["#edf6ee", "#d1c089", "#b3204d", "#412e28", "#151101"],
1182
+ ["#9d7e79", "#ccac95", "#9a947c", "#748b83", "#5b756c"],
1183
+ ["#fcfef5", "#e9ffe1", "#cdcfb7", "#d6e6c3", "#fafbe3"],
1184
+ ["#9cddc8", "#bfd8ad", "#ddd9ab", "#f7af63", "#633d2e"],
1185
+ ["#30261c", "#403831", "#36544f", "#1f5f61", "#0b8185"],
1186
+ ["#aaff00", "#ffaa00", "#ff00aa", "#aa00ff", "#00aaff"],
1187
+ ["#d1313d", "#e5625c", "#f9bf76", "#8eb2c5", "#615375"],
1188
+ ["#ffe181", "#eee9e5", "#fad3b2", "#ffba7f", "#ff9c97"],
1189
+ ["#73c8a9", "#dee1b6", "#e1b866", "#bd5532", "#373b44"],
1190
+ ["#805841", "#dcf7f3", "#fffcdd", "#ffd8d8", "#f5a2a2"]
1191
+ ];
1192
+ var getDebugLayoutObject = (lo) => {
1193
+ let {
1194
+ x,
1195
+ y,
1196
+ width,
1197
+ height
1198
+ } = {
1199
+ ...lo,
1200
+ ...lo.size,
1201
+ ...lo.center,
1202
+ ...lo.position
1203
+ };
1204
+ if (lo.x1 !== void 0 && lo.x2 !== void 0 && lo.y1 !== void 0 && lo.y2 !== void 0) {
1205
+ x = (lo.x1 + lo.x2) / 2;
1206
+ y = (lo.y1 + lo.y2) / 2;
1207
+ width = Math.abs(lo.x1 - lo.x2);
1208
+ height = Math.abs(lo.y1 - lo.y2);
1209
+ }
1210
+ const title = lo.text || lo.name || lo.source?.text || lo.source?.name || "?";
1211
+ const content = lo;
1212
+ if (x === void 0 || y === void 0)
1213
+ return null;
1214
+ if (width === void 0) {
1215
+ if ("outer_diameter" in lo) {
1216
+ width = lo.outer_diameter;
1217
+ height = lo.outer_diameter;
1218
+ }
1219
+ }
1220
+ if (width === void 0 || height === void 0) {
1221
+ width = 0.1;
1222
+ height = 0.1;
1223
+ }
1224
+ return {
1225
+ x,
1226
+ y,
1227
+ width,
1228
+ height,
1229
+ title,
1230
+ content,
1231
+ bg_color: nice_color_palettes[stringHash(lo.type || title) % nice_color_palettes.length]?.[4] ?? "#f00"
1232
+ };
1233
+ };
1234
+
1235
+ // lib/utils/is-truthy.ts
1236
+ var isTruthy = (value) => Boolean(value);
1237
+
1238
+ // lib/find-bounds-and-center.ts
1239
+ var findBoundsAndCenter = (elements) => {
1240
+ const debugObjects = elements.filter((elm) => elm.type.startsWith("pcb_")).concat(
1241
+ elements.filter((elm) => elm.type === "pcb_trace").flatMap((elm) => elm.route)
1242
+ ).map((elm) => getDebugLayoutObject(elm)).filter(isTruthy);
1243
+ if (debugObjects.length === 0)
1244
+ return { center: { x: 0, y: 0 }, width: 0, height: 0 };
1245
+ let minX = debugObjects[0].x - debugObjects[0].width / 2;
1246
+ let maxX = debugObjects[0].x + debugObjects[0].width / 2;
1247
+ let minY = debugObjects[0].y - debugObjects[0].height / 2;
1248
+ let maxY = debugObjects[0].y + debugObjects[0].height / 2;
1249
+ for (const obj of debugObjects.slice(1)) {
1250
+ minX = Math.min(minX, obj.x - obj.width / 2);
1251
+ maxX = Math.max(maxX, obj.x + obj.width / 2);
1252
+ minY = Math.min(minY, obj.y - obj.height / 2);
1253
+ maxY = Math.max(maxY, obj.y + obj.height / 2);
1254
+ }
1255
+ const width = maxX - minX;
1256
+ const height = maxY - minY;
1257
+ const center = { x: minX + width / 2, y: minY + height / 2 };
1258
+ return { center, width, height };
1259
+ };
1260
+ export {
1261
+ applySelector,
1262
+ applySelectorAST,
1263
+ cju_default as cju,
1264
+ cju_indexed_default as cjuIndexed,
1265
+ directionToVec,
1266
+ findBoundsAndCenter,
1267
+ getBoundsOfPcbElements,
1268
+ getElementById,
1269
+ getElementId,
1270
+ getReadableNameForElement,
1271
+ getReadableNameForPcbPort,
1272
+ getReadableNameForPcbSmtpad,
1273
+ getReadableNameForPcbTrace,
1274
+ oppositeDirection,
1275
+ oppositeSide,
1276
+ rotateClockwise,
1277
+ rotateCounterClockwise,
1278
+ rotateDirection,
1279
+ su,
1280
+ transformPCBElement,
1281
+ transformPCBElements,
1282
+ transformSchematicElement,
1283
+ transformSchematicElements,
1284
+ vecToDirection
1285
+ };
1286
+ //# sourceMappingURL=index.js.map