geomui 0.5.51 → 0.5.55

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.
@@ -1,19 +1,21 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import type { tParamDef } from 'geometrix';
3
- declare const __propDef: {
4
- props: {
5
- pDef: tParamDef;
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
6
12
  };
7
- events: {
8
- [evt: string]: CustomEvent<any>;
9
- };
10
- slots: {};
11
- exports?: {} | undefined;
12
- bindings?: string | undefined;
13
- };
14
- export type DrawingListProps = typeof __propDef.props;
15
- export type DrawingListEvents = typeof __propDef.events;
16
- export type DrawingListSlots = typeof __propDef.slots;
17
- export default class DrawingList extends SvelteComponent<DrawingListProps, DrawingListEvents, DrawingListSlots> {
13
+ z_$$bindings?: Bindings;
18
14
  }
19
- export {};
15
+ declare const DrawingList: $$__sveltets_2_IsomorphicComponent<{
16
+ pDef: tParamDef;
17
+ }, {
18
+ [evt: string]: CustomEvent<any>;
19
+ }, {}, {}, string>;
20
+ type DrawingList = InstanceType<typeof DrawingList>;
21
+ export default DrawingList;
@@ -1,247 +1,309 @@
1
- <script>import ModalDiag from "./ModalDiag.svelte";
2
- import ModalImg from "./ModalImg.svelte";
3
- import LocStorWrite from "./LocStorWrite.svelte";
4
- import LocStorRead from "./LocStorRead.svelte";
5
- import SimpleDrawing from "./SimpleDrawing.svelte";
6
- import { PType, parseParamFile, createParamFile, adjustZero } from "geometrix";
7
- import { storePV } from "./storePVal";
8
- import { downloadParams, generateUrl } from "./downloadParams";
9
- import { onMount, createEventDispatcher } from "svelte";
10
- import { browser } from "$app/environment";
11
- import { page } from "$app/stores";
12
- import { base } from "$app/paths";
13
- const dispatch = createEventDispatcher();
14
- export let pDef;
15
- export let fgeom;
16
- export let selFace;
17
- export let zAdjust;
18
- export let simTime = 0;
19
- const cAdjustZero = adjustZero();
20
- let inputComment = "";
21
- function paramChange() {
22
- dispatch("paramChg", { foo: "bla" });
23
- }
24
- function tolerantApply(iPartName, ipVal) {
25
- let rMsg = "";
26
- let applyWarn1 = false;
27
- if (iPartName !== pDef.partName) {
28
- rMsg += `warn361: read partName: '${iPartName}' expected partName: '${pDef.partName}'
29
- `;
30
- applyWarn1 = true;
31
- }
32
- let cover = 0;
33
- let uncover = 0;
34
- let equal = 0;
35
- const pNameList = [];
36
- for (const p of pDef.params) {
37
- pNameList.push(p.name);
38
- if (Object.hasOwn(ipVal, p.name)) {
39
- cover += 1;
40
- if ($storePV[pDef.partName][p.name] === ipVal[p.name]) {
41
- equal += 1;
42
- } else {
43
- $storePV[pDef.partName][p.name] = ipVal[p.name];
44
- }
45
- } else {
46
- uncover += 1;
47
- }
48
- }
49
- let notInScope = 0;
50
- for (const pa of Object.keys(ipVal)) {
51
- if (!pNameList.includes(pa)) {
52
- notInScope += 1;
53
- rMsg += `warn363: parameter ${pa} not in the scope of the design (${notInScope})
54
- `;
55
- }
56
- }
57
- const applyWarn2 = notInScope > 0 ? true : false;
58
- const loadDate = (/* @__PURE__ */ new Date()).toLocaleTimeString();
59
- rMsg += `Params loaded at ${loadDate} :`;
60
- rMsg += ` def-nb: ${Object.keys(pDef.params).length}`;
61
- rMsg += `, cover-nb: ${cover}, uncover-nb: ${uncover}
62
- `;
63
- rMsg += ` load-nb: ${Object.keys(ipVal).length}`;
64
- rMsg += `, equal-nb: ${equal}, changed-nb: ${cover - equal}`;
65
- rMsg += `, out-of-scope: ${notInScope}`;
66
- const rApplyWarn = applyWarn1 || applyWarn2;
67
- return [rMsg, rApplyWarn];
68
- }
69
- let loadMsg = "";
70
- let applyWarn = false;
71
- function initParams2() {
72
- if (browser) {
73
- const searchParams = new URLSearchParams($page.url.search);
74
- const pVal2 = {};
75
- for (const [kk, vv] of searchParams) {
76
- const vvn = Number(vv);
77
- if (!isNaN(vvn)) {
78
- pVal2[kk] = vvn;
79
- }
80
- }
81
- if (Object.keys(pVal2).length > 0) {
82
- [loadMsg, applyWarn] = tolerantApply(pDef.partName, pVal2);
83
- }
84
- }
85
- }
86
- function forceInit() {
87
- initParams2();
88
- paramChange();
89
- }
90
- onMount(() => {
91
- forceInit();
92
- });
93
- function loadParams(iStr) {
94
- try {
95
- const [paramJson] = parseParamFile(iStr);
96
- [loadMsg, applyWarn] = tolerantApply(paramJson.partName, paramJson.pVal);
97
- inputComment = paramJson.comment;
98
- paramChange();
99
- } catch (emsg) {
100
- let errMsg = "err723: error by parsing parameter file\n";
101
- errMsg += emsg;
102
- loadMsg = errMsg;
103
- applyWarn = true;
104
- }
105
- }
106
- async function loadFile(fileP) {
107
- const fText = await fileP.text();
108
- loadParams(fText);
109
- }
110
- function loadParamFromFile(eve) {
111
- if (eve.target) {
112
- const paramFiles = eve.target.files;
113
- if (paramFiles) {
114
- loadFile(paramFiles[0]);
115
- }
116
- }
117
- }
118
- function downloadParams2() {
119
- downloadParams(pDef.partName, $storePV[pDef.partName], inputComment);
120
- }
121
- let modalLoadDefault = false;
122
- let modalLoadLocal = false;
123
- let modalSaveUrl = false;
124
- let modalSaveLocal = false;
125
- function loadDefaults() {
126
- const pInit = {};
127
- for (const p of pDef.params) {
128
- pInit[p.name] = p.init;
129
- }
130
- [loadMsg, applyWarn] = tolerantApply(pDef.partName, pInit);
131
- }
132
- let locStorRname;
133
- function loadLocStor() {
134
- if (locStorRname !== void 0 && locStorRname !== "") {
135
- const storeKey = `${pDef.partName}_${locStorRname}`;
136
- if (browser) {
137
- const storeStr = window.localStorage.getItem(storeKey);
138
- if (storeStr === null) {
139
- loadMsg = `Warn157: localStorage key ${storeKey} is null`;
140
- applyWarn = true;
141
- } else {
142
- loadParams(storeStr);
143
- }
144
- }
145
- } else {
146
- loadMsg = "Warn239: No valid name for loading from localStorage!";
147
- applyWarn = true;
148
- }
149
- }
150
- let locStorWname;
151
- function saveInLocStor() {
152
- if (locStorWname !== void 0 && locStorWname !== "") {
153
- const storeKey = `${pDef.partName}_${locStorWname}`;
154
- const re2 = /\..*$/;
155
- const lastModif = (/* @__PURE__ */ new Date()).toISOString().replace(re2, "");
156
- const storeAllStr = createParamFile(
157
- lastModif,
158
- pDef.partName,
159
- $storePV[pDef.partName],
160
- inputComment
161
- );
162
- if (browser) {
163
- window.localStorage.setItem(storeKey, storeAllStr);
164
- }
165
- } else {
166
- console.log("Warn639: No valid name for writing to localStorage!");
167
- }
168
- }
169
- let pUrl = "";
170
- function generateUrl2() {
171
- const url1 = generateUrl($page.url.href, $storePV[pDef.partName], false);
172
- return url1.toString();
173
- }
174
- function openModalUrl() {
175
- pUrl = generateUrl2();
176
- modalSaveUrl = true;
177
- }
178
- function saveAsUrl() {
179
- }
180
- let paramSvg = `${base}/pgdsvg/default_param_blank.svg`;
181
- function paramPict(keyName) {
182
- paramSvg = `${base}/pgdsvg/default_param_blank.svg`;
183
- if (Object.keys(pDef.paramSvg).includes(keyName)) {
184
- paramSvg = `${base}/pgdsvg/${pDef.paramSvg[keyName]}`;
185
- }
186
- }
187
- let prePartName = "";
188
- function paramPict2(idx, pDef_page) {
189
- if (prePartName !== pDef.partName) {
190
- const paramNb = Object.keys($storePV[pDef_page]).length;
191
- if (idx < paramNb) {
192
- paramPict(Object.keys($storePV[pDef_page])[idx]);
193
- }
194
- }
195
- }
196
- $: paramPict2(0, pDef.partName);
197
- let modalImg = false;
198
- function showSvg() {
199
- modalImg = true;
200
- }
201
- function makeHTable(iParams) {
202
- const rHTable = [];
203
- const sectionMain = {
204
- sectionName: "main",
205
- sectionID: "g0main",
206
- sectionVisible: false,
207
- params: []
208
- };
209
- let section = sectionMain;
210
- let sectionID = 0;
211
- for (const param of iParams) {
212
- if (param.pType === PType.eSectionSeparator) {
213
- rHTable.push(section);
214
- sectionID += 1;
215
- const sectionNew = {
216
- sectionName: param.name,
217
- sectionID: `g${sectionID}${param.name}`,
218
- sectionVisible: true,
219
- params: []
220
- };
221
- section = sectionNew;
222
- } else {
223
- section.params.push(param);
224
- }
225
- }
226
- rHTable.push(section);
227
- return rHTable;
228
- }
229
- function makeHTableVis(iHTable) {
230
- const rVis = {};
231
- for (const section of iHTable) {
232
- rVis[section.sectionID] = section.sectionVisible;
233
- }
234
- return rVis;
235
- }
236
- let htable;
237
- let htableVis;
238
- $: {
239
- htable = makeHTable(pDef.params);
240
- if (prePartName !== pDef.partName) {
241
- prePartName = pDef.partName;
242
- htableVis = makeHTableVis(htable);
243
- }
244
- }
1
+ <script lang="ts">
2
+ //import type { tOkFunc } from './ModalDiag.svelte';
3
+ import ModalDiag from './ModalDiag.svelte';
4
+ import ModalImg from './ModalImg.svelte';
5
+ import LocStorWrite from './LocStorWrite.svelte';
6
+ import LocStorRead from './LocStorRead.svelte';
7
+ import SimpleDrawing from './SimpleDrawing.svelte';
8
+ import type { tParam, tParamDef, tParamVal, tGeomFunc, tCanvasAdjust } from 'geometrix';
9
+ import { PType, parseParamFile, createParamFile, adjustZero } from 'geometrix';
10
+ import { storePV } from './storePVal';
11
+ import { downloadParams, generateUrl } from './downloadParams';
12
+ import { onMount, createEventDispatcher } from 'svelte';
13
+ import { browser } from '$app/environment';
14
+ import { page } from '$app/stores';
15
+ import { base } from '$app/paths';
16
+
17
+ const dispatch = createEventDispatcher();
18
+
19
+ export let pDef: tParamDef;
20
+ export let fgeom: tGeomFunc;
21
+ export let selFace: string;
22
+ export let zAdjust: tCanvasAdjust;
23
+ export let simTime = 0;
24
+
25
+ const cAdjustZero = adjustZero();
26
+ let inputComment = '';
27
+
28
+ // initialization
29
+ function paramChange() {
30
+ dispatch('paramChg', { foo: 'bla' });
31
+ }
32
+ // tolerant applyParamVal
33
+ function tolerantApply(iPartName: string, ipVal: tParamVal): [string, boolean] {
34
+ let rMsg = '';
35
+ // partName
36
+ let applyWarn1 = false;
37
+ if (iPartName !== pDef.partName) {
38
+ rMsg += `warn361: read partName: '${iPartName}' expected partName: '${pDef.partName}'\n`;
39
+ applyWarn1 = true;
40
+ }
41
+ // forward
42
+ let cover = 0;
43
+ let uncover = 0;
44
+ let equal = 0;
45
+ const pNameList: string[] = [];
46
+ for (const p of pDef.params) {
47
+ pNameList.push(p.name);
48
+ if (Object.hasOwn(ipVal, p.name)) {
49
+ cover += 1;
50
+ if ($storePV[pDef.partName][p.name] === ipVal[p.name]) {
51
+ equal += 1;
52
+ } else {
53
+ $storePV[pDef.partName][p.name] = ipVal[p.name];
54
+ }
55
+ } else {
56
+ uncover += 1;
57
+ }
58
+ }
59
+ // backward
60
+ let notInScope = 0;
61
+ for (const pa of Object.keys(ipVal)) {
62
+ if (!pNameList.includes(pa)) {
63
+ notInScope += 1;
64
+ rMsg += `warn363: parameter ${pa} not in the scope of the design (${notInScope})\n`;
65
+ }
66
+ }
67
+ const applyWarn2 = notInScope > 0 ? true : false;
68
+ const loadDate = new Date().toLocaleTimeString();
69
+ rMsg += `Params loaded at ${loadDate} :`;
70
+ rMsg += ` def-nb: ${Object.keys(pDef.params).length}`;
71
+ rMsg += `, cover-nb: ${cover}, uncover-nb: ${uncover}\n`;
72
+ rMsg += ` load-nb: ${Object.keys(ipVal).length}`;
73
+ rMsg += `, equal-nb: ${equal}, changed-nb: ${cover - equal}`;
74
+ rMsg += `, out-of-scope: ${notInScope}`;
75
+ const rApplyWarn = applyWarn1 || applyWarn2;
76
+ return [rMsg, rApplyWarn];
77
+ }
78
+ //function initParams1() {
79
+ // for (const p of pDef.params) {
80
+ // $storePV[pDef.partName][p.name] = p.init;
81
+ // }
82
+ //}
83
+ // load parameters
84
+ let loadMsg = '';
85
+ let applyWarn = false;
86
+ function initParams2() {
87
+ if (browser) {
88
+ const searchParams = new URLSearchParams($page.url.search);
89
+ const pVal2: tParamVal = {};
90
+ for (const [kk, vv] of searchParams) {
91
+ //console.log(`dbg638: ${kk} ${vv}`);
92
+ const vvn = Number(vv);
93
+ if (!isNaN(vvn)) {
94
+ pVal2[kk] = vvn;
95
+ }
96
+ }
97
+ //console.log(`dbg072: pVal2.length ${Object.keys(pVal2).length}`);
98
+ if (Object.keys(pVal2).length > 0) {
99
+ [loadMsg, applyWarn] = tolerantApply(pDef.partName, pVal2);
100
+ }
101
+ }
102
+ }
103
+ // Bug? No initialization when loading page! Keep the previous values!
104
+ //initParams1();
105
+ function forceInit() {
106
+ initParams2();
107
+ paramChange();
108
+ }
109
+ onMount(() => {
110
+ forceInit();
111
+ });
112
+ // workaround because $page.url.searchParams contains the new value with some delay
113
+ //function delay(milliseconds: number) {
114
+ // return new Promise((resolve) => {
115
+ // setTimeout(resolve, milliseconds);
116
+ // });
117
+ //}
118
+ //async function forceInit2(partName: string) {
119
+ // await delay(1000);
120
+ // console.log(`dbg081: forceInit: partName ${partName} url ${$page.url}`);
121
+ // forceInit(partName);
122
+ //}
123
+ //$: forceInit2(pDef.partName);
124
+ // end of the workaround
125
+ function loadParams(iStr: string) {
126
+ try {
127
+ const [paramJson] = parseParamFile(iStr);
128
+ [loadMsg, applyWarn] = tolerantApply(paramJson.partName, paramJson.pVal);
129
+ inputComment = paramJson.comment;
130
+ paramChange();
131
+ } catch (emsg) {
132
+ let errMsg = 'err723: error by parsing parameter file\n';
133
+ errMsg += emsg as string;
134
+ loadMsg = errMsg;
135
+ applyWarn = true;
136
+ }
137
+ }
138
+ // load from file
139
+ async function loadFile(fileP: File) {
140
+ const fText = await fileP.text();
141
+ loadParams(fText);
142
+ }
143
+ function loadParamFromFile(eve: Event) {
144
+ if (eve.target) {
145
+ type tEveFileList = FileList | null;
146
+ const paramFiles: tEveFileList = (eve.target as HTMLInputElement).files;
147
+ if (paramFiles) {
148
+ loadFile(paramFiles[0]);
149
+ }
150
+ }
151
+ }
152
+ // download parameters
153
+ function downloadParams2() {
154
+ downloadParams(pDef.partName, $storePV[pDef.partName], inputComment);
155
+ }
156
+ // modal
157
+ let modalLoadDefault = false;
158
+ let modalLoadLocal = false;
159
+ let modalSaveUrl = false;
160
+ let modalSaveLocal = false;
161
+ function loadDefaults() {
162
+ const pInit: tParamVal = {};
163
+ for (const p of pDef.params) {
164
+ pInit[p.name] = p.init;
165
+ }
166
+ [loadMsg, applyWarn] = tolerantApply(pDef.partName, pInit);
167
+ }
168
+ // load parameters from localStorage
169
+ let locStorRname: string;
170
+ function loadLocStor() {
171
+ if (locStorRname !== undefined && locStorRname !== '') {
172
+ const storeKey = `${pDef.partName}_${locStorRname}`;
173
+ //console.log(`load from localStorage ${storeKey}`);
174
+ if (browser) {
175
+ const storeStr = window.localStorage.getItem(storeKey);
176
+ if (storeStr === null) {
177
+ loadMsg = `Warn157: localStorage key ${storeKey} is null`;
178
+ applyWarn = true;
179
+ } else {
180
+ loadParams(storeStr);
181
+ }
182
+ }
183
+ } else {
184
+ loadMsg = 'Warn239: No valid name for loading from localStorage!';
185
+ applyWarn = true;
186
+ }
187
+ }
188
+ // save parameters into localStorage
189
+ let locStorWname: string;
190
+ //$: console.log(`dbg888: ${locStorWname}`);
191
+ function saveInLocStor() {
192
+ if (locStorWname !== undefined && locStorWname !== '') {
193
+ const storeKey = `${pDef.partName}_${locStorWname}`;
194
+ const re2 = /\..*$/;
195
+ const lastModif = new Date().toISOString().replace(re2, '');
196
+ const storeAllStr = createParamFile(
197
+ lastModif,
198
+ pDef.partName,
199
+ $storePV[pDef.partName],
200
+ inputComment
201
+ );
202
+ //console.log(`save in localStorage ${storeKey}`);
203
+ if (browser) {
204
+ window.localStorage.setItem(storeKey, storeAllStr);
205
+ }
206
+ } else {
207
+ console.log('Warn639: No valid name for writing to localStorage!');
208
+ }
209
+ }
210
+ // Save as URL
211
+ let pUrl = '';
212
+ function generateUrl2(): string {
213
+ const url1 = generateUrl($page.url.href, $storePV[pDef.partName], false);
214
+ return url1.toString();
215
+ }
216
+ function openModalUrl() {
217
+ pUrl = generateUrl2();
218
+ modalSaveUrl = true;
219
+ }
220
+ function saveAsUrl() {
221
+ //console.log(`dbg244: voila`);
222
+ }
223
+ // parameter picture
224
+ let paramSvg = `${base}/pgdsvg/default_param_blank.svg`;
225
+ function paramPict(keyName: string) {
226
+ //console.log(`dbg783: ${keyName}`);
227
+ // convention for the file-names of the parameter description
228
+ //paramSvg = `${base}/pgdsvg/${pDef.partName}_${keyName}.svg`;
229
+ paramSvg = `${base}/pgdsvg/default_param_blank.svg`;
230
+ if (Object.keys(pDef.paramSvg).includes(keyName)) {
231
+ paramSvg = `${base}/pgdsvg/${pDef.paramSvg[keyName]}`;
232
+ }
233
+ }
234
+ // TODO: solve properly this workaround (avoiding weird re-trigger)
235
+ let prePartName = '';
236
+ function paramPict2(idx: number, pDef_page: string) {
237
+ //console.log(`dbg283: ${pDef_page}`);
238
+ if (prePartName !== pDef.partName) {
239
+ // workaround for avoiding weird re-trigger
240
+ const paramNb = Object.keys($storePV[pDef_page]).length;
241
+ if (idx < paramNb) {
242
+ paramPict(Object.keys($storePV[pDef_page])[idx]);
243
+ }
244
+ }
245
+ }
246
+ $: paramPict2(0, pDef.partName);
247
+ let modalImg = false;
248
+ function showSvg() {
249
+ //console.log(`dbg231: svgPath: ${svgPath}`);
250
+ modalImg = true;
251
+ }
252
+ // hierarchical table
253
+ interface tHTableSection {
254
+ sectionName: string;
255
+ sectionID: string;
256
+ sectionVisible: boolean;
257
+ params: tParam[];
258
+ }
259
+ type tHTableVis = Record<string, boolean>;
260
+ function makeHTable(iParams: tParam[]): tHTableSection[] {
261
+ const rHTable: tHTableSection[] = [];
262
+ const sectionMain: tHTableSection = {
263
+ sectionName: 'main',
264
+ sectionID: 'g0main',
265
+ sectionVisible: false,
266
+ params: []
267
+ };
268
+ let section = sectionMain;
269
+ let sectionID = 0;
270
+ for (const param of iParams) {
271
+ if (param.pType === PType.eSectionSeparator) {
272
+ rHTable.push(section);
273
+ sectionID += 1;
274
+ const sectionNew: tHTableSection = {
275
+ sectionName: param.name,
276
+ sectionID: `g${sectionID}${param.name}`,
277
+ sectionVisible: true,
278
+ params: []
279
+ };
280
+ section = sectionNew;
281
+ } else {
282
+ section.params.push(param);
283
+ }
284
+ }
285
+ rHTable.push(section);
286
+ return rHTable;
287
+ }
288
+ function makeHTableVis(iHTable: tHTableSection[]): tHTableVis {
289
+ const rVis: tHTableVis = {};
290
+ for (const section of iHTable) {
291
+ rVis[section.sectionID] = section.sectionVisible;
292
+ }
293
+ return rVis;
294
+ }
295
+ let htable: tHTableSection[];
296
+ let htableVis: tHTableVis;
297
+ // TODO: second workaround to be solved properly
298
+ //let prePartName = '';
299
+ $: {
300
+ htable = makeHTable(pDef.params);
301
+ if (prePartName !== pDef.partName) {
302
+ // workaround for avoiding weird re-trigger
303
+ prePartName = pDef.partName;
304
+ htableVis = makeHTableVis(htable);
305
+ }
306
+ }
245
307
  </script>
246
308
 
247
309
  <section>
@@ -276,10 +338,10 @@ $: {
276
338
  rows="3"
277
339
  cols="80"
278
340
  readonly
279
- wrap="off"
341
+ wrap="soft"
280
342
  value={loadMsg}
281
343
  class:colorWarn={applyWarn}
282
- />
344
+ ></textarea>
283
345
  <table>
284
346
  <thead>
285
347
  <tr>
@@ -294,16 +356,18 @@ $: {
294
356
  </tr>
295
357
  </thead>
296
358
  {#each htable as sect, sidx}
297
- <tr class="separator">
298
- <td>{sidx + 1}</td>
299
- <td colspan="4">{sect.sectionName}</td>
300
- <td colspan="3">
301
- <label>
302
- <input type="checkbox" bind:checked={htableVis[sect.sectionID]} />
303
- <span> </span></label
304
- >
305
- </td>
306
- </tr>
359
+ <tbody>
360
+ <tr class="separator">
361
+ <td>{sidx + 1}</td>
362
+ <td colspan="4">{sect.sectionName}</td>
363
+ <td colspan="3">
364
+ <label>
365
+ <input type="checkbox" bind:checked={htableVis[sect.sectionID]} />
366
+ <span> </span></label
367
+ >
368
+ </td>
369
+ </tr>
370
+ </tbody>
307
371
  <tbody class:collaps={htableVis[sect.sectionID]}>
308
372
  {#each sect.params as param, pidx}
309
373
  <tr class:changed={$storePV[pDef.partName][param.name] !== param.init}>
@@ -463,7 +527,7 @@ section > main > table > tbody > tr.changed {
463
527
  background-color: #ded;
464
528
  }
465
529
 
466
- section > main > table > tr.separator {
530
+ section > main > table > tbody > tr.separator {
467
531
  font-weight: 700;
468
532
  background-color: Tan;
469
533
  }
@@ -507,7 +571,6 @@ tr.separator > td > label > input[type=checkbox]:checked + span::after {
507
571
  }
508
572
 
509
573
  section > main > table > thead > tr > td,
510
- section > main > table > tr > td,
511
574
  section > main > table > tbody > tr > td {
512
575
  padding-left: 0.4rem;
513
576
  padding-right: 0.4rem;