tangrid 0.1.0 → 1.0.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.
package/README.md CHANGED
@@ -102,6 +102,26 @@ export class UsersTableComponent {
102
102
  }
103
103
  ```
104
104
 
105
+ ## Theming
106
+
107
+ The default theme is included with the component. For Material, Bootstrap, Ant, or Ant-alt themes, add the optional theme CSS to your global styles:
108
+
109
+ **angular.json:**
110
+ ```json
111
+ "styles": [
112
+ "node_modules/tangrid/styles/themes/material.css",
113
+ "node_modules/tangrid/styles/themes/bootstrap.css"
114
+ ]
115
+ ```
116
+
117
+ **Or in `styles.scss`:**
118
+ ```scss
119
+ @import 'tangrid/styles/themes/material.css';
120
+ @import 'tangrid/styles/themes/bootstrap.css';
121
+ ```
122
+
123
+ Use the `[theme]` input to switch: `theme="default"` | `theme="material"` | `theme="bootstrap"` | `theme="ant"` | `theme="ant-alt"`.
124
+
105
125
  ## API Reference
106
126
 
107
127
  ### `<tan-grid>` Component
@@ -0,0 +1,3 @@
1
+ {
2
+ "module": "../fesm2022/tangrid-config.mjs"
3
+ }
@@ -0,0 +1,168 @@
1
+ import { untracked, computed, signal, effect, afterNextRender, AfterRenderPhase, inject, DestroyRef } from '@angular/core';
2
+ import { Virtualizer, elementScroll, observeElementOffset, observeElementRect, windowScroll, observeWindowOffset, observeWindowRect } from '@tanstack/virtual-core';
3
+
4
+ function proxyVirtualizer(virtualizerSignal, lazyInit) {
5
+ return new Proxy(virtualizerSignal, {
6
+ apply() {
7
+ return virtualizerSignal();
8
+ },
9
+ get(target, property) {
10
+ const untypedTarget = target;
11
+ if (untypedTarget[property]) {
12
+ return untypedTarget[property];
13
+ }
14
+ let virtualizer = untracked(virtualizerSignal);
15
+ if (virtualizer == null) {
16
+ virtualizer = lazyInit();
17
+ untracked(() => virtualizerSignal.set(virtualizer));
18
+ }
19
+ // Create computed signals for each property that represents a reactive value
20
+ if (typeof property === 'string' &&
21
+ [
22
+ 'getTotalSize',
23
+ 'getVirtualItems',
24
+ 'isScrolling',
25
+ 'options',
26
+ 'range',
27
+ 'scrollDirection',
28
+ 'scrollElement',
29
+ 'scrollOffset',
30
+ 'scrollRect',
31
+ 'measureElementCache',
32
+ 'measurementsCache',
33
+ ].includes(property)) {
34
+ const isFunction = typeof virtualizer[property] === 'function';
35
+ Object.defineProperty(untypedTarget, property, {
36
+ value: isFunction
37
+ ? computed(() => target()[property]())
38
+ : computed(() => target()[property]),
39
+ configurable: true,
40
+ enumerable: true,
41
+ });
42
+ }
43
+ // Create plain signals for functions that accept arguments and return reactive values
44
+ if (typeof property === 'string' &&
45
+ [
46
+ 'getOffsetForAlignment',
47
+ 'getOffsetForIndex',
48
+ 'getVirtualItemForOffset',
49
+ 'indexFromElement',
50
+ ].includes(property)) {
51
+ const fn = virtualizer[property];
52
+ Object.defineProperty(untypedTarget, property, {
53
+ value: toComputed(virtualizerSignal, fn),
54
+ configurable: true,
55
+ enumerable: true,
56
+ });
57
+ }
58
+ return untypedTarget[property] || virtualizer[property];
59
+ },
60
+ has(_, property) {
61
+ return !!untracked(virtualizerSignal)[property];
62
+ },
63
+ ownKeys() {
64
+ return Reflect.ownKeys(untracked(virtualizerSignal));
65
+ },
66
+ getOwnPropertyDescriptor() {
67
+ return {
68
+ enumerable: true,
69
+ configurable: true,
70
+ };
71
+ },
72
+ });
73
+ }
74
+ function toComputed(signal, fn) {
75
+ const computedCache = {};
76
+ return (...args) => {
77
+ // Cache computeds by their arguments to avoid re-creating the computed on each call
78
+ const serializedArgs = serializeArgs(...args);
79
+ if (Object.prototype.hasOwnProperty.call(computedCache, serializedArgs)) {
80
+ return computedCache[serializedArgs]?.();
81
+ }
82
+ const computedSignal = computed(() => {
83
+ void signal();
84
+ return fn(...args);
85
+ });
86
+ computedCache[serializedArgs] = computedSignal;
87
+ return computedSignal();
88
+ };
89
+ }
90
+ function serializeArgs(...args) {
91
+ return JSON.stringify(args);
92
+ }
93
+ function createVirtualizerBase(options) {
94
+ let virtualizer;
95
+ function lazyInit() {
96
+ if (!virtualizer) {
97
+ virtualizer = new Virtualizer(options());
98
+ }
99
+ return virtualizer;
100
+ }
101
+ const virtualizerSignal = signal(virtualizer, { equal: () => false });
102
+ // two-way sync options
103
+ effect(() => {
104
+ const _options = options();
105
+ lazyInit();
106
+ virtualizerSignal.set(virtualizer);
107
+ virtualizer.setOptions({
108
+ ..._options,
109
+ onChange: (instance, sync) => {
110
+ // update virtualizerSignal so that dependent computeds recompute.
111
+ virtualizerSignal.set(instance);
112
+ _options.onChange?.(instance, sync);
113
+ },
114
+ });
115
+ // update virtualizerSignal so that dependent computeds recompute.
116
+ virtualizerSignal.set(virtualizer);
117
+ }, { allowSignalWrites: true });
118
+ const scrollElement = computed(() => options().getScrollElement());
119
+ // let the virtualizer know when the scroll element is changed
120
+ effect(() => {
121
+ const el = scrollElement();
122
+ if (el) {
123
+ untracked(virtualizerSignal)._willUpdate();
124
+ }
125
+ }, { allowSignalWrites: true });
126
+ let cleanup;
127
+ // FIX: Use function callback with options for afterNextRender
128
+ afterNextRender(() => (virtualizer ?? lazyInit())._didMount(), { phase: AfterRenderPhase.Read });
129
+ inject(DestroyRef).onDestroy(() => cleanup?.());
130
+ return proxyVirtualizer(virtualizerSignal, lazyInit);
131
+ }
132
+ function injectVirtualizer(options) {
133
+ const resolvedOptions = computed(() => {
134
+ const opts = options();
135
+ return {
136
+ observeElementRect: observeElementRect,
137
+ observeElementOffset: observeElementOffset,
138
+ scrollToFn: elementScroll,
139
+ getScrollElement: () => {
140
+ const elementOrRef = opts.scrollElement;
141
+ return ((isElementRef(elementOrRef)
142
+ ? elementOrRef.nativeElement
143
+ : elementOrRef) ?? null);
144
+ },
145
+ ...opts,
146
+ };
147
+ });
148
+ return createVirtualizerBase(resolvedOptions);
149
+ }
150
+ function isElementRef(elementOrRef) {
151
+ return elementOrRef != null && 'nativeElement' in elementOrRef;
152
+ }
153
+ function injectWindowVirtualizer(options) {
154
+ const resolvedOptions = computed(() => {
155
+ return {
156
+ getScrollElement: () => (typeof document !== 'undefined' ? window : null),
157
+ observeElementRect: observeWindowRect,
158
+ observeElementOffset: observeWindowOffset,
159
+ scrollToFn: windowScroll,
160
+ initialOffset: () => (typeof document !== 'undefined' ? window.scrollY : 0),
161
+ ...options(),
162
+ };
163
+ });
164
+ return createVirtualizerBase(resolvedOptions);
165
+ }
166
+
167
+ export { injectVirtualizer, injectWindowVirtualizer };
168
+ //# sourceMappingURL=tangrid-table-virtual-provider-DS8nOCc-.mjs.map