+
+
+
+
+
diff --git a/src/components/Tab.vue b/src/components/Tab.vue
index 46110a57..bc2bfb3c 100644
--- a/src/components/Tab.vue
+++ b/src/components/Tab.vue
@@ -318,14 +318,14 @@
height: fit-content;
}
.content {
- padding: 16px;
+ padding: 0px 16px 16px 16px;
width: 100%;
overflow-y: scroll;
overflow-x: hidden;
max-width: 500px;
}
- // desktop styles
- @media (min-width: 700px) {
+ // tablet & desktop styles
+ @media (min-width: $tablet-breakpoint) {
.buttons {
display: flex;
justify-content: flex-end;
@@ -364,7 +364,6 @@
}
.content {
- padding: 16px;
position: absolute;
top: 16px;
background-color: var(--ns-color-white);
diff --git a/src/shared/Paramable.ts b/src/shared/Paramable.ts
index 1ee170d2..51668d9e 100644
--- a/src/shared/Paramable.ts
+++ b/src/shared/Paramable.ts
@@ -39,6 +39,12 @@ export interface ParamInterface {
// a blank input in the UI will use the `default` property instead of
// displaying an error to the user.
required: boolean
+ // The placeholder text that appears in the entry box for the parameter
+ // when that box is empty. This is really only applicable to non-required
+ // parameters, because for required ones, that box is not allowed to be
+ // empty. The placeholder defaults to the string representation of the
+ // default value for the parameter.
+ placeholder?: string
/* If you want the control for this parameter only to be visible when
* some other parameter has a specific value (because it is otherwise
* irrelevant), set this `visibleDependency` property to the name of
@@ -366,10 +372,12 @@ export class Paramable
const tentative = this.tentativeValues[prop]
const status = ValidationStatus.ok()
- typeFunctions[param.type].validate(tentative, status)
+ // No need to validate empty optional params
+ if (tentative || param.required)
+ typeFunctions[param.type].validate(tentative, status)
if (status.isValid()) {
- const realized = typeFunctions[param.type].realize(tentative)
- if (realized === me[prop]) continue
+ // Skip any parameters that already produce the current value
+ if (me[prop] === realizeOne(param, tentative)) continue
}
// Circumventing typescript a bit as we do above
diff --git a/src/shared/Specimen.ts b/src/shared/Specimen.ts
index 9663437d..21699b0c 100644
--- a/src/shared/Specimen.ts
+++ b/src/shared/Specimen.ts
@@ -166,11 +166,8 @@ export class Specimen {
* the key of the desired visualizer's export module
*/
set visualizerKey(visualizerKey: string) {
- // TODO: Do we need to check if the previous visualizer is already
- // inhabiting an HTML element and .depart it if so, before it is
- // setup again? Or will garbage collection of the old visualizer take
- // care of that?
this._visualizerKey = visualizerKey
+ this._visualizer.depart(this.location!)
this._visualizer = new vizMODULES[visualizerKey].visualizer(
this._sequence
)
diff --git a/src/shared/layoutUtilities.ts b/src/shared/layoutUtilities.ts
new file mode 100644
index 00000000..7f1a863a
--- /dev/null
+++ b/src/shared/layoutUtilities.ts
@@ -0,0 +1,9 @@
+/* Helper functions for laying out the user interface */
+export function isMobile() {
+ const tabletBreakpoint = parseInt(
+ window
+ .getComputedStyle(document.documentElement)
+ .getPropertyValue('--ns-breakpoint-tablet')
+ )
+ return window.innerWidth < tabletBreakpoint
+}
diff --git a/src/views/Gallery.vue b/src/views/Gallery.vue
index f8218d6c..13b27e92 100644
--- a/src/views/Gallery.vue
+++ b/src/views/Gallery.vue
@@ -23,60 +23,43 @@
keyboard_arrow_up