@emuanalytics/flow-rdf-ui 4.1.8 → 4.1.10

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.
@@ -384,6 +384,7 @@ const _FlowUiQueryBuilder = class _FlowUiQueryBuilder extends FlowRdfElement {
384
384
  .value=${ruleSet}
385
385
  .config=${this.config}
386
386
  size=${this.size}
387
+ !borders=${this.borders}
387
388
  ?tree-lines=${this.treeLines}
388
389
  @flow-ui-change=${this.handleSubQueryValueChange}
389
390
  @flow-ui-remove=${(ev) => this.handleRemoveRule(ev, index)}
@@ -226,7 +226,7 @@ const styles = css`
226
226
  &::after {
227
227
  content: '';
228
228
  left: -10px;
229
- border-color: var(--flow-ui-color-neutral-200);
229
+ border-color: var(--control-border-color);
230
230
  border-style: solid;
231
231
  width: 9px;
232
232
  position: absolute;
@@ -315,6 +315,14 @@ const styles = css`
315
315
  .query-builder__footer ::slotted(flow-ui-button:not(:first-of-type)) {
316
316
  margin-inline-start: var(--flow-ui-spacing-x-small);
317
317
  }
318
+
319
+ /* Sub query builder styling */
320
+
321
+ .query-builder--child[borders='true'] {
322
+ /* remove right border */
323
+ border-radius: var(--control-border-radius) 0 0 var(--control-border-radius);
324
+ border-right: 0;
325
+ }
318
326
  `;
319
327
 
320
328
  export { styles as default };
@@ -7,6 +7,7 @@ import { boolean } from '../../internal/boolean.mjs';
7
7
  import { defaultValue } from '../../internal/default-value.mjs';
8
8
  import { FlowRdfFormControl } from '../../internal/flow-ui-rdf-element.mjs';
9
9
  import { FormControlController } from '../../internal/form.mjs';
10
+ import { clamp } from '../../internal/math.mjs';
10
11
  import { HasSlotController } from '../../internal/slot.mjs';
11
12
  import { isNumber } from '../../internal/type-checks.mjs';
12
13
  import { watch } from '../../internal/watch.mjs';
@@ -78,13 +79,15 @@ class FlowUiRange extends FlowRdfFormControl {
78
79
  super.disconnectedCallback();
79
80
  this.resizeObserver.unobserve(this.input);
80
81
  }
81
- handleChange() {
82
+ handleRangeChange(event) {
83
+ event.stopPropagation();
82
84
  this.emit("flow-ui-change");
83
85
  }
84
- handleInput() {
86
+ handleRangeInput(event) {
87
+ event.stopPropagation();
85
88
  this.value = parseFloat(this.input.value);
86
- this.emit("flow-ui-input");
87
89
  this.syncRange();
90
+ this.emit("flow-ui-input");
88
91
  }
89
92
  /*
90
93
  Handler for flow-ui-input & flow-ui-change events from number input.
@@ -97,11 +100,13 @@ class FlowUiRange extends FlowRdfFormControl {
97
100
  this.syncRange();
98
101
  }
99
102
  }
100
- handleBlur() {
103
+ handleBlur(event) {
104
+ event.stopPropagation();
101
105
  this.hasFocus = false;
102
106
  this.emit("flow-ui-blur");
103
107
  }
104
- handleFocus() {
108
+ handleFocus(event) {
109
+ event.stopPropagation();
105
110
  this.hasFocus = true;
106
111
  this.emit("flow-ui-focus");
107
112
  }
@@ -114,8 +119,7 @@ class FlowUiRange extends FlowRdfFormControl {
114
119
  }
115
120
  handleValueChange() {
116
121
  this.formControlController.updateValidity();
117
- this.input.value = this.value?.toString();
118
- this.value = parseFloat(this.input.value);
122
+ this.value = clamp(this.value, this.min, this.max);
119
123
  this.syncRange();
120
124
  }
121
125
  handleDisabledChange() {
@@ -126,7 +130,7 @@ class FlowUiRange extends FlowRdfFormControl {
126
130
  const percent = Math.max(0, (this.value - this.min) / (this.max - this.min));
127
131
  this.syncProgress(percent);
128
132
  }
129
- handleInvalid(event) {
133
+ handleRangeInvalid(event) {
130
134
  this.formControlController.setValidity(false);
131
135
  this.formControlController.emitInvalidEvent(event);
132
136
  }
@@ -240,30 +244,35 @@ class FlowUiRange extends FlowRdfFormControl {
240
244
  step=${ifDefined(this.step)}
241
245
  .value=${live(this.value.toString())}
242
246
  aria-describedby="help-text"
243
- @change=${this.handleChange}
247
+ @change=${this.handleRangeChange}
244
248
  @focus=${this.handleFocus}
245
- @input=${this.handleInput}
246
- @invalid=${this.handleInvalid}
249
+ @input=${this.handleRangeInput}
250
+ @invalid=${this.handleRangeInvalid}
247
251
  @blur=${this.handleBlur}
248
252
  />
249
253
  <slot name="suffix" part="suffix" class="range__suffix"></slot>
250
254
 
251
- ${this.noInput ? nothing : html`
252
- <flow-ui-input
253
- class="number-input"
254
- type="number"
255
- inline
256
- filled
257
- exportparts="form-control:number-input"
258
- no-step-buttons
259
- size=${this.size}
260
- format=${this.format}
261
- ?disabled=${this.disabled}
262
- .value=${this.value.toString()}
263
- @flow-ui-input=${this.handleNumberChange}
264
- @flow-ui-change=${this.handleNumberChange}
265
- ></flow-ui-input>
266
- `}
255
+ <flow-ui-input
256
+ class=${classMap({
257
+ "number-input": true,
258
+ "no-input": this.noInput
259
+ })}
260
+ type="number"
261
+ inline
262
+ filled
263
+ exportparts="form-control:number-input"
264
+ no-step-buttons
265
+ size=${this.size}
266
+ format=${this.format}
267
+ min=${ifDefined(this.min)}
268
+ max=${ifDefined(this.max)}
269
+ step=${ifDefined(this.step)}
270
+ ?disabled=${this.disabled}
271
+ .value=${this.value.toString()}
272
+ @flow-ui-change=${this.handleNumberChange}
273
+ @flow-ui-focus=${this.handleFocus}
274
+ @flow-ui-blur=${this.handleBlur}
275
+ ></flow-ui-input>
267
276
  </div>
268
277
  </div>
269
278
 
@@ -210,6 +210,10 @@ const styles = css`
210
210
  color: var(--flow-ui-control-icon-color);
211
211
  }
212
212
 
213
+ .number-input.no-input {
214
+ display: none;
215
+ }
216
+
213
217
  @media (forced-colors: active) {
214
218
  .range__control,
215
219
  .range__control::-webkit-slider-thumb {
@@ -23,6 +23,9 @@ var __decorateClass = (decorators, target, key, kind) => {
23
23
  class FlowUiSplitView extends FlowRdfElement {
24
24
  constructor() {
25
25
  super(...arguments);
26
+ // Saved panel layouts for restoring when panels are dynamically added/removed
27
+ // The key is a comma-separated concatenation of panel ids e.g. 'pane-1,pane-2,pane-3'
28
+ this._panelLayouts = {};
26
29
  this._panels = [];
27
30
  this.noDragClose = false;
28
31
  this.positions = ["auto", "auto", "auto", "auto"];
@@ -41,9 +44,11 @@ class FlowUiSplitView extends FlowRdfElement {
41
44
  const panelsRemoved = mutations.map((m) => Array.from(m.removedNodes.values())).flat().filter((n) => n instanceof FlowUiSplitViewPane);
42
45
  if (panelsAdded.length > 0) {
43
46
  this.handlePanelAdded(panelsAdded[0]);
47
+ console.log("Split view panel added:", this._panels.map((panel) => panel.id).join(":"));
44
48
  }
45
49
  if (panelsRemoved.length > 0) {
46
50
  this.handlePanelRemoved(panelsRemoved[0]);
51
+ console.log("Split view panel removed:", this._panels.map((panel) => panel.id).join(":"));
47
52
  }
48
53
  this.layoutPanels();
49
54
  });
@@ -302,6 +307,7 @@ class FlowUiSplitView extends FlowRdfElement {
302
307
  if (splitViewSize === 0) {
303
308
  return;
304
309
  }
310
+ this.savePanelLayouts();
305
311
  const numOpenPanels = this._panels.filter((panel) => !panel.closed && !panel.hidden).length;
306
312
  const panelSizes = this._panels.map((panel) => {
307
313
  if (panel.hidden) {
@@ -348,8 +354,11 @@ class FlowUiSplitView extends FlowRdfElement {
348
354
  panel.divider = !panel.hidden;
349
355
  }
350
356
  const lastVisiblePanel = this._panels.slice().reverse().find((panel) => !panel.hidden);
351
- lastVisiblePanel.divider = false;
357
+ if (lastVisiblePanel) {
358
+ lastVisiblePanel.divider = false;
359
+ }
352
360
  this.positions = panelSizes.map((size) => size + "px");
361
+ console.log("Panel layouts", this._panelLayouts);
353
362
  }
354
363
  resizePanels() {
355
364
  const boundingRect = this.splitView.getBoundingClientRect();
@@ -459,20 +468,53 @@ class FlowUiSplitView extends FlowRdfElement {
459
468
  }
460
469
  handlePanelAdded(panel) {
461
470
  this.updatePanelInfo();
462
- if (isUndefined(panel.size) || panel.size === "auto") {
463
- panel.size = panel.minSize ?? "50px";
471
+ if (!this.restorePanelLayouts()) {
472
+ if (isUndefined(panel.size) || panel.size === "auto") {
473
+ panel.size = panel.minSize ?? "50px";
474
+ }
475
+ this.shrinkPanels(this._panels.length - 1, -1, true, this.sizeToPixels(panel.size));
464
476
  }
465
- this.shrinkPanels(this._panels.length - 1, -1, true, this.sizeToPixels(panel.size));
466
477
  }
467
478
  handlePanelRemoved(panel) {
468
479
  this.updatePanelInfo();
469
- this.growPanels(this._panels.length - 1, -1, true, this.sizeToPixels(panel.size));
480
+ if (!this.restorePanelLayouts()) {
481
+ this.growPanels(this._panels.length - 1, -1, true, this.sizeToPixels(panel.size));
482
+ }
470
483
  }
471
484
  updatePanelInfo() {
472
485
  this._panels = [...this.panelSlot.assignedElements()].filter(
473
486
  (el) => el.tagName.toLowerCase() === "flow-ui-split-view-pane"
474
487
  );
475
488
  }
489
+ // Key used to stor panel layouts for a given set of panels
490
+ // This is a comma-separated concatenation of panel ids e.g. 'pane-1,pane-2,pane-3'
491
+ panelLayoutsKey() {
492
+ return this._panels.map((panel) => panel.id).join(",");
493
+ }
494
+ savePanelLayouts() {
495
+ const panelLayoutsKey = this.panelLayoutsKey();
496
+ const panelLayouts = this._panels.map(
497
+ (panel) => ({ id: panel.id, size: panel.size, closed: panel.closed })
498
+ );
499
+ this._panelLayouts[panelLayoutsKey] = panelLayouts;
500
+ console.log("Saving panel layouts:", panelLayoutsKey, panelLayouts);
501
+ }
502
+ restorePanelLayouts() {
503
+ const panelLayoutsKey = this.panelLayoutsKey();
504
+ if (this._panelLayouts[panelLayoutsKey]) {
505
+ this._panelLayouts[panelLayoutsKey].forEach((panelLayout) => {
506
+ const panel = this._panels.find((p) => p.id === panelLayout.id);
507
+ if (panel) {
508
+ panel.size = panelLayout.size;
509
+ panel.closed = panelLayout.closed;
510
+ }
511
+ });
512
+ console.log("Restoring panel layouts:", panelLayoutsKey, this._panelLayouts[panelLayoutsKey]);
513
+ return true;
514
+ } else {
515
+ return false;
516
+ }
517
+ }
476
518
  }
477
519
  FlowUiSplitView.styles = styles;
478
520
  __decorateClass([
@@ -5,6 +5,7 @@ import { boolean } from '../../internal/boolean.mjs';
5
5
  import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
6
6
  import { setDefaultAnimation } from '../../utilities/animation-registry.mjs';
7
7
  import styles from './split-view-pane.styles.mjs';
8
+ import { isStringFull } from '../../internal/type-checks.mjs';
8
9
 
9
10
  var __defProp = Object.defineProperty;
10
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -17,9 +18,12 @@ var __decorateClass = (decorators, target, key, kind) => {
17
18
  __defProp(target, key, result);
18
19
  return result;
19
20
  };
21
+ let id = 0;
20
22
  class FlowUiSplitViewPane extends FlowRdfElement {
21
23
  constructor() {
22
24
  super(...arguments);
25
+ this.attrId = ++id;
26
+ this.componentId = `flow-ui-split-view-pane-${this.attrId}`;
23
27
  this.vertical = false;
24
28
  this.closed = false;
25
29
  this.divider = false;
@@ -27,6 +31,7 @@ class FlowUiSplitViewPane extends FlowRdfElement {
27
31
  }
28
32
  connectedCallback() {
29
33
  super.connectedCallback();
34
+ this.id = isStringFull(this.id) ? this.id : this.componentId;
30
35
  this.vertical = boolean(this.vertical, true);
31
36
  this.closed = boolean(this.closed, true);
32
37
  this.divider = boolean(this.divider, true);
@@ -3,12 +3,11 @@ import { floorDateTime } from '../../internal/datetime.mjs';
3
3
 
4
4
  const TIMER_INTERVAL = 100;
5
5
  class Ticker {
6
- constructor(tickUnit, tickValue, zone) {
6
+ constructor(tickInterval = { seconds: 5 }, zone) {
7
7
  this.subscribers = [];
8
8
  this.currentDateTime = DateTime.fromMillis(0);
9
9
  this.nextUpdateAt = DateTime.fromMillis(0);
10
- this.tickUnit = tickUnit;
11
- this.tickValue = tickValue;
10
+ this.tickInterval = tickInterval;
12
11
  this.zone = zone;
13
12
  }
14
13
  subscribe(fn) {
@@ -34,6 +33,7 @@ class Ticker {
34
33
  if (!this.timer) {
35
34
  return;
36
35
  }
36
+ console.log("Ticker stop");
37
37
  clearInterval(this.timer);
38
38
  this.timer = void 0;
39
39
  this.nextUpdateAt = DateTime.fromMillis(0);
@@ -42,9 +42,8 @@ class Ticker {
42
42
  setZone(zone) {
43
43
  this.zone = zone;
44
44
  }
45
- setTick(tickUnit, tickValue) {
46
- this.tickUnit = tickUnit;
47
- this.tickValue = tickValue;
45
+ setTickInterval(tickInterval) {
46
+ this.tickInterval = tickInterval;
48
47
  }
49
48
  /**
50
49
  * Tick the clock
@@ -59,8 +58,10 @@ class Ticker {
59
58
  const now = DateTime.local({ zone: this.zone }).set({ millisecond: 0 });
60
59
  if (now >= this.nextUpdateAt) {
61
60
  this.nextUpdateAt = floorDateTime(now.plus({ second: 1 }), "second", 1);
61
+ const majorStepUnit = Object.keys(this.tickInterval)[0];
62
+ const majorStepValue = this.tickInterval[majorStepUnit];
62
63
  let minorFlooredNow = floorDateTime(now, "second", 1);
63
- const majorFlooredNow = floorDateTime(now, this.tickUnit, this.tickValue);
64
+ const majorFlooredNow = floorDateTime(now, majorStepUnit, majorStepValue);
64
65
  if (forceMajor) {
65
66
  minorFlooredNow = majorFlooredNow;
66
67
  }
@@ -35,6 +35,7 @@ class FlowUiTimer extends FlowRdfElement {
35
35
  this.zoneFormat = "ZZZZ";
36
36
  this.majorStep = "1 minute";
37
37
  this.minorStep = "5 seconds";
38
+ this.updateInterval = "5 seconds";
38
39
  this.hideZone = false;
39
40
  this.placement = "bottom-start";
40
41
  this.debouncedEmitChange = debounce(
@@ -50,7 +51,7 @@ class FlowUiTimer extends FlowRdfElement {
50
51
  super.connectedCallback();
51
52
  this.hideZone = boolean(this.hideZone, true);
52
53
  this.running = boolean(this.running, true);
53
- this.ticker = new Ticker("second", 5, "Europe/London");
54
+ this.ticker = new Ticker({ seconds: 5 }, "Europe/London");
54
55
  this.tickerSubscription = this.ticker.subscribe((dateTime, tickType) => {
55
56
  if (tickType === "major") {
56
57
  this.value = dateTime;
@@ -72,6 +73,10 @@ class FlowUiTimer extends FlowRdfElement {
72
73
  this.minorStepDuration = parseDuration(this.minorStep) ?? { second: 5 };
73
74
  this.majorStepDuration = parseDuration(this.majorStep) ?? { minute: 1 };
74
75
  }
76
+ updateUpdateInterval() {
77
+ const updateIntervalDuration = parseDuration(this.updateInterval) ?? { second: 5 };
78
+ this.ticker.setTickInterval(updateIntervalDuration);
79
+ }
75
80
  updateRunning() {
76
81
  if (this.running) {
77
82
  this.ticker.start();
@@ -113,32 +118,16 @@ class FlowUiTimer extends FlowRdfElement {
113
118
  const minorStepValue = this.minorStepDuration[minorStepUnit];
114
119
  switch (direction) {
115
120
  case "fast-back":
116
- dateTime = ceilDateTime(
117
- this._displayDateTime.minus(this.majorStepDuration),
118
- majorStepUnit,
119
- majorStepValue
120
- );
121
+ dateTime = ceilDateTime(this._displayDateTime.minus(this.majorStepDuration), majorStepUnit, majorStepValue);
121
122
  break;
122
123
  case "back":
123
- dateTime = ceilDateTime(
124
- this._displayDateTime.minus(this.minorStepDuration),
125
- minorStepUnit,
126
- minorStepValue
127
- );
124
+ dateTime = ceilDateTime(this._displayDateTime.minus(this.minorStepDuration), minorStepUnit, minorStepValue);
128
125
  break;
129
126
  case "forward":
130
- dateTime = floorDateTime(
131
- this._displayDateTime.plus(this.minorStepDuration),
132
- minorStepUnit,
133
- minorStepValue
134
- );
127
+ dateTime = floorDateTime(this._displayDateTime.plus(this.minorStepDuration), minorStepUnit, minorStepValue);
135
128
  break;
136
129
  case "fast-forward":
137
- dateTime = floorDateTime(
138
- this._displayDateTime.plus(this.majorStepDuration),
139
- majorStepUnit,
140
- majorStepValue
141
- );
130
+ dateTime = floorDateTime(this._displayDateTime.plus(this.majorStepDuration), majorStepUnit, majorStepValue);
142
131
  break;
143
132
  default:
144
133
  dateTime = this._displayDateTime;
@@ -182,11 +171,17 @@ class FlowUiTimer extends FlowRdfElement {
182
171
  <div class="timer__time-container">
183
172
  <span class="timer__time">${this.formattedDisplayDateTime(this.timeFormat)}</span>
184
173
 
185
- ${!this.hideZone ? html`
186
- <flow-ui-tooltip hoist placement="top" content=${this.formattedDisplayDateTime("ZZZZZ")}>
187
- <span class="timer__zone">${this.formattedDisplayDateTime(this.zoneFormat)}</span>
188
- </flow-ui-tooltip>
189
- ` : nothing}
174
+ ${// Note that flow-ui-show event was causing timer to stop because of dropdown handling of flow-ui-show above
175
+ !this.hideZone ? html`
176
+ <flow-ui-tooltip
177
+ hoist
178
+ placement="top"
179
+ content=${this.formattedDisplayDateTime("ZZZZZ")}
180
+ @flow-ui-show=${(ev) => ev.stopImmediatePropagation()}
181
+ >
182
+ <span class="timer__zone">${this.formattedDisplayDateTime(this.zoneFormat)}</span>
183
+ </flow-ui-tooltip>
184
+ ` : nothing}
190
185
  </div>
191
186
  </div>
192
187
 
@@ -279,6 +274,9 @@ __decorateClass([
279
274
  __decorateClass([
280
275
  property({ attribute: "minor-step" })
281
276
  ], FlowUiTimer.prototype, "minorStep", 2);
277
+ __decorateClass([
278
+ property({ attribute: "update-interval" })
279
+ ], FlowUiTimer.prototype, "updateInterval", 2);
282
280
  __decorateClass([
283
281
  property({ type: Boolean, attribute: "hide-zone" })
284
282
  ], FlowUiTimer.prototype, "hideZone", 2);
@@ -291,6 +289,9 @@ __decorateClass([
291
289
  __decorateClass([
292
290
  watch(["majorStep", "minorStep"])
293
291
  ], FlowUiTimer.prototype, "updateParsedSteps", 1);
292
+ __decorateClass([
293
+ watch(["updateInterval"])
294
+ ], FlowUiTimer.prototype, "updateUpdateInterval", 1);
294
295
  __decorateClass([
295
296
  watch("running")
296
297
  ], FlowUiTimer.prototype, "updateRunning", 1);
@@ -36,6 +36,7 @@ const _FlowUiTreeItem = class _FlowUiTreeItem extends FlowRdfElement {
36
36
  this.disabled = false;
37
37
  this.lazy = false;
38
38
  this.size = "medium";
39
+ this.hidden = false;
39
40
  }
40
41
  /** @internal */
41
42
  static isTreeItem(node) {
@@ -47,6 +48,7 @@ const _FlowUiTreeItem = class _FlowUiTreeItem extends FlowRdfElement {
47
48
  this.selected = boolean(this.selected, true);
48
49
  this.disabled = boolean(this.disabled, true);
49
50
  this.lazy = boolean(this.lazy, true);
51
+ this.hidden = boolean(this.hidden, true);
50
52
  this.setAttribute("role", "treeitem");
51
53
  this.setAttribute("tabindex", "-1");
52
54
  if (this.isNestedItem()) {
@@ -158,6 +160,7 @@ const _FlowUiTreeItem = class _FlowUiTreeItem extends FlowRdfElement {
158
160
  "tree-item--expanded": this.expanded,
159
161
  "tree-item--selected": this.selected,
160
162
  "tree-item--disabled": this.disabled,
163
+ "tree-item--hidden": this.hidden,
161
164
  "tree-item--small": this.size === "small",
162
165
  "tree-item--medium": this.size === "medium",
163
166
  "tree-item--large": this.size === "large",
@@ -272,6 +275,9 @@ __decorateClass([
272
275
  __decorateClass([
273
276
  property({ reflect: true })
274
277
  ], _FlowUiTreeItem.prototype, "size", 2);
278
+ __decorateClass([
279
+ property({ type: Boolean, reflect: true })
280
+ ], _FlowUiTreeItem.prototype, "hidden", 2);
275
281
  __decorateClass([
276
282
  query("slot:not([name])")
277
283
  ], _FlowUiTreeItem.prototype, "defaultSlot", 2);
@@ -106,6 +106,10 @@ const styles = css`
106
106
  display: none;
107
107
  }
108
108
 
109
+ .tree-item.tree-item--hidden {
110
+ display: none;
111
+ }
112
+
109
113
  .tree-item__expand-button--visible {
110
114
  cursor: pointer;
111
115
  }