argus-table 0.2.2 → 0.4.0

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.
Files changed (83) hide show
  1. package/README.md +1 -1
  2. package/dist/argus-column-group.js +66 -0
  3. package/dist/argus-column-group.js.map +1 -0
  4. package/dist/argus-column.js +28 -26
  5. package/dist/argus-column.js.map +1 -1
  6. package/dist/argus-table.js +1497 -285
  7. package/dist/argus-table.js.map +1 -1
  8. package/dist/attributes.js +21 -0
  9. package/dist/attributes.js.map +1 -0
  10. package/dist/cdn/argus-table.js +120 -61
  11. package/dist/cdn/argus-table.js.map +1 -1
  12. package/dist/column-registry.js +23 -0
  13. package/dist/column-registry.js.map +1 -0
  14. package/dist/controllers/auto-width.js +16 -4
  15. package/dist/controllers/auto-width.js.map +1 -1
  16. package/dist/controllers/column-children.js +32 -9
  17. package/dist/controllers/column-children.js.map +1 -1
  18. package/dist/controllers/column-window.js +135 -0
  19. package/dist/controllers/column-window.js.map +1 -0
  20. package/dist/controllers/data-controller.js +9 -4
  21. package/dist/controllers/data-controller.js.map +1 -1
  22. package/dist/controllers/plugins.js +121 -0
  23. package/dist/controllers/plugins.js.map +1 -0
  24. package/dist/controllers/reorder-drag.js +19 -17
  25. package/dist/controllers/reorder-drag.js.map +1 -1
  26. package/dist/controllers/row-measure.js +122 -0
  27. package/dist/controllers/row-measure.js.map +1 -0
  28. package/dist/controllers/virtual-controller.js +315 -21
  29. package/dist/controllers/virtual-controller.js.map +1 -1
  30. package/dist/core/src/columns/column-groups.js +129 -0
  31. package/dist/core/src/columns/column-groups.js.map +1 -0
  32. package/dist/core/src/columns/column-order.js +125 -27
  33. package/dist/core/src/columns/column-order.js.map +1 -1
  34. package/dist/core/src/columns/resolve-columns.js +18 -5
  35. package/dist/core/src/columns/resolve-columns.js.map +1 -1
  36. package/dist/core/src/columns/spread-width.js +43 -0
  37. package/dist/core/src/columns/spread-width.js.map +1 -0
  38. package/dist/core/src/data/page-cache.js +4 -0
  39. package/dist/core/src/data/page-cache.js.map +1 -1
  40. package/dist/core/src/filters/filter.js +183 -0
  41. package/dist/core/src/filters/filter.js.map +1 -0
  42. package/dist/core/src/grid/row-layout.js +19 -11
  43. package/dist/core/src/grid/row-layout.js.map +1 -1
  44. package/dist/core/src/state/selection.js +71 -0
  45. package/dist/core/src/state/selection.js.map +1 -0
  46. package/dist/core/src/table/create-table.js +276 -66
  47. package/dist/core/src/table/create-table.js.map +1 -1
  48. package/dist/core/src/table/filtered-row-model.js +48 -0
  49. package/dist/core/src/table/filtered-row-model.js.map +1 -0
  50. package/dist/core/src/table/sorted-row-model.js +13 -2
  51. package/dist/core/src/table/sorted-row-model.js.map +1 -1
  52. package/dist/core/src/virtual/column-window.js +72 -0
  53. package/dist/core/src/virtual/column-window.js.map +1 -0
  54. package/dist/core/src/virtual/row-pool.js +2 -1
  55. package/dist/core/src/virtual/row-pool.js.map +1 -1
  56. package/dist/core/src/virtual/row-sizes.js +152 -0
  57. package/dist/core/src/virtual/row-sizes.js.map +1 -0
  58. package/dist/core/src/virtual/scroll-scale.js +41 -3
  59. package/dist/core/src/virtual/scroll-scale.js.map +1 -1
  60. package/dist/custom-elements.json +1683 -211
  61. package/dist/events.js +16 -8
  62. package/dist/events.js.map +1 -1
  63. package/dist/index.d.ts +808 -127
  64. package/dist/index.js +4 -2
  65. package/dist/interactive.js +22 -0
  66. package/dist/interactive.js.map +1 -0
  67. package/dist/max-height.js +22 -8
  68. package/dist/max-height.js.map +1 -1
  69. package/dist/render/body.js +48 -8
  70. package/dist/render/body.js.map +1 -1
  71. package/dist/render/cells.js +22 -11
  72. package/dist/render/cells.js.map +1 -1
  73. package/dist/render/content-directive.js +115 -0
  74. package/dist/render/content-directive.js.map +1 -0
  75. package/dist/render/content.js +33 -10
  76. package/dist/render/content.js.map +1 -1
  77. package/dist/render/header.js +104 -22
  78. package/dist/render/header.js.map +1 -1
  79. package/dist/render/pinned-rows.js +1 -1
  80. package/dist/render/pinned-rows.js.map +1 -1
  81. package/dist/styles/base.js +1 -1
  82. package/dist/styles/base.js.map +1 -1
  83. package/package.json +1 -1
package/README.md CHANGED
@@ -51,7 +51,7 @@ npm i argus-table @argus-table/themes
51
51
  - **Label:** give it a name with `aria-label` or `aria-labelledby`.
52
52
  - **Columns and data** are JavaScript properties, because they hold objects and functions.
53
53
  - **Cells:** a column's `cell` function can return a string, a number, a DOM node or a Lit template.
54
- - **Theme:** `default.css` is neutral and uses the page's font. `material.css` is a Material-inspired alternative (load Roboto yourself). Both are optional, and the table is usable without either.
54
+ - **Theme:** `default.css` is neutral and uses the page's font. `material.css` (load Roboto yourself), `fluent.css` and `bootstrap.css` are Material-, Fluent- and Bootstrap-inspired alternatives, and `minimal.css` (load Instrument Sans yourself) is a quiet, airy one with an amber accent. All are optional, and the table is usable without any.
55
55
 
56
56
  ## Rows from a server
57
57
 
@@ -0,0 +1,66 @@
1
+ import { ArgusColumn } from "./argus-column.js";
2
+ import { flagConverter } from "./attributes.js";
3
+ import { notify, unwatchColumns, watchColumns } from "./column-registry.js";
4
+ import __decorate from "./_virtual/_@oxc-project_runtime@0.156.0/helpers/esm/decorate.js";
5
+ import { ReactiveElement } from "lit";
6
+ import { customElement, property } from "lit/decorators.js";
7
+ // src/argus-column-group.ts
8
+ var _ArgusColumnGroup;
9
+ var ArgusColumnGroup = _ArgusColumnGroup = class ArgusColumnGroup extends ReactiveElement {
10
+ constructor(..._args) {
11
+ super(..._args);
12
+ this.groupId = "";
13
+ this.#parent = null;
14
+ }
15
+ #parent;
16
+ #group;
17
+ /** Data only: no shadow root, nothing rendered. */
18
+ createRenderRoot() {
19
+ return this;
20
+ }
21
+ connectedCallback() {
22
+ super.connectedCallback();
23
+ watchColumns(this, () => {
24
+ this.#group = void 0;
25
+ notify(this.#parent);
26
+ });
27
+ this.#parent = this.parentElement;
28
+ notify(this.#parent);
29
+ }
30
+ disconnectedCallback() {
31
+ super.disconnectedCallback();
32
+ unwatchColumns(this);
33
+ const parent = this.#parent;
34
+ this.#parent = null;
35
+ notify(parent);
36
+ }
37
+ /**
38
+ * The group as the table reads it, with its column and group children in document order.
39
+ * @internal
40
+ */
41
+ toColumnGroup() {
42
+ return this.#group ??= {
43
+ id: this.groupId,
44
+ header: this.header,
45
+ reorderable: this.reorderable,
46
+ columns: [...this.children].flatMap((c) => {
47
+ if (c instanceof ArgusColumn) return [c.columnId];
48
+ if (c instanceof _ArgusColumnGroup) return [c.toColumnGroup()];
49
+ return [];
50
+ })
51
+ };
52
+ }
53
+ willUpdate() {
54
+ this.#group = void 0;
55
+ }
56
+ updated() {
57
+ notify(this.#parent);
58
+ }
59
+ };
60
+ __decorate([property({ attribute: "group-id" })], ArgusColumnGroup.prototype, "groupId", void 0);
61
+ __decorate([property()], ArgusColumnGroup.prototype, "header", void 0);
62
+ __decorate([property({ converter: flagConverter })], ArgusColumnGroup.prototype, "reorderable", void 0);
63
+ ArgusColumnGroup = _ArgusColumnGroup = __decorate([customElement("argus-column-group")], ArgusColumnGroup);
64
+ export { ArgusColumnGroup };
65
+
66
+ //# sourceMappingURL=argus-column-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"argus-column-group.js","names":["_decorate"],"sources":["../src/argus-column-group.ts"],"sourcesContent":["import { ReactiveElement } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ArgusColumn } from './argus-column.js';\nimport { flagConverter } from './attributes.js';\nimport { notify, unwatchColumns, watchColumns } from './column-registry.js';\nimport type { CellContent, ColumnGroup } from './types.js';\n\n/**\n * A header over the `<argus-column>` children it wraps, written as markup instead\n * of an entry in the table's `columnGroups` property. Groups nest: a group inside\n * a group adds a header row. It is data only and renders nothing.\n *\n * Only direct children of the table or of another group count. A non-empty\n * `columnGroups` property wins over the children, and a non-empty `columns`\n * property turns all column and group children off.\n *\n * @summary Declarative column group of an `<argus-table>`.\n */\n@customElement('argus-column-group')\nexport class ArgusColumnGroup extends ReactiveElement {\n /** Stable key. Must be unique among the table's groups; it may equal a column id. */\n @property({ attribute: 'group-id' })\n groupId = '';\n\n /** Header content: text as an attribute; a Lit template, a node or a function as a property. Default: the id. */\n @property()\n header?: CellContent | (() => CellContent);\n\n /** Whether the group can be moved as a whole. Default: `true`; `reorderable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n reorderable?: boolean;\n\n #parent: Element | null = null;\n #group: ColumnGroup | undefined;\n\n /** Data only: no shadow root, nothing rendered. */\n protected override createRenderRoot(): HTMLElement {\n return this;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Columns and groups inside tell this group, which tells its own parent.\n watchColumns(this, () => {\n this.#group = undefined;\n notify(this.#parent);\n });\n this.#parent = this.parentElement;\n notify(this.#parent);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n unwatchColumns(this);\n const parent = this.#parent;\n this.#parent = null;\n notify(parent);\n }\n\n /**\n * The group as the table reads it, with its column and group children in document order.\n * @internal\n */\n toColumnGroup(): ColumnGroup {\n return (this.#group ??= {\n id: this.groupId,\n header: this.header,\n reorderable: this.reorderable,\n columns: [...this.children].flatMap((c): (string | ColumnGroup)[] => {\n if (c instanceof ArgusColumn) return [c.columnId];\n if (c instanceof ArgusColumnGroup) return [c.toColumnGroup()];\n return [];\n }),\n });\n }\n\n protected override willUpdate(): void {\n this.#group = undefined;\n }\n\n protected override updated(): void {\n notify(this.#parent);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'argus-column-group': ArgusColumnGroup;\n }\n}\n"],"mappings":";;;;;;;;AAmBO,IAAM,mBAAA,oBAAN,MAAM,yBAAyB,gBAAgB;;;EAG1C,KAAA,UAAA;EAUgB,KAAA,UAAA;;CAA1B;CACA;;CAGA,mBAAmD;EACjD,OAAO;CACT;CAEA,oBAAmC;EACjC,MAAM,kBAAkB;EAExB,aAAa,YAAY;GACvB,KAAK,SAAS,KAAA;GACd,OAAO,KAAK,OAAO;EACrB,CAAC;EACD,KAAK,UAAU,KAAK;EACpB,OAAO,KAAK,OAAO;CACrB;CAEA,uBAAsC;EACpC,MAAM,qBAAqB;EAC3B,eAAe,IAAI;EACnB,MAAM,SAAS,KAAK;EACpB,KAAK,UAAU;EACf,OAAO,MAAM;CACf;;;;;CAMA,gBAA6B;EAC3B,OAAQ,KAAK,WAAW;GACtB,IAAI,KAAK;GACT,QAAQ,KAAK;GACb,aAAa,KAAK;GAClB,SAAS,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAgC;IACnE,IAAI,aAAa,aAAa,OAAO,CAAC,EAAE,QAAQ;IAChD,IAAI,aAAA,mBAA+B,OAAO,CAAC,EAAE,cAAc,CAAC;IAC5D,OAAO,CAAC;GACV,CAAC;EACH;CACF;CAEA,aAAsC;EACpC,KAAK,SAAS,KAAA;CAChB;CAEA,UAAmC;EACjC,OAAO,KAAK,OAAO;CACrB;AACF;AA9DGA,WAAA,CAAA,SAAS,EAAE,WAAW,WAAW,CAAC,CAAA,GAAA,iBAAA,WAAA,WAAA,KAAA,CAAA;AAIlCA,WAAA,CAAA,SAAS,CAAA,GAAA,iBAAA,WAAA,UAAA,KAAA,CAAA;AAITA,WAAA,CAAA,SAAS,EAAE,WAAW,cAAc,CAAC,CAAA,GAAA,iBAAA,WAAA,eAAA,KAAA,CAAA;AAXvC,mBAAA,oBAAAA,WAAA,CAAA,cAAc,oBAAoB,CAAA,GAAA,gBAAA"}
@@ -1,25 +1,10 @@
1
+ import { flagConverter } from "./attributes.js";
2
+ import { notify } from "./column-registry.js";
1
3
  import __decorate from "./_virtual/_@oxc-project_runtime@0.156.0/helpers/esm/decorate.js";
2
4
  import { ReactiveElement, html } from "lit";
3
5
  import { customElement, property } from "lit/decorators.js";
4
6
  import { templateContent } from "lit/directives/template-content.js";
5
7
  // src/argus-column.ts
6
- /**
7
- * Tables watching their `<argus-column>` children, by table element. Columns
8
- * call their parent's entry when they connect, disconnect or change, so the
9
- * table needs no MutationObserver on its own children (which would fire on
10
- * every light-DOM cell render while scrolling).
11
- */
12
- var watchers = /* @__PURE__ */ new WeakMap();
13
- /** Calls `onChange` whenever an `<argus-column>` child of `host` is added, removed, moved or changed. */
14
- function watchColumns(host, onChange) {
15
- watchers.set(host, onChange);
16
- }
17
- function unwatchColumns(host) {
18
- watchers.delete(host);
19
- }
20
- function notify(parent) {
21
- if (parent) watchers.get(parent)?.();
22
- }
23
8
  /** `width` attribute: `"90"` or `"90px"` → 90, `"auto"`, `"2fr"` → `{ flex: 2 }`. */
24
9
  var widthConverter = { fromAttribute(value) {
25
10
  if (value === null) return void 0;
@@ -30,13 +15,6 @@ var widthConverter = { fromAttribute(value) {
30
15
  const n = Number(match[1]);
31
16
  return match[2] === "fr" ? { flex: n } : n;
32
17
  } };
33
- /**
34
- * Boolean attribute with a default that may be `true`: absent → unset (the
35
- * default applies), `"false"` → `false`, anything else → `true`.
36
- */
37
- var flagConverter = { fromAttribute(value) {
38
- return value === null ? void 0 : value.trim().toLowerCase() !== "false";
39
- } };
40
18
  var ArgusColumn = class ArgusColumn extends ReactiveElement {
41
19
  constructor(..._args) {
42
20
  super(..._args);
@@ -50,6 +28,14 @@ var ArgusColumn = class ArgusColumn extends ReactiveElement {
50
28
  #parent;
51
29
  #def;
52
30
  #children;
31
+ /** `hidden` is the standard attribute: it updates the column like its own properties. */
32
+ static get observedAttributes() {
33
+ return [...super.observedAttributes, "hidden"];
34
+ }
35
+ attributeChangedCallback(name, old, value) {
36
+ super.attributeChangedCallback(name, old, value);
37
+ if (name === "hidden") this.requestUpdate();
38
+ }
53
39
  /** Data only: no shadow root, nothing rendered. */
54
40
  createRenderRoot() {
55
41
  return this;
@@ -71,6 +57,7 @@ var ArgusColumn = class ArgusColumn extends ReactiveElement {
71
57
  * The column as the table reads it. Unset fields stay `undefined`, which the
72
58
  * table reads as its defaults. An unknown `pin` is ignored and an unknown
73
59
  * `align` falls back to `start`.
60
+ * @internal
74
61
  */
75
62
  toColumnDef() {
76
63
  if (this.#def) return this.#def;
@@ -79,15 +66,23 @@ var ArgusColumn = class ArgusColumn extends ReactiveElement {
79
66
  id: this.columnId,
80
67
  header: this.header,
81
68
  accessor: this.accessor,
69
+ formula: this.formula,
82
70
  cell: this.cell ?? (template && (() => html`${templateContent(template)}`)),
83
71
  width: this.width,
84
72
  minWidth: this.minWidth,
85
73
  maxWidth: this.maxWidth,
86
74
  pin: this.pin,
75
+ hidden: this.hasAttribute("hidden"),
76
+ pinnable: this.pinnable,
77
+ hideable: this.hideable,
87
78
  align: this.align,
79
+ wrap: this.wrap,
88
80
  sortable: this.sortable,
89
81
  resizable: this.resizable,
90
- reorderable: this.reorderable
82
+ reorderable: this.reorderable,
83
+ filter: this.filter,
84
+ filterFn: this.filterFn,
85
+ filterOptions: this.filterOptions
91
86
  };
92
87
  }
93
88
  willUpdate() {
@@ -100,6 +95,7 @@ var ArgusColumn = class ArgusColumn extends ReactiveElement {
100
95
  __decorate([property({ attribute: "column-id" })], ArgusColumn.prototype, "columnId", void 0);
101
96
  __decorate([property()], ArgusColumn.prototype, "header", void 0);
102
97
  __decorate([property()], ArgusColumn.prototype, "accessor", void 0);
98
+ __decorate([property()], ArgusColumn.prototype, "formula", void 0);
103
99
  __decorate([property({ attribute: false })], ArgusColumn.prototype, "cell", void 0);
104
100
  __decorate([property({ converter: widthConverter })], ArgusColumn.prototype, "width", void 0);
105
101
  __decorate([property({
@@ -111,11 +107,17 @@ __decorate([property({
111
107
  type: Number
112
108
  })], ArgusColumn.prototype, "maxWidth", void 0);
113
109
  __decorate([property()], ArgusColumn.prototype, "pin", void 0);
110
+ __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "pinnable", void 0);
111
+ __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "hideable", void 0);
114
112
  __decorate([property()], ArgusColumn.prototype, "align", void 0);
113
+ __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "wrap", void 0);
115
114
  __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "sortable", void 0);
116
115
  __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "resizable", void 0);
117
116
  __decorate([property({ converter: flagConverter })], ArgusColumn.prototype, "reorderable", void 0);
117
+ __decorate([property()], ArgusColumn.prototype, "filter", void 0);
118
+ __decorate([property({ attribute: false })], ArgusColumn.prototype, "filterFn", void 0);
119
+ __decorate([property({ attribute: false })], ArgusColumn.prototype, "filterOptions", void 0);
118
120
  ArgusColumn = __decorate([customElement("argus-column")], ArgusColumn);
119
- export { ArgusColumn, unwatchColumns, watchColumns };
121
+ export { ArgusColumn };
120
122
 
121
123
  //# sourceMappingURL=argus-column.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"argus-column.js","names":["_decorate"],"sources":["../src/argus-column.ts"],"sourcesContent":["import { html, ReactiveElement, type ComplexAttributeConverter } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { templateContent } from 'lit/directives/template-content.js';\nimport type {\n CellContent,\n CellContext,\n ColumnAlign,\n ColumnDef,\n ColumnPin,\n ColumnWidth,\n} from './types.js';\n\n/**\n * Tables watching their `<argus-column>` children, by table element. Columns\n * call their parent's entry when they connect, disconnect or change, so the\n * table needs no MutationObserver on its own children (which would fire on\n * every light-DOM cell render while scrolling).\n */\nconst watchers = new WeakMap<Element, () => void>();\n\n/** Calls `onChange` whenever an `<argus-column>` child of `host` is added, removed, moved or changed. */\nexport function watchColumns(host: Element, onChange: () => void): void {\n watchers.set(host, onChange);\n}\n\nexport function unwatchColumns(host: Element): void {\n watchers.delete(host);\n}\n\nfunction notify(parent: Element | null): void {\n if (parent) watchers.get(parent)?.();\n}\n\n/** `width` attribute: `\"90\"` or `\"90px\"` → 90, `\"auto\"`, `\"2fr\"` → `{ flex: 2 }`. */\nconst widthConverter: ComplexAttributeConverter<ColumnWidth | undefined> = {\n fromAttribute(value) {\n if (value === null) return undefined;\n const text = value.trim().toLowerCase();\n if (text === 'auto') return 'auto';\n const match = /^(\\d*\\.?\\d+)(px|fr)?$/.exec(text);\n if (!match) return undefined;\n const n = Number(match[1]);\n return match[2] === 'fr' ? { flex: n } : n;\n },\n};\n\n/**\n * Boolean attribute with a default that may be `true`: absent → unset (the\n * default applies), `\"false\"` → `false`, anything else → `true`.\n */\nconst flagConverter: ComplexAttributeConverter<boolean | undefined> = {\n fromAttribute(value) {\n return value === null ? undefined : value.trim().toLowerCase() !== 'false';\n },\n};\n\n/**\n * One column of the parent `<argus-table>`, written as markup instead of an entry in\n * its `columns` property. It is data only and renders nothing.\n *\n * Only direct children of the table count, in document order. A non-empty `columns`\n * property wins over the children. Adding, removing, moving or changing a column\n * updates the table; sizes, order and sorting are kept by `column-id`.\n *\n * A `<template>` child is the content of every cell in the column (static: the same\n * for each row). Set the `cell` property for content that depends on the row.\n *\n * @summary Declarative column of an `<argus-table>`.\n */\n@customElement('argus-column')\nexport class ArgusColumn<T = unknown> extends ReactiveElement {\n /** Stable key, used in state objects, events and persistence. Must be unique within the table. */\n @property({ attribute: 'column-id' })\n columnId = '';\n\n /** Header content: text as an attribute; a Lit template, a node or a function as a property. */\n @property()\n header?: CellContent | (() => CellContent);\n\n /**\n * How to read the cell value: a property path such as `customer.name`, or (as a\n * property) a function of the row and its index.\n */\n @property()\n accessor?: string | ((row: T, index: number) => unknown);\n\n /** Cell content from the row: `(row, context) => content`. Property only; wins over a `<template>` child. */\n @property({ attribute: false })\n cell?: (row: T, context: CellContext<T>) => CellContent;\n\n /** Width: `90` (px), `auto` to fit the content, or `2fr` for a share of the free space. Default: 150 px. */\n @property({ converter: widthConverter })\n width?: ColumnWidth;\n\n /** Lower bound for resizing and for flex columns, in px. Default: 40. */\n @property({ attribute: 'min-width', type: Number })\n minWidth?: number;\n\n /** Upper bound for resizing, in px. Default: no limit. */\n @property({ attribute: 'max-width', type: Number })\n maxWidth?: number;\n\n /** Pins the column to the `start` or `end` side. */\n @property()\n pin?: ColumnPin;\n\n /** Text alignment: `start`, `center` or `end`. Default: `start`. */\n @property()\n align?: ColumnAlign;\n\n /** Whether the header can be clicked to sort. Default: `false`. */\n @property({ converter: flagConverter })\n sortable?: boolean;\n\n /** Whether the column can be resized. Default: `true`; `resizable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n resizable?: boolean;\n\n /** Whether the column can be moved. Default: `true`; `reorderable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n reorderable?: boolean;\n\n #parent: Element | null = null;\n #def: ColumnDef<T> | undefined;\n readonly #children = new MutationObserver(() => {\n this.#def = undefined;\n this.requestUpdate();\n });\n\n /** Data only: no shadow root, nothing rendered. */\n protected override createRenderRoot(): HTMLElement {\n return this;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.#children.observe(this, { childList: true });\n this.#parent = this.parentElement;\n notify(this.#parent);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#children.disconnect();\n const parent = this.#parent;\n this.#parent = null;\n notify(parent);\n }\n\n /**\n * The column as the table reads it. Unset fields stay `undefined`, which the\n * table reads as its defaults. An unknown `pin` is ignored and an unknown\n * `align` falls back to `start`.\n */\n toColumnDef(): ColumnDef<T> {\n if (this.#def) return this.#def;\n const template = [...this.children].find((c) => c instanceof HTMLTemplateElement);\n return (this.#def = {\n id: this.columnId,\n header: this.header,\n accessor: this.accessor,\n cell: this.cell ?? (template && (() => html`${templateContent(template)}`)),\n width: this.width,\n minWidth: this.minWidth,\n maxWidth: this.maxWidth,\n pin: this.pin,\n align: this.align,\n sortable: this.sortable,\n resizable: this.resizable,\n reorderable: this.reorderable,\n });\n }\n\n protected override willUpdate(): void {\n this.#def = undefined;\n }\n\n protected override updated(): void {\n notify(this.#parent);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'argus-column': ArgusColumn;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"argus-column.js","names":["_decorate"],"sources":["../src/argus-column.ts"],"sourcesContent":["import { html, ReactiveElement, type ComplexAttributeConverter } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { templateContent } from 'lit/directives/template-content.js';\nimport { flagConverter } from './attributes.js';\nimport { notify } from './column-registry.js';\nimport type {\n CellContent,\n CellContext,\n ColumnAlign,\n ColumnDef,\n ColumnPin,\n ColumnWidth,\n FilterKind,\n FilterValue,\n} from './types.js';\n\n/** `width` attribute: `\"90\"` or `\"90px\"` → 90, `\"auto\"`, `\"2fr\"` → `{ flex: 2 }`. */\nconst widthConverter: ComplexAttributeConverter<ColumnWidth | undefined> = {\n fromAttribute(value) {\n if (value === null) return undefined;\n const text = value.trim().toLowerCase();\n if (text === 'auto') return 'auto';\n const match = /^(\\d*\\.?\\d+)(px|fr)?$/.exec(text);\n if (!match) return undefined;\n const n = Number(match[1]);\n return match[2] === 'fr' ? { flex: n } : n;\n },\n};\n\n/**\n * One column of the parent `<argus-table>`, written as markup instead of an entry in\n * its `columns` property. It is data only and renders nothing.\n *\n * Only direct children of the table or of an `<argus-column-group>` count, in\n * document order. A non-empty `columns` property wins over the children. Adding, removing, moving or changing a column\n * updates the table; sizes, order and sorting are kept by `column-id`.\n *\n * A `<template>` child is the content of every cell in the column (static: the same\n * for each row). Set the `cell` property for content that depends on the row.\n *\n * The standard `hidden` attribute (or property) hides the column, like `hidden` in\n * `columns`; the table's `columnVisibility` overrides it.\n *\n * @summary Declarative column of an `<argus-table>`.\n */\n@customElement('argus-column')\nexport class ArgusColumn<T = unknown> extends ReactiveElement {\n /** Stable key, used in state objects, events and persistence. Must be unique within the table. */\n @property({ attribute: 'column-id' })\n columnId = '';\n\n /** Header content: text as an attribute; a Lit template, a node or a function as a property. */\n @property()\n header?: CellContent | (() => CellContent);\n\n /**\n * How to read the cell value: a property path such as `customer.name`, or (as a\n * property) a function of the row and its index.\n */\n @property()\n accessor?: string | ((row: T, index: number) => unknown);\n\n /**\n * A spreadsheet formula computed per row from other columns, such as\n * `[price] * [quantity]`. Needs the `formulas()` plugin from `@argus-table/formulas`.\n */\n @property()\n formula?: string;\n\n /** Cell content from the row: `(row, context) => content`. Property only; wins over a `<template>` child. */\n @property({ attribute: false })\n cell?: (row: T, context: CellContext<T>) => CellContent;\n\n /** Width: `90` (px), `auto` to fit the content, or `2fr` for a share of the free space. Default: 150 px. */\n @property({ converter: widthConverter })\n width?: ColumnWidth;\n\n /** Lower bound for resizing and for flex columns, in px. Default: 40. */\n @property({ attribute: 'min-width', type: Number })\n minWidth?: number;\n\n /** Upper bound for resizing, in px. Default: no limit. */\n @property({ attribute: 'max-width', type: Number })\n maxWidth?: number;\n\n /** Pins the column to the `start` or `end` side. The table's `columnPinning` overrides it. */\n @property()\n pin?: ColumnPin;\n\n /** Whether the user can pin or unpin the column. Default: `true`; `pinnable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n pinnable?: boolean;\n\n /** Whether the user can hide the column. Default: `true`; `hideable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n hideable?: boolean;\n\n /** Text alignment: `start`, `center` or `end`. Default: `start`. */\n @property()\n align?: ColumnAlign;\n\n /**\n * Wraps the cell text onto more lines instead of cutting it off. Default:\n * `false`. With a fixed row height, text that doesn't fit is clipped.\n */\n @property({ converter: flagConverter })\n wrap?: boolean;\n\n /** Whether the header can be clicked to sort. Default: `false`. */\n @property({ converter: flagConverter })\n sortable?: boolean;\n\n /** Whether the column can be resized. Default: `true`; `resizable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n resizable?: boolean;\n\n /** Whether the column can be moved. Default: `true`; `reorderable=\"false\"` turns it off. */\n @property({ converter: flagConverter })\n reorderable?: boolean;\n\n /**\n * The kind of filter users can set, e.g. from the column menu: `text`, `number`,\n * `date` or `set`. Unset: users can't filter the column.\n */\n @property()\n filter?: FilterKind;\n\n /** Replaces the built-in matching for this column's filter. Property only. */\n @property({ attribute: false })\n filterFn?: ColumnDef<T>['filterFn'];\n\n /** The values a `set` filter offers; needed with a `dataSource`. Property only. */\n @property({ attribute: false })\n filterOptions?: readonly FilterValue[];\n\n #parent: Element | null = null;\n #def: ColumnDef<T> | undefined;\n readonly #children = new MutationObserver(() => {\n this.#def = undefined;\n this.requestUpdate();\n });\n\n /** `hidden` is the standard attribute: it updates the column like its own properties. */\n static override get observedAttributes(): string[] {\n return [...super.observedAttributes, 'hidden'];\n }\n\n override attributeChangedCallback(name: string, old: string | null, value: string | null): void {\n super.attributeChangedCallback(name, old, value);\n if (name === 'hidden') this.requestUpdate();\n }\n\n /** Data only: no shadow root, nothing rendered. */\n protected override createRenderRoot(): HTMLElement {\n return this;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.#children.observe(this, { childList: true });\n this.#parent = this.parentElement;\n notify(this.#parent);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#children.disconnect();\n const parent = this.#parent;\n this.#parent = null;\n notify(parent);\n }\n\n /**\n * The column as the table reads it. Unset fields stay `undefined`, which the\n * table reads as its defaults. An unknown `pin` is ignored and an unknown\n * `align` falls back to `start`.\n * @internal\n */\n toColumnDef(): ColumnDef<T> {\n if (this.#def) return this.#def;\n const template = [...this.children].find((c) => c instanceof HTMLTemplateElement);\n return (this.#def = {\n id: this.columnId,\n header: this.header,\n accessor: this.accessor,\n formula: this.formula,\n cell: this.cell ?? (template && (() => html`${templateContent(template)}`)),\n width: this.width,\n minWidth: this.minWidth,\n maxWidth: this.maxWidth,\n pin: this.pin,\n hidden: this.hasAttribute('hidden'),\n pinnable: this.pinnable,\n hideable: this.hideable,\n align: this.align,\n wrap: this.wrap,\n sortable: this.sortable,\n resizable: this.resizable,\n reorderable: this.reorderable,\n filter: this.filter,\n filterFn: this.filterFn,\n filterOptions: this.filterOptions,\n });\n }\n\n protected override willUpdate(): void {\n this.#def = undefined;\n }\n\n protected override updated(): void {\n notify(this.#parent);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'argus-column': ArgusColumn;\n }\n}\n"],"mappings":"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"}