terrier-engine 4.4.34 → 4.4.35

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/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "files": [
5
5
  "*"
6
6
  ],
7
- "version": "4.4.34",
7
+ "version": "4.4.35",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Terrier-Tech/terrier-engine"
@@ -4,27 +4,34 @@ import Fragments from "../fragments"
4
4
  import {untypedKey} from "tuff-core/messages";
5
5
 
6
6
  export type CollapsibleConfig = {
7
- collapsed?: Boolean
8
- chevronSide?: string
7
+ collapsed?: boolean
8
+ chevronSide?: 'left' | 'right'
9
9
  }
10
10
  /**
11
11
  * A part that renders content inside a panel.
12
12
  */
13
13
  export default abstract class PanelPart<TState> extends ContentPart<TState & { collapsible?: CollapsibleConfig}> {
14
+ protected static readonly DEFAULT_CHEVRON_SIDE: 'left' | 'right' = 'left'
14
15
 
15
16
  toggleCollapseKey = untypedKey()
16
17
 
18
+ private _prevCollapsedState?: boolean
19
+
17
20
  async init() {
18
21
  if (this.state.collapsible) {
19
- if (!this.state.collapsible.chevronSide) {
20
- this.state.collapsible.chevronSide = 'left'
21
- }
22
+ this._prevCollapsedState = this.state.collapsible.collapsed
23
+ this.state.collapsible.chevronSide ??= PanelPart.DEFAULT_CHEVRON_SIDE
22
24
  this.onClick(this.toggleCollapseKey, _ => {
23
25
  this.toggleCollapse()
24
26
  })
25
27
  }
26
28
  }
27
29
 
30
+ assignState(state: TState & { collapsible?: CollapsibleConfig }): boolean {
31
+ this._prevCollapsedState = state.collapsible?.collapsed
32
+ return super.assignState(state);
33
+ }
34
+
28
35
  getLoadingContainer() {
29
36
  return this.element?.getElementsByClassName('tt-panel')[0]
30
37
  }
@@ -38,11 +45,13 @@ export default abstract class PanelPart<TState> extends ContentPart<TState & { c
38
45
  }
39
46
 
40
47
  render(parent: PartTag) {
48
+ const collapsibleConfig = this.state.collapsible
41
49
  parent.div('.tt-panel', panel => {
42
50
  panel.class(...this.panelClasses)
51
+ if (collapsibleConfig?.collapsed) panel.class('collapsed')
43
52
  if (this._title?.length || this.hasActions('tertiary')) {
44
53
  panel.div('.panel-header', header => {
45
- if (this.state.collapsible?.chevronSide == 'left') {
54
+ if (collapsibleConfig?.chevronSide == 'left') {
46
55
  this.renderChevron(header)
47
56
  }
48
57
  header.h2(h2 => {
@@ -54,38 +63,70 @@ export default abstract class PanelPart<TState> extends ContentPart<TState & { c
54
63
  header.div('.tertiary-actions', actions => {
55
64
  this.theme.renderActions(actions, this.getActions('tertiary'))
56
65
  })
57
- if (this.state.collapsible?.chevronSide == 'right') {
66
+ if (collapsibleConfig?.chevronSide == 'right') {
58
67
  this.renderChevron(header)
59
68
  }
60
69
  })
61
70
  }
62
- if (!this.state.collapsible?.collapsed) {
63
- panel.div('.panel-content', ...this.contentClasses, content => {
64
- this.renderContent(content)
71
+ panel.div('.panel-content', ...this.contentClasses, content => {
72
+ content.div('.content-container', container => {
73
+ this.renderContent(container)
65
74
  })
66
- }
75
+ })
67
76
 
68
77
  Fragments.panelActions(panel, this.getAllActions(), this.theme)
69
78
  })
70
79
  }
71
80
 
81
+ update(elem: HTMLElement) {
82
+ const panel = elem.querySelector('.tt-panel')
83
+ if (!(panel instanceof HTMLElement)) return
84
+ this.transitionCollapsed(panel)
85
+ }
86
+
87
+ private transitionCollapsed(panelElem: HTMLElement) {
88
+ const collapsibleConfig = this.state.collapsible
89
+ if (!collapsibleConfig) return
90
+
91
+ if (collapsibleConfig.collapsed == this._prevCollapsedState) return
92
+
93
+ const content = panelElem.querySelector('.panel-content') as HTMLElement
94
+ const contentContainer = content.querySelector('.content-container') as HTMLElement
95
+
96
+ const height = `${contentContainer.clientHeight}px`
97
+ if (collapsibleConfig.collapsed) {
98
+ // we can't transition between 'auto' and a set pixel value,
99
+ // so we need to first set to the initial pixel value (gotten from the content container,
100
+ // whose height is not limited), then set to 0
101
+ content.style.flexBasis = height
102
+ requestAnimationFrame(() => {
103
+ // ensure initial height has been set before continuing
104
+ content.style.flexBasis = '0'
105
+ })
106
+ } else {
107
+ content.style.flexBasis = height
108
+ }
109
+
110
+ panelElem.classList.toggle('collapsed', collapsibleConfig.collapsed)
111
+ }
112
+
72
113
  toggleCollapse() {
73
114
  if (this.state.collapsible) {
74
- this.state.collapsible.collapsed = !this.state.collapsible?.collapsed
75
- this.dirty()
115
+ this._prevCollapsedState = this.state.collapsible.collapsed
116
+ this.state.collapsible.collapsed = !this.state.collapsible.collapsed
117
+ this.stale()
76
118
  }
77
119
  }
78
120
 
79
121
  renderChevron(parent: PartTag) {
80
122
  if (this.state.collapsible) {
81
- parent.div('.collapsible-chevron', chev => {
123
+ parent.a('.collapsible-chevron', chev => {
82
124
  this.renderChevronIcon(chev, this.state.collapsible?.collapsed!)
83
- parent.emitClick(this.toggleCollapseKey)
84
- })
125
+ }).emitClick(this.toggleCollapseKey)
85
126
  }
86
127
  }
87
128
 
88
- renderChevronIcon(parent: PartTag, isCollapsed: Boolean) {
89
- this.app.theme.renderIcon(parent, isCollapsed ? 'glyp-chevron_right' : 'glyp-chevron_down', 'white')
129
+ renderChevronIcon(parent: PartTag, _isCollapsed: Boolean) {
130
+ this.app.theme.renderIcon(parent, 'glyp-chevron_down', 'white')
90
131
  }
91
132
  }