mtrl-addons 0.1.0 → 0.1.2

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 (92) hide show
  1. package/.cursorrules +117 -0
  2. package/AI.md +241 -0
  3. package/build.js +148 -0
  4. package/bun.lock +792 -0
  5. package/index.ts +7 -0
  6. package/package.json +10 -17
  7. package/scripts/analyze-orphaned-functions.ts +387 -0
  8. package/src/components/index.ts +45 -0
  9. package/src/components/list/api.ts +314 -0
  10. package/src/components/list/config.ts +352 -0
  11. package/src/components/list/constants.ts +56 -0
  12. package/src/components/list/features/api.ts +428 -0
  13. package/src/components/list/features/index.ts +31 -0
  14. package/src/components/list/features/list-manager.ts +502 -0
  15. package/src/components/list/features.ts +112 -0
  16. package/src/components/list/index.ts +39 -0
  17. package/src/components/list/list.ts +234 -0
  18. package/src/components/list/types.ts +513 -0
  19. package/src/core/collection/base-collection.ts +100 -0
  20. package/src/core/collection/collection-composer.ts +178 -0
  21. package/src/core/collection/collection.ts +745 -0
  22. package/src/core/collection/constants.ts +172 -0
  23. package/src/core/collection/events.ts +428 -0
  24. package/src/core/collection/features/api/loading.ts +279 -0
  25. package/src/core/collection/features/operations/data-operations.ts +147 -0
  26. package/src/core/collection/index.ts +104 -0
  27. package/src/core/collection/state.ts +497 -0
  28. package/src/core/collection/types.ts +404 -0
  29. package/src/core/compose/features/collection.ts +119 -0
  30. package/src/core/compose/features/index.ts +39 -0
  31. package/src/core/compose/features/performance.ts +161 -0
  32. package/src/core/compose/features/selection.ts +213 -0
  33. package/src/core/compose/features/styling.ts +108 -0
  34. package/src/core/compose/index.ts +31 -0
  35. package/src/core/index.ts +167 -0
  36. package/src/core/layout/config.ts +102 -0
  37. package/src/core/layout/index.ts +168 -0
  38. package/src/core/layout/jsx.ts +174 -0
  39. package/src/core/layout/schema.ts +963 -0
  40. package/src/core/layout/types.ts +92 -0
  41. package/src/core/list-manager/api.ts +599 -0
  42. package/src/core/list-manager/config.ts +593 -0
  43. package/src/core/list-manager/constants.ts +268 -0
  44. package/src/core/list-manager/features/api.ts +58 -0
  45. package/src/core/list-manager/features/collection/collection.ts +705 -0
  46. package/src/core/list-manager/features/collection/index.ts +17 -0
  47. package/src/core/list-manager/features/viewport/constants.ts +42 -0
  48. package/src/core/list-manager/features/viewport/index.ts +16 -0
  49. package/src/core/list-manager/features/viewport/item-size.ts +274 -0
  50. package/src/core/list-manager/features/viewport/loading.ts +263 -0
  51. package/src/core/list-manager/features/viewport/placeholders.ts +281 -0
  52. package/src/core/list-manager/features/viewport/rendering.ts +575 -0
  53. package/src/core/list-manager/features/viewport/scrollbar.ts +495 -0
  54. package/src/core/list-manager/features/viewport/scrolling.ts +795 -0
  55. package/src/core/list-manager/features/viewport/template.ts +220 -0
  56. package/src/core/list-manager/features/viewport/viewport.ts +654 -0
  57. package/src/core/list-manager/features/viewport/virtual.ts +309 -0
  58. package/src/core/list-manager/index.ts +279 -0
  59. package/src/core/list-manager/list-manager.ts +206 -0
  60. package/src/core/list-manager/types.ts +439 -0
  61. package/src/core/list-manager/utils/calculations.ts +290 -0
  62. package/src/core/list-manager/utils/range-calculator.ts +349 -0
  63. package/src/core/list-manager/utils/speed-tracker.ts +273 -0
  64. package/src/index.ts +17 -0
  65. package/src/styles/components/_list.scss +244 -0
  66. package/src/styles/index.scss +12 -0
  67. package/src/types/mtrl.d.ts +6 -0
  68. package/test/benchmarks/layout/advanced.test.ts +656 -0
  69. package/test/benchmarks/layout/comparison.test.ts +519 -0
  70. package/test/benchmarks/layout/performance-comparison.test.ts +274 -0
  71. package/test/benchmarks/layout/real-components.test.ts +733 -0
  72. package/test/benchmarks/layout/simple.test.ts +321 -0
  73. package/test/benchmarks/layout/stress.test.ts +990 -0
  74. package/test/collection/basic.test.ts +304 -0
  75. package/test/components/list.test.ts +256 -0
  76. package/test/core/collection/collection.test.ts +394 -0
  77. package/test/core/collection/failed-ranges.test.ts +270 -0
  78. package/test/core/compose/features.test.ts +183 -0
  79. package/test/core/layout/layout.test.ts +201 -0
  80. package/test/core/list-manager/features/collection.test.ts +704 -0
  81. package/test/core/list-manager/features/viewport.test.ts +698 -0
  82. package/test/core/list-manager/list-manager.test.ts +593 -0
  83. package/test/core/list-manager/utils/calculations.test.ts +433 -0
  84. package/test/core/list-manager/utils/range-calculator.test.ts +569 -0
  85. package/test/core/list-manager/utils/speed-tracker.test.ts +530 -0
  86. package/test/utils/dom-helpers.ts +275 -0
  87. package/test/utils/performance-helpers.ts +392 -0
  88. package/tsconfig.build.json +23 -0
  89. package/tsconfig.json +20 -0
  90. package/dist/index.d.ts +0 -5
  91. package/dist/index.js +0 -38
  92. package/dist/index.mjs +0 -8
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Basic collection tests
3
+ *
4
+ * Tests the core functionality of the collection system
5
+ * including creation, data operations, and template rendering.
6
+ */
7
+
8
+ import { describe, test, expect, beforeEach } from "bun:test";
9
+ import { JSDOM } from "jsdom";
10
+
11
+ // Mock DOM environment for testing
12
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
13
+ global.document = dom.window.document;
14
+ global.HTMLElement = dom.window.HTMLElement;
15
+ global.requestAnimationFrame = (cb: FrameRequestCallback) => {
16
+ setTimeout(cb, 0);
17
+ return 0;
18
+ };
19
+
20
+ // Import our collection system
21
+ import {
22
+ createCollection,
23
+ type CollectionItem,
24
+ } from "../../src/core/collection";
25
+
26
+ // Test data interface
27
+ interface TestUser extends CollectionItem {
28
+ id: string;
29
+ name: string;
30
+ email: string;
31
+ age: number;
32
+ }
33
+
34
+ // Test data
35
+ const testUsers: TestUser[] = [
36
+ { id: "1", name: "John Doe", email: "john@example.com", age: 30 },
37
+ { id: "2", name: "Jane Smith", email: "jane@example.com", age: 25 },
38
+ { id: "3", name: "Bob Johnson", email: "bob@example.com", age: 35 },
39
+ ];
40
+
41
+ describe("Collection System", () => {
42
+ let container: HTMLElement;
43
+
44
+ beforeEach(() => {
45
+ // Create a fresh container for each test
46
+ container = document.createElement("div");
47
+ document.body.appendChild(container);
48
+ });
49
+
50
+ test("creates collection with basic configuration", () => {
51
+ const collection = createCollection<TestUser>({
52
+ container,
53
+ items: testUsers,
54
+ className: "user-list",
55
+ ariaLabel: "User List",
56
+ });
57
+
58
+ expect(collection.element).toBe(container);
59
+ expect(collection.getSize()).toBe(3);
60
+ expect(collection.isEmpty()).toBe(false);
61
+ expect(container.classList.contains("mtrl-collection")).toBe(true);
62
+ expect(container.classList.contains("user-list")).toBe(true);
63
+ expect(container.getAttribute("aria-label")).toBe("User List");
64
+ });
65
+
66
+ test("renders items with default template", async () => {
67
+ const collection = createCollection<TestUser>({
68
+ container,
69
+ items: testUsers,
70
+ });
71
+
72
+ // Wait for rendering
73
+ await new Promise((resolve) => setTimeout(resolve, 10));
74
+
75
+ expect(container.children.length).toBe(3);
76
+ expect(container.children[0].textContent).toBe("1");
77
+ expect(container.children[1].textContent).toBe("2");
78
+ expect(container.children[2].textContent).toBe("3");
79
+ });
80
+
81
+ test("renders items with object template", async () => {
82
+ const collection = createCollection<TestUser>({
83
+ container,
84
+ items: testUsers,
85
+ template: {
86
+ tag: "div",
87
+ className: "user-item",
88
+ children: [
89
+ { tag: "div", className: "user-name", textContent: "{{name}}" },
90
+ { tag: "div", className: "user-email", textContent: "{{email}}" },
91
+ ],
92
+ },
93
+ });
94
+
95
+ // Wait for rendering
96
+ await new Promise((resolve) => setTimeout(resolve, 10));
97
+
98
+ expect(container.children.length).toBe(3);
99
+
100
+ const firstUser = container.children[0] as HTMLElement;
101
+ expect(firstUser.className).toBe("user-item");
102
+ expect(firstUser.children.length).toBe(2);
103
+ expect(firstUser.children[0].textContent).toBe("John Doe");
104
+ expect(firstUser.children[1].textContent).toBe("john@example.com");
105
+ });
106
+
107
+ test("renders items with string template", async () => {
108
+ const collection = createCollection<TestUser>({
109
+ container,
110
+ items: testUsers,
111
+ template: "<div class='user'>{{name}} ({{email}})</div>",
112
+ });
113
+
114
+ // Wait for rendering
115
+ await new Promise((resolve) => setTimeout(resolve, 10));
116
+
117
+ expect(container.children.length).toBe(3);
118
+ expect(container.children[0].innerHTML).toBe(
119
+ "<div class='user'>John Doe (john@example.com)</div>"
120
+ );
121
+ });
122
+
123
+ test("adds new items", async () => {
124
+ const collection = createCollection<TestUser>({
125
+ container,
126
+ items: [testUsers[0]],
127
+ });
128
+
129
+ expect(collection.getSize()).toBe(1);
130
+
131
+ const newUser: TestUser = {
132
+ id: "4",
133
+ name: "Alice Brown",
134
+ email: "alice@example.com",
135
+ age: 28,
136
+ };
137
+ await collection.add(newUser);
138
+
139
+ expect(collection.getSize()).toBe(2);
140
+ const items = collection.getItems();
141
+ expect(items.length).toBe(2);
142
+ expect(items[1].name).toBe("Alice Brown");
143
+ });
144
+
145
+ test("updates existing items", async () => {
146
+ const collection = createCollection<TestUser>({
147
+ container,
148
+ items: testUsers,
149
+ });
150
+
151
+ const updatedUser: TestUser = {
152
+ id: "1",
153
+ name: "John Smith",
154
+ email: "johnsmith@example.com",
155
+ age: 31,
156
+ };
157
+
158
+ await collection.update(updatedUser);
159
+
160
+ const user = collection.getItem("1");
161
+ expect(user?.name).toBe("John Smith");
162
+ expect(user?.email).toBe("johnsmith@example.com");
163
+ });
164
+
165
+ test("removes items", async () => {
166
+ const collection = createCollection<TestUser>({
167
+ container,
168
+ items: testUsers,
169
+ });
170
+
171
+ expect(collection.getSize()).toBe(3);
172
+
173
+ await collection.remove("2");
174
+
175
+ expect(collection.getSize()).toBe(2);
176
+ expect(collection.getItem("2")).toBeUndefined();
177
+ expect(collection.getItem("1")).toBeDefined();
178
+ expect(collection.getItem("3")).toBeDefined();
179
+ });
180
+
181
+ test("clears all items", () => {
182
+ const collection = createCollection<TestUser>({
183
+ container,
184
+ items: testUsers,
185
+ });
186
+
187
+ expect(collection.getSize()).toBe(3);
188
+
189
+ collection.clear();
190
+
191
+ expect(collection.getSize()).toBe(0);
192
+ expect(collection.isEmpty()).toBe(true);
193
+ });
194
+
195
+ test("filters items with query", () => {
196
+ const collection = createCollection<TestUser>({
197
+ container,
198
+ items: testUsers,
199
+ });
200
+
201
+ expect(collection.getSize()).toBe(3);
202
+
203
+ // Filter users over 30
204
+ collection.query((user) => user.age > 30);
205
+
206
+ expect(collection.getSize()).toBe(1);
207
+ expect(collection.getItems()[0].name).toBe("Bob Johnson");
208
+ });
209
+
210
+ test("sorts items", () => {
211
+ const collection = createCollection<TestUser>({
212
+ container,
213
+ items: testUsers,
214
+ });
215
+
216
+ // Sort by age ascending
217
+ collection.sort((a, b) => a.age - b.age);
218
+
219
+ const items = collection.getItems();
220
+ expect(items[0].name).toBe("Jane Smith"); // age 25
221
+ expect(items[1].name).toBe("John Doe"); // age 30
222
+ expect(items[2].name).toBe("Bob Johnson"); // age 35
223
+ });
224
+
225
+ test("validates items when adding", async () => {
226
+ const collection = createCollection<TestUser>({
227
+ container,
228
+ items: [],
229
+ validate: (user) => user.age >= 18,
230
+ });
231
+
232
+ const validUser: TestUser = {
233
+ id: "1",
234
+ name: "John Doe",
235
+ email: "john@example.com",
236
+ age: 30,
237
+ };
238
+ const invalidUser: TestUser = {
239
+ id: "2",
240
+ name: "Minor",
241
+ email: "minor@example.com",
242
+ age: 16,
243
+ };
244
+
245
+ await collection.add([validUser, invalidUser]);
246
+
247
+ expect(collection.getSize()).toBe(1);
248
+ expect(collection.getItems()[0].name).toBe("John Doe");
249
+ });
250
+
251
+ test("transforms items when adding", async () => {
252
+ const collection = createCollection<TestUser>({
253
+ container,
254
+ items: [],
255
+ transform: (user: any) => ({
256
+ ...user,
257
+ name: user.name.toUpperCase(),
258
+ }),
259
+ });
260
+
261
+ const user: TestUser = {
262
+ id: "1",
263
+ name: "John Doe",
264
+ email: "john@example.com",
265
+ age: 30,
266
+ };
267
+ await collection.add(user);
268
+
269
+ expect(collection.getItems()[0].name).toBe("JOHN DOE");
270
+ });
271
+
272
+ test("handles template changes", async () => {
273
+ const collection = createCollection<TestUser>({
274
+ container,
275
+ items: [testUsers[0]],
276
+ });
277
+
278
+ // Change template
279
+ collection.setTemplate({
280
+ tag: "div",
281
+ className: "new-template",
282
+ textContent: "User: {{name}}",
283
+ });
284
+
285
+ // Wait for rendering
286
+ await new Promise((resolve) => setTimeout(resolve, 10));
287
+
288
+ expect(container.children[0].textContent).toBe("User: John Doe");
289
+ expect(container.children[0].className).toBe("new-template");
290
+ });
291
+
292
+ test("destroys collection properly", () => {
293
+ const collection = createCollection<TestUser>({
294
+ container,
295
+ items: testUsers,
296
+ });
297
+
298
+ expect(container.children.length).toBeGreaterThan(0);
299
+
300
+ collection.destroy();
301
+
302
+ expect(container.children.length).toBe(0);
303
+ });
304
+ });
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Basic list component tests
3
+ *
4
+ * Tests the pipe composition list component that wraps the collection system
5
+ */
6
+
7
+ import { describe, test, expect, beforeEach } from "bun:test";
8
+ import { JSDOM } from "jsdom";
9
+
10
+ // Mock DOM environment for testing
11
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
12
+ global.document = dom.window.document;
13
+ global.HTMLElement = dom.window.HTMLElement;
14
+ global.window = dom.window as any;
15
+ global.navigator = dom.window.navigator;
16
+ global.requestAnimationFrame = (cb: FrameRequestCallback) => {
17
+ setTimeout(cb, 0);
18
+ return 0;
19
+ };
20
+
21
+ // Mock scrollIntoView since JSDOM doesn't implement it
22
+ global.HTMLElement.prototype.scrollIntoView = function (
23
+ options?: ScrollIntoViewOptions
24
+ ) {
25
+ // Mock implementation - just logs the call
26
+ console.log(`Mock scrollIntoView called with options:`, options);
27
+ };
28
+
29
+ // Import our list component
30
+ import { createList, type ListItem } from "../../src/components/list";
31
+
32
+ // Test data interface
33
+ interface TestUser extends ListItem {
34
+ id: string;
35
+ name: string;
36
+ email: string;
37
+ age: number;
38
+ }
39
+
40
+ // Test data
41
+ const testUsers: TestUser[] = [
42
+ { id: "1", name: "John Doe", email: "john@example.com", age: 30 },
43
+ { id: "2", name: "Jane Smith", email: "jane@example.com", age: 25 },
44
+ { id: "3", name: "Bob Johnson", email: "bob@example.com", age: 35 },
45
+ ];
46
+
47
+ describe("List Component (Pipe Composition)", () => {
48
+ let container: HTMLElement;
49
+
50
+ beforeEach(() => {
51
+ // Create a fresh container for each test
52
+ container = document.createElement("div");
53
+ document.body.appendChild(container);
54
+ });
55
+
56
+ test("creates list with pipe composition pattern", () => {
57
+ const list = createList<TestUser>({
58
+ container,
59
+ items: testUsers,
60
+ className: "user-list",
61
+ ariaLabel: "User List",
62
+ });
63
+
64
+ // mtrl creates a new element and mounts it to the container
65
+ expect(list.element).not.toBe(container);
66
+ expect(list.element.parentElement).toBe(container);
67
+ expect(list.getSize()).toBe(3);
68
+ expect(list.isEmpty()).toBe(false);
69
+ expect(list.element.classList.contains("mtrl-list")).toBe(true);
70
+ expect(list.element.getAttribute("aria-label")).toBe("User List");
71
+ expect(list.element.getAttribute("role")).toBe("list");
72
+ });
73
+
74
+ test("applies list styling through composition", async () => {
75
+ const list = createList<TestUser>({
76
+ container,
77
+ items: testUsers,
78
+ listStyle: {
79
+ itemSize: 60,
80
+ gap: 8,
81
+ padding: 16,
82
+ striped: true,
83
+ hoverable: true,
84
+ bordered: false,
85
+ },
86
+ });
87
+
88
+ // Wait for rendering
89
+ await new Promise((resolve) => setTimeout(resolve, 10));
90
+
91
+ // Check styling on the list element, not the container
92
+ expect(list.element.style.getPropertyValue("--mtrl-list-gap")).toBe("8px");
93
+ expect(list.element.style.getPropertyValue("--mtrl-list-padding")).toBe(
94
+ "16px"
95
+ );
96
+ expect(list.element.style.getPropertyValue("--mtrl-list-item-height")).toBe(
97
+ "60px"
98
+ );
99
+ expect(list.element.classList.contains("mtrl-list--striped")).toBe(true);
100
+ expect(list.element.classList.contains("mtrl-list--hoverable")).toBe(true);
101
+ expect(list.element.classList.contains("mtrl-list--bordered")).toBe(false);
102
+ });
103
+
104
+ test("enables selection through composition", async () => {
105
+ const list = createList<TestUser>({
106
+ container,
107
+ items: testUsers,
108
+ selection: {
109
+ enabled: true,
110
+ multiple: true,
111
+ },
112
+ });
113
+
114
+ // Wait for rendering
115
+ await new Promise((resolve) => setTimeout(resolve, 10));
116
+
117
+ // Test selection methods exist
118
+ expect(typeof list.selectItem).toBe("function");
119
+ expect(typeof list.deselectItem).toBe("function");
120
+ expect(typeof list.selectAll).toBe("function");
121
+ expect(typeof list.deselectAll).toBe("function");
122
+ expect(typeof list.getSelectedItems).toBe("function");
123
+ expect(typeof list.getSelectedIds).toBe("function");
124
+
125
+ // Test selection functionality
126
+ list.selectItem("1");
127
+ expect(list.getSelectedIds()).toContain("1");
128
+ expect(list.getSelectedItems().length).toBe(1);
129
+
130
+ list.selectItem("2");
131
+ expect(list.getSelectedIds()).toHaveLength(2);
132
+
133
+ list.deselectItem("1");
134
+ expect(list.getSelectedIds()).toHaveLength(1);
135
+ expect(list.getSelectedIds()).toContain("2");
136
+
137
+ list.deselectAll();
138
+ expect(list.getSelectedIds()).toHaveLength(0);
139
+ });
140
+
141
+ test("tracks performance through composition", async () => {
142
+ const list = createList<TestUser>({
143
+ container,
144
+ items: testUsers,
145
+ performance: {
146
+ recycleElements: true,
147
+ bufferSize: 50,
148
+ },
149
+ });
150
+
151
+ // Wait for rendering
152
+ await new Promise((resolve) => setTimeout(resolve, 10));
153
+
154
+ // Test performance methods exist
155
+ expect(typeof list.getMetrics).toBe("function");
156
+ expect(typeof list.resetMetrics).toBe("function");
157
+
158
+ const metrics = list.getMetrics();
159
+ expect(typeof metrics.renderCount).toBe("number");
160
+ expect(typeof metrics.scrollCount).toBe("number");
161
+ expect(typeof metrics.averageRenderTime).toBe("number");
162
+ expect(typeof metrics.averageScrollTime).toBe("number");
163
+ });
164
+
165
+ test("provides list API through composition", async () => {
166
+ const list = createList<TestUser>({
167
+ container,
168
+ items: testUsers,
169
+ });
170
+
171
+ // Wait for rendering
172
+ await new Promise((resolve) => setTimeout(resolve, 10));
173
+
174
+ // Test API methods exist
175
+ expect(typeof list.scrollToItem).toBe("function");
176
+ expect(typeof list.scrollToIndex).toBe("function");
177
+ expect(typeof list.scrollToPage).toBe("function");
178
+
179
+ // Test scrolling doesn't crash
180
+ list.scrollToItem("2");
181
+ list.scrollToIndex(1);
182
+ });
183
+
184
+ test("maintains collection functionality", async () => {
185
+ const list = createList<TestUser>({
186
+ container,
187
+ items: [testUsers[0]],
188
+ });
189
+
190
+ // Test collection methods still work
191
+ expect(list.getSize()).toBe(1);
192
+
193
+ const newUser: TestUser = {
194
+ id: "4",
195
+ name: "Alice Brown",
196
+ email: "alice@example.com",
197
+ age: 28,
198
+ };
199
+ await list.add(newUser);
200
+
201
+ expect(list.getSize()).toBe(2);
202
+ expect(list.getItem("4")?.name).toBe("Alice Brown");
203
+
204
+ await list.remove("1");
205
+ expect(list.getSize()).toBe(1);
206
+ expect(list.getItem("1")).toBeUndefined();
207
+ });
208
+
209
+ test("console shows pipe composition pattern", () => {
210
+ // Capture console logs
211
+ const logs: string[] = [];
212
+ const originalLog = console.log;
213
+ console.log = (message: string) => {
214
+ logs.push(message);
215
+ };
216
+
217
+ try {
218
+ createList<TestUser>({
219
+ container,
220
+ items: testUsers,
221
+ selection: { enabled: true },
222
+ listStyle: { striped: true },
223
+ });
224
+
225
+ // Restore console
226
+ console.log = originalLog;
227
+
228
+ // Verify composition pattern logs
229
+ expect(
230
+ logs.some((log) =>
231
+ log.includes("Creating list component (mtrl compose system)")
232
+ )
233
+ ).toBe(true);
234
+ expect(
235
+ logs.some((log) => log.includes("Adding collection capabilities"))
236
+ ).toBe(true);
237
+ expect(
238
+ logs.some((log) => log.includes("Adding styling capabilities"))
239
+ ).toBe(true);
240
+ expect(
241
+ logs.some((log) => log.includes("Adding selection capabilities"))
242
+ ).toBe(true);
243
+ expect(
244
+ logs.some((log) => log.includes("Adding performance tracking"))
245
+ ).toBe(true);
246
+ expect(logs.some((log) => log.includes("Adding list API methods"))).toBe(
247
+ true
248
+ );
249
+ expect(
250
+ logs.some((log) => log.includes("created via mtrl compose system"))
251
+ ).toBe(true);
252
+ } finally {
253
+ console.log = originalLog;
254
+ }
255
+ });
256
+ });