@kupcad/ui 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -154,7 +154,10 @@ webview and the desktop app to the language server.
154
154
  Edges, Axes, Grid and Plate toggles; Fit, Persp, and the Iso, Top, Front and Right views, the
155
155
  one looked from pressed, a turn by hand pressing none), the model's parts in its bottom half,
156
156
  each with its colour and copies (a click on one selects its copies, as a click in the viewer
157
- does: `bind:selected`). A bar above: a section through the model along an axis (a solid's: a drawing, which isn't cut, or no model offers none), screenshot, an
157
+ does: `bind:selected`). In a pane narrower than 36em (a phone's) the panel is under the model,
158
+ at most half the pane. The model fills what the rest leave, no less than
159
+ `--kc-model-min-height` (none by default), which a host whose pane is as tall as its content
160
+ sets: the model has no height of its own. A bar above: a section through the model along an axis (a solid's: a drawing, which isn't cut, or no model offers none), screenshot, an
158
161
  `actions` snippet (a host's own buttons, the Export menu), the Panel button, and a `toggles`
159
162
  snippet after it (a host's toggles of its own panes beside the pane, the Parameters button;
160
163
  `.kc-control` with `aria-expanded` gives one the Panel button's look). Below, a status
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kupcad/ui",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "KupCAD's UI: a three.js viewer of a model the core made, for any host (@kupcad/ui/viewer), and the Svelte panels around it (the viewer's pane, parameters, console, a language server's preview), styled by --kc-* tokens.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -36,11 +36,11 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@kupcad/protocol": "0.1.2",
39
+ "@kupcad/protocol": "0.1.4",
40
40
  "three": "^0.186.1"
41
41
  },
42
42
  "devDependencies": {
43
- "@kupcad/wasm": "0.1.2",
43
+ "@kupcad/wasm": "0.1.4",
44
44
  "@playwright/test": "^1.64.1",
45
45
  "@sveltejs/vite-plugin-svelte": "^7.3.1",
46
46
  "@testing-library/svelte": "^5.4.2",
@@ -2,11 +2,13 @@
2
2
  @component
3
3
  The parameters' controls, from the schema a frame (or `kupcad doc`) gives: grouped by their
4
4
  `group:`, each showing the value set in the panel, else the one the run took. `overrides` is
5
- what the panel sets (bindable), each change (and revert) given to `onchange`, which a host
6
- sends to the core; a value refused by the run is shown on its control. A bar at the top, held
7
- there as the panel scrolls, says how many values are set; while any is, its Reset all reverts
8
- them all at once, the panel's refusals with them. The button keeps its place when there is
9
- nothing to reset, so nothing under the bar moves as a first value is set or the last reverted.
5
+ what the panel sets (bindable), each change (and revert) given to `onchange` as plain values,
6
+ which a host sends to the core (to a worker, a webview's host: a list kept in state is a proxy
7
+ that a message can't copy); a value refused by the run is shown on its control. A bar at the
8
+ top, held there as the panel scrolls, says how many values are set; while any is, its Reset
9
+ all reverts them all at once, the panel's refusals with them. The button keeps its place when
10
+ there is nothing to reset, so nothing under the bar moves as a first value is set or the last
11
+ reverted.
10
12
  A value set back to the parameter's own (the one it showed before the panel set it: the run's,
11
13
  the script's or a host's preset's) is a revert, not a value set.
12
14
  -->
@@ -20,6 +22,7 @@
20
22
  withOverride,
21
23
  withoutOverride,
22
24
  } from './params.js';
25
+ import { plainValues } from './values.svelte.js';
23
26
 
24
27
  /** @import { Failure, ParamSpec, ParamValue, ParamValues, UiSchema } from '@kupcad/protocol/types' */
25
28
 
@@ -52,7 +55,7 @@
52
55
  /** @param {ParamValues} next */
53
56
  function change(next) {
54
57
  overrides = next;
55
- onchange?.(next);
58
+ onchange?.(plainValues(next));
56
59
  }
57
60
 
58
61
  /**
@@ -78,9 +78,12 @@
78
78
  </dialog>
79
79
 
80
80
  <style>
81
+ /* In the middle of the window by its own margin, not the browser's default one, which a page's
82
+ reset (Tailwind's) takes away */
81
83
  .kc-shortcuts {
82
84
  width: min(32em, calc(100vw - 32px));
83
85
  max-height: calc(100vh - 64px);
86
+ margin: auto;
84
87
  padding: 16px 20px;
85
88
  font-family: var(--kc-font);
86
89
  font-size: var(--kc-font-size);
@@ -4,8 +4,11 @@
4
4
  copies, volume and size, the face and its area). Beside it a panel, which the toolbar's Panel
5
5
  button hides: the view's controls (the render mode; edges, axes, the floor; fit, perspective,
6
6
  the views) over the model's parts (a click on one selecting its copies, as a click in the
7
- viewer does), half of it each. A bar above: a section through the model, a screenshot and a
8
- host's own actions (which take the controls' look by .kc-control), the Panel button, and a
7
+ viewer does), half of it each; in a pane narrower than 36em (a phone's), under the model, at
8
+ most half the pane. The model fills what the rest leave, and no less than
9
+ `--kc-model-min-height` (none by default): a host whose pane is as tall as its content sets it,
10
+ the model having no height of its own. A bar above: a section through the model, a screenshot
11
+ and a host's own actions (which take the controls' look by .kc-control), the Panel button, and a
9
12
  host's toggles of its own panes beside this one. Below: how its run went, and what it said
10
13
  went wrong, one with a line clicked given to the host (`onproblem`), and a button that lists
11
14
  the keyboard shortcuts (the host's own, then the viewer's). How the view looks (the render mode,
@@ -496,6 +499,7 @@
496
499
 
497
500
  <style>
498
501
  .kc-viewer-pane {
502
+ container-type: inline-size;
499
503
  display: flex;
500
504
  flex-direction: column;
501
505
  height: 100%;
@@ -530,6 +534,7 @@
530
534
  position: relative;
531
535
  flex: 1;
532
536
  min-width: 0;
537
+ min-height: var(--kc-model-min-height, 0);
533
538
  }
534
539
  .tooltip {
535
540
  position: absolute;
@@ -573,6 +578,26 @@
573
578
  .parts {
574
579
  border-top: 1px solid var(--kc-border);
575
580
  }
581
+ /* A narrow pane: the panel under the model, as wide, the controls then the parts at their own
582
+ heights; scrolled past half the pane */
583
+ @container (max-width: 36em) {
584
+ .body {
585
+ flex-direction: column;
586
+ }
587
+ .panel {
588
+ flex: none;
589
+ width: auto;
590
+ max-height: 50%;
591
+ overflow: auto;
592
+ border-left: none;
593
+ border-top: 1px solid var(--kc-border);
594
+ }
595
+ .controls,
596
+ .parts {
597
+ flex: none;
598
+ overflow: visible;
599
+ }
600
+ }
576
601
  .caption {
577
602
  margin: 0 0 2px;
578
603
  color: var(--kc-muted);
package/src/params.js CHANGED
@@ -60,8 +60,10 @@ export function partsOf(rule) {
60
60
  * A number control's increment: the script's `step:`, else 1 for one between a `min` and a
61
61
  * `max` (a slider moved by a hand lands on whole numbers, not on 27.41112), or, for a range
62
62
  * narrower than 1, which a step of 1 couldn't move in, the power of ten that gives it at least
63
- * ten positions; any value for a number with no range.
64
- * @param {Rule} rule
63
+ * ten positions; any value for a number with no range. Finer still where the range's ends or
64
+ * the parameter's default have more decimals: a control's steps count from its `min`, so 1.2 to
65
+ * 4 by 1 reached neither 4 nor a default of 2, which the slider showed as 2.2.
66
+ * @param {Rule | ParamSpec} rule
65
67
  * @returns {number | 'any'}
66
68
  */
67
69
  export function stepOf(rule) {
@@ -69,7 +71,32 @@ export function stepOf(rule) {
69
71
  const { min, max } = rule;
70
72
  if (min === null || max === null || !(max > min)) return 'any';
71
73
  const range = max - min;
72
- return range >= 1 ? 1 : 10 ** (Math.floor(Math.log10(range)) - 1);
74
+ const coarsest = range >= 1 ? 1 : 10 ** (Math.floor(Math.log10(range)) - 1);
75
+ const marks = [min, max];
76
+ if ('default_value' in rule && typeof rule.default_value === 'number') {
77
+ marks.push(rule.default_value);
78
+ }
79
+ const steps = marks.map(decimalStepOf);
80
+ return steps.includes(null) ? 'any' : Math.min(coarsest, .../** @type {number[]} */ (steps));
81
+ }
82
+
83
+ /** The decimal places a step may have: past them, a number is taken as having no grid. */
84
+ const MAX_PLACES = 9;
85
+
86
+ /**
87
+ * The coarsest power of ten, 1 at most, that `n` is a whole multiple of (0.1 for 1.2, 1 for 40),
88
+ * or null for a number of more than MAX_PLACES decimals.
89
+ * @param {number} n
90
+ * @returns {number | null}
91
+ */
92
+ function decimalStepOf(n) {
93
+ for (let places = 0; places <= MAX_PLACES; places += 1) {
94
+ const scaled = n * 10 ** places;
95
+ if (Math.abs(scaled - Math.round(scaled)) < 1e-9 * Math.max(1, Math.abs(scaled))) {
96
+ return 10 ** -places;
97
+ }
98
+ }
99
+ return null;
73
100
  }
74
101
 
75
102
  /**