@malloydata/render 0.0.105-dev231124203430 → 0.0.105-dev231127164722

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.
@@ -0,0 +1,2 @@
1
+ <link rel="preconnect" href="https://rsms.me/" />
2
+ <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
@@ -48,10 +48,31 @@ MalloyRender.styles = (0, lit_1.css) `
48
48
  --table-border: 1px solid #e5e7eb;
49
49
  --table-background: white;
50
50
  --table-gutter-size: 15px;
51
+ --table-pinned-background: #f5fafc;
52
+ --table-pinned-border: 1px solid #daedf3;
51
53
 
52
54
  font-family: Inter, system-ui, sans-serif;
53
55
  font-size: var(--table-font-size);
54
56
  }
57
+
58
+ @supports (font-variation-settings: normal) {
59
+ :host {
60
+ font-family:
61
+ InterVariable,
62
+ Inter,
63
+ system-ui sans-serif;
64
+
65
+ font-variant-numeric: tabular-nums;
66
+ font-feature-settings:
67
+ 'cv01' 1,
68
+ 'cv02' 1,
69
+ 'cv03' 1,
70
+ 'cv04' 1,
71
+ 'cv09' 1,
72
+ 'liga' 1,
73
+ 'calt' 1;
74
+ }
75
+ }
55
76
  `;
56
77
  __decorate([
57
78
  (0, decorators_js_1.property)({ attribute: false })
@@ -1,9 +1,19 @@
1
1
  import { DataArray } from '@malloydata/malloy';
2
- import { LitElement } from 'lit';
2
+ import { LitElement, TemplateResult } from 'lit';
3
3
  export declare class Table extends LitElement {
4
4
  static styles: import("lit").CSSResult;
5
5
  data: DataArray;
6
- render(): import("lit-html").TemplateResult<1>;
6
+ rowLimit: number;
7
+ pinnedHeader: boolean;
8
+ protected _scrolling: boolean;
9
+ parentCtx: any;
10
+ ctx: {
11
+ root: boolean;
12
+ };
13
+ connectedCallback(): void;
14
+ private _handleScroll;
15
+ protected createRenderRoot(): HTMLElement | DocumentFragment;
16
+ render(): TemplateResult<1>;
7
17
  }
8
18
  declare global {
9
19
  interface HTMLElementTagNameMap {
@@ -32,7 +32,9 @@ exports.Table = void 0;
32
32
  const lit_1 = require("lit");
33
33
  const decorators_js_1 = require("lit/decorators.js");
34
34
  const class_map_js_1 = require("lit/directives/class-map.js");
35
+ const context_1 = require("@lit/context");
35
36
  const util_1 = require("./util");
37
+ const tableContext = (0, context_1.createContext)('table');
36
38
  // TODO: replace with an estimator per column
37
39
  function getColumnWidth() {
38
40
  return 130;
@@ -44,30 +46,45 @@ const getContentStyle = (f) => {
44
46
  }
45
47
  return '';
46
48
  };
47
- const renderCell = (f, value) => {
49
+ const renderCell = (f, value, options) => {
48
50
  return (0, lit_1.html) `<div class="cell-wrapper">
49
- <div class="cell-gutter-start"></div>
51
+ <div
52
+ class=${(0, class_map_js_1.classMap)({
53
+ 'cell-gutter': true,
54
+ 'hide-gutter-border': options.hideStartGutter,
55
+ })}
56
+ ></div>
50
57
  <div class="cell-content" style="${getContentStyle(f)}">${value}</div>
51
- <div class="cell-gutter-end"></div>
58
+ <div
59
+ class=${(0, class_map_js_1.classMap)({
60
+ 'cell-gutter': true,
61
+ 'hide-gutter-border': options.hideEndGutter,
62
+ })}
63
+ ></div>
52
64
  </div>`;
53
65
  };
54
- const renderFieldContent = (row, f) => {
66
+ const renderFieldContent = (row, f, options) => {
67
+ var _a;
55
68
  if (f.isExploreField()) {
56
69
  return (0, lit_1.html) `<malloy-table
57
70
  .data=${row.cell(f)}
71
+ .pinnedHeader=${(_a = options.pinnedHeader) !== null && _a !== void 0 ? _a : false}
72
+ .rowLimit=${options.pinnedHeader ? 1 : Infinity}
58
73
  ></malloy-table>`;
59
74
  }
60
- return renderCell(f, row.cell(f).value);
75
+ if (options.pinnedHeader)
76
+ return renderCell(f, '', {
77
+ hideStartGutter: (0, util_1.isFirstChild)(f),
78
+ hideEndGutter: (0, util_1.isLastChild)(f),
79
+ });
80
+ return renderCell(f, row.cell(f).value, {
81
+ hideStartGutter: (0, util_1.isFirstChild)(f),
82
+ hideEndGutter: (0, util_1.isLastChild)(f),
83
+ });
61
84
  };
62
- const renderField = (row, f) => {
63
- return (0, lit_1.html) `<td
64
- class=${(0, class_map_js_1.classMap)({
65
- 'column-cell': true,
66
- 'hide-end-gutter': (0, util_1.isLastChild)(f),
67
- 'hide-start-gutter': (0, util_1.isFirstChild)(f),
68
- })}
69
- >
70
- ${renderFieldContent(row, f)}
85
+ const renderField = (row, f, options) => {
86
+ return (0, lit_1.html) `<td class="column-cell">
87
+ ${renderFieldContent(row, f, options)}
71
88
  </td>`;
72
89
  };
73
90
  const renderHeader = (f) => {
@@ -78,40 +95,118 @@ const renderHeader = (f) => {
78
95
  const isLast = (0, util_1.isLastChild)(f);
79
96
  const isParentLast = (0, util_1.isLastChild)(f.parentExplore);
80
97
  const hideEndGutter = isLast && (isParentLast || isParentNotAField);
81
- return (0, lit_1.html) `<th
82
- class=${(0, class_map_js_1.classMap)({
83
- 'column-cell': true,
84
- 'hide-end-gutter': hideEndGutter,
85
- 'hide-start-gutter': hideStartGutter,
98
+ return (0, lit_1.html) `<th class="column-cell">
99
+ ${renderCell(f, f.name, {
100
+ hideStartGutter,
101
+ hideEndGutter,
86
102
  })}
87
- >
88
- ${renderCell(f, f.name)}
89
103
  </th>`;
90
104
  };
91
105
  let Table = exports.Table = class Table extends lit_1.LitElement {
106
+ constructor() {
107
+ super(...arguments);
108
+ this.rowLimit = Infinity;
109
+ this.pinnedHeader = false;
110
+ this._scrolling = false;
111
+ this.ctx = { root: false };
112
+ }
113
+ connectedCallback() {
114
+ super.connectedCallback();
115
+ if (typeof this.parentCtx === 'undefined') {
116
+ this.ctx = {
117
+ root: true,
118
+ };
119
+ }
120
+ }
121
+ _handleScroll(e) {
122
+ const target = e.target;
123
+ this._scrolling = target.scrollTop > 0;
124
+ }
125
+ // If rendering a pinned header, render it within the current ShadowDOM root so we can use CSS to style the nested table headers when scrolling
126
+ createRenderRoot() {
127
+ if (this.pinnedHeader)
128
+ return this;
129
+ return super.createRenderRoot();
130
+ }
92
131
  render() {
93
132
  const fields = this.data.field.allFields;
94
133
  const headers = fields.map(f => renderHeader(f));
95
- const rows = Array.from(this.data, row => (0, lit_1.html) `<tr>
96
- ${fields.map(f => renderField(row, f))}
134
+ const renderOptions = {
135
+ pinnedHeader: this.pinnedHeader,
136
+ };
137
+ const rows = [];
138
+ let i = 0;
139
+ for (const row of this.data) {
140
+ if (i >= this.rowLimit)
141
+ break;
142
+ rows.push((0, lit_1.html) `<tr>
143
+ ${fields.map(f => renderField(row, f, renderOptions))}
97
144
  </tr>`);
98
- return (0, lit_1.html) `<table>
99
- <thead>
100
- <tr>
101
- ${headers}
102
- </tr>
103
- </thead>
104
- <tbody>
105
- ${rows}
106
- </tbody>
107
- </table>`;
145
+ i++;
146
+ }
147
+ const renderStickyHeader = () => {
148
+ if (this.ctx.root)
149
+ return (0, lit_1.html) `<div class="sticky-header">
150
+ <div class="sticky-header-content">
151
+ <malloy-table
152
+ class=${(0, class_map_js_1.classMap)({
153
+ 'pinned-header': true,
154
+ 'scrolled': this._scrolling,
155
+ })}
156
+ .rowLimit=${1}
157
+ .data=${this.data}
158
+ .pinnedHeader=${true}
159
+ ></malloy-table>
160
+ </div>
161
+ </div>`;
162
+ };
163
+ return (0, lit_1.html) `<div @scroll=${this._handleScroll} class="table-wrapper">
164
+ ${renderStickyHeader()}
165
+ <table>
166
+ <thead>
167
+ <tr>
168
+ ${headers}
169
+ </tr>
170
+ </thead>
171
+ <tbody>
172
+ ${rows}
173
+ </tbody>
174
+ </table>
175
+ </div>`;
108
176
  }
109
177
  };
110
178
  Table.styles = (0, lit_1.css) `
179
+ .table-wrapper {
180
+ width: 100%;
181
+ height: 100%;
182
+ position: relative;
183
+ overflow: auto;
184
+ }
185
+
186
+ .sticky-header {
187
+ position: sticky;
188
+ top: 0px;
189
+ z-index: 100;
190
+ }
191
+
192
+ .sticky-header-content {
193
+ position: absolute;
194
+ top: 0px;
195
+ left: 0px;
196
+ pointer-events: none;
197
+ }
198
+
199
+ .sticky-header-content th {
200
+ pointer-events: all;
201
+ }
202
+
111
203
  table {
112
204
  border-collapse: collapse;
113
205
  background: var(--table-background);
114
- font-variant-numeric: tabular-nums;
206
+ }
207
+
208
+ th {
209
+ transition: background-color 0.25s;
115
210
  }
116
211
 
117
212
  table * {
@@ -154,29 +249,60 @@ Table.styles = (0, lit_1.css) `
154
249
  text-overflow: ellipsis;
155
250
  }
156
251
 
157
- .cell-gutter-start {
252
+ .cell-gutter {
158
253
  border-top: var(--table-border);
159
254
  height: var(--table-row-height);
160
255
  width: var(--table-gutter-size);
256
+ transition: border-color 0.25s;
161
257
  }
162
258
 
163
- .cell-gutter-end {
164
- border-top: var(--table-border);
165
- height: var(--table-row-height);
166
- width: var(--table-gutter-size);
259
+ .cell-gutter.hide-gutter-border {
260
+ border-color: transparent;
261
+ }
262
+
263
+ .pinned-header table {
264
+ background: transparent;
265
+ }
266
+
267
+ .pinned-header th {
268
+ background: var(--table-background);
167
269
  }
168
270
 
169
- .hide-end-gutter .cell-gutter-end {
170
- border-top: none;
271
+ .pinned-header.scrolled th {
272
+ background: var(--table-pinned-background);
273
+ box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.5);
171
274
  }
172
275
 
173
- .hide-start-gutter .cell-gutter-start {
174
- border-top: none;
276
+ .pinned-header.scrolled {
277
+ .cell-content,
278
+ .cell-gutter,
279
+ .cell-gutter.hide-gutter-border {
280
+ border-top: var(--table-pinned-border);
281
+ }
175
282
  }
176
283
  `;
177
284
  __decorate([
178
285
  (0, decorators_js_1.property)({ attribute: false })
179
286
  ], Table.prototype, "data", void 0);
287
+ __decorate([
288
+ (0, decorators_js_1.property)({ type: Number })
289
+ ], Table.prototype, "rowLimit", void 0);
290
+ __decorate([
291
+ (0, decorators_js_1.property)({ type: Boolean })
292
+ ], Table.prototype, "pinnedHeader", void 0);
293
+ __decorate([
294
+ (0, decorators_js_1.state)()
295
+ ], Table.prototype, "_scrolling", void 0);
296
+ __decorate([
297
+ (0, context_1.consume)({ context: tableContext }),
298
+ (0, decorators_js_1.property)({ attribute: false })
299
+ ], Table.prototype, "parentCtx", void 0);
300
+ __decorate([
301
+ (0, context_1.provide)({ context: tableContext })
302
+ ], Table.prototype, "ctx", void 0);
303
+ __decorate([
304
+ (0, decorators_js_1.eventOptions)({ passive: true })
305
+ ], Table.prototype, "_handleScroll", null);
180
306
  exports.Table = Table = __decorate([
181
307
  (0, decorators_js_1.customElement)('malloy-table')
182
308
  ], Table);
@@ -28,3 +28,10 @@ export declare const Nested: {
28
28
  view: string;
29
29
  };
30
30
  };
31
+ export declare const NestedCompact: {
32
+ args: {
33
+ source: string;
34
+ view: string;
35
+ classes: string;
36
+ };
37
+ };
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Nested = exports.Products2Column = exports.ProductsTableCustomTheme = exports.ProductsTable = void 0;
6
+ exports.NestedCompact = exports.Nested = exports.Products2Column = exports.ProductsTableCustomTheme = exports.ProductsTable = void 0;
7
7
  const tables_malloy_raw_1 = __importDefault(require("./static/tables.malloy?raw"));
8
8
  const util_1 = require("./util");
9
9
  require("./themes.css");
@@ -11,11 +11,15 @@ require("../component/render");
11
11
  const meta = {
12
12
  title: 'Malloy Next/Tables',
13
13
  render: ({ classes }, context) => {
14
+ const parent = document.createElement('div');
15
+ parent.style.height = '1000px';
16
+ parent.style.position = 'relative';
14
17
  const el = document.createElement('malloy-render');
15
18
  if (classes)
16
19
  el.classList.add(classes);
17
20
  el.result = context.loaded['result'];
18
- return el;
21
+ parent.appendChild(el);
22
+ return parent;
19
23
  },
20
24
  loaders: [(0, util_1.createLoader)(tables_malloy_raw_1.default)],
21
25
  argTypes: {},
@@ -46,4 +50,11 @@ exports.Nested = {
46
50
  view: 'nested',
47
51
  },
48
52
  };
53
+ exports.NestedCompact = {
54
+ args: {
55
+ source: 'products',
56
+ view: 'nested',
57
+ classes: 'compact',
58
+ },
59
+ };
49
60
  //# sourceMappingURL=tables.stories.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/render",
3
- "version": "0.0.105-dev231124203430",
3
+ "version": "0.0.105-dev231127164722",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,8 @@
23
23
  "build-storybook": "storybook build"
24
24
  },
25
25
  "dependencies": {
26
- "@malloydata/malloy": "^0.0.105-dev231124203430",
26
+ "@lit/context": "^1.1.0",
27
+ "@malloydata/malloy": "^0.0.105-dev231127164722",
27
28
  "@types/luxon": "^2.4.0",
28
29
  "lit": "^3.0.2",
29
30
  "lodash": "^4.17.20",