@esportsplus/template 0.32.2 → 0.32.4

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.
@@ -1,15 +1,6 @@
1
1
  import { Attributes, Element } from './types.js';
2
- declare const set: (element: Element, name: string, value: unknown) => void;
3
2
  declare const setClass: (element: Element, classlist: false | string | undefined, value: unknown) => void;
4
3
  declare const setProperty: (element: Element, name: string, value: unknown) => void;
4
+ declare const setProperties: (element: Element, value: Attributes | Attributes[]) => void;
5
5
  declare const setStyle: (element: Element, styles: false | string | undefined, value: unknown) => void;
6
- declare const spread: (element: Element, value: Attributes | Attributes[]) => void;
7
- declare const _default: {
8
- set: (element: Element, name: string, value: unknown) => void;
9
- setClass: (element: Element, classlist: false | string | undefined, value: unknown) => void;
10
- setProperty: (element: Element, name: string, value: unknown) => void;
11
- setStyle: (element: Element, styles: false | string | undefined, value: unknown) => void;
12
- spread: (element: Element, value: Attributes | Attributes[]) => void;
13
- };
14
- export default _default;
15
- export { set, setClass, setProperty, setStyle, spread };
6
+ export { setClass, setProperty, setProperties, setStyle };
@@ -1,9 +1,9 @@
1
1
  import { effect } from '@esportsplus/reactivity';
2
2
  import { isArray, isObject } from '@esportsplus/utilities';
3
- import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS, STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants.js';
3
+ import { STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants.js';
4
4
  import { raf } from './utilities.js';
5
5
  import q from '@esportsplus/queue';
6
- import event from './event/index.js';
6
+ import { runtime } from './event/index.js';
7
7
  let delimiters = {
8
8
  class: ' ',
9
9
  style: ';'
@@ -138,36 +138,10 @@ function schedule(ctx, element, name, state, value) {
138
138
  scheduled = true;
139
139
  raf(task);
140
140
  }
141
- function task() {
142
- let context, n = queue.length;
143
- while ((context = queue.next()) && n--) {
144
- let { element, updates } = context;
145
- for (let name in updates) {
146
- apply(element, name, updates[name]);
147
- }
148
- context.updates = {};
149
- context.updating = false;
150
- }
151
- if (queue.length) {
152
- raf(task);
153
- }
154
- else {
155
- scheduled = false;
156
- }
157
- }
158
- const set = (element, name, value) => {
141
+ function set(element, name, value) {
159
142
  if (typeof value === 'function') {
160
143
  if (name[0] === 'o' && name[1] === 'n') {
161
- let e = name.slice(2).toLowerCase(), key = name.toLowerCase();
162
- if (LIFECYCLE_EVENTS.has(key)) {
163
- event[key](element, value);
164
- }
165
- else if (DIRECT_ATTACH_EVENTS.has(key)) {
166
- event.direct(element, e, value);
167
- }
168
- else {
169
- event.delegate(element, e, value);
170
- }
144
+ runtime(element, name, value);
171
145
  }
172
146
  else {
173
147
  reactive(element, name, STATE_HYDRATING, value);
@@ -187,7 +161,24 @@ const set = (element, name, value) => {
187
161
  return;
188
162
  }
189
163
  (name === 'class' || name === 'style' ? list : property)(null, element, null, name, STATE_HYDRATING, value);
190
- };
164
+ }
165
+ function task() {
166
+ let context, n = queue.length;
167
+ while ((context = queue.next()) && n--) {
168
+ let { element, updates } = context;
169
+ for (let name in updates) {
170
+ apply(element, name, updates[name]);
171
+ }
172
+ context.updates = {};
173
+ context.updating = false;
174
+ }
175
+ if (queue.length) {
176
+ raf(task);
177
+ }
178
+ else {
179
+ scheduled = false;
180
+ }
181
+ }
191
182
  const setClass = (element, classlist, value) => {
192
183
  let ctx = context(element), store = ctx.store ??= {};
193
184
  store['class.static'] = classlist || '';
@@ -207,18 +198,7 @@ const setProperty = (element, name, value) => {
207
198
  property(null, element, null, name, STATE_HYDRATING, value);
208
199
  }
209
200
  };
210
- const setStyle = (element, styles, value) => {
211
- let ctx = context(element), store = ctx.store ??= {};
212
- store['style.static'] = styles || '';
213
- store['style'] ??= new Set();
214
- if (typeof value === 'function') {
215
- reactive(element, 'style', STATE_HYDRATING, value);
216
- }
217
- else {
218
- list(ctx, element, null, 'style', STATE_HYDRATING, value);
219
- }
220
- };
221
- const spread = function (element, value) {
201
+ const setProperties = function (element, value) {
222
202
  if (isObject(value)) {
223
203
  for (let name in value) {
224
204
  let v = value[name];
@@ -230,9 +210,19 @@ const spread = function (element, value) {
230
210
  }
231
211
  else if (isArray(value)) {
232
212
  for (let i = 0, n = value.length; i < n; i++) {
233
- spread(element, value[i]);
213
+ setProperties(element, value[i]);
234
214
  }
235
215
  }
236
216
  };
237
- export default { set, setClass, setProperty, setStyle, spread };
238
- export { set, setClass, setProperty, setStyle, spread };
217
+ const setStyle = (element, styles, value) => {
218
+ let ctx = context(element), store = ctx.store ??= {};
219
+ store['style.static'] = styles || '';
220
+ store['style'] ??= new Set();
221
+ if (typeof value === 'function') {
222
+ reactive(element, 'style', STATE_HYDRATING, value);
223
+ }
224
+ else {
225
+ list(ctx, element, null, 'style', STATE_HYDRATING, value);
226
+ }
227
+ };
228
+ export { setClass, setProperty, setProperties, setStyle };
@@ -4,15 +4,15 @@ declare const COMPILER_ENTRYPOINT = "html";
4
4
  declare const COMPILER_ENTRYPOINT_REACTIVITY = "reactive";
5
5
  declare const COMPILER_NAMESPACE: string;
6
6
  declare const enum COMPILER_TYPES {
7
- ArraySlot = 0,
8
- AttributeSlot = 1,
9
- AttributeSpreadSlot = 2,
10
- DocumentFragment = 3,
11
- Effect = 4,
12
- NodeSlot = 5,
13
- Primitive = 6,
14
- Static = 7,
15
- Unknown = 8
7
+ ArraySlot = "array-slot",
8
+ Attributes = "attributes",
9
+ Attribute = "attribute",
10
+ DocumentFragment = "document-fragment",
11
+ Effect = "effect",
12
+ Node = "node",
13
+ Primitive = "primitive",
14
+ Static = "static",
15
+ Unknown = "unknown"
16
16
  }
17
17
  declare const DIRECT_ATTACH_EVENTS: Set<string>;
18
18
  declare const LIFECYCLE_EVENTS: Set<string>;
@@ -6,15 +6,15 @@ const COMPILER_ENTRYPOINT_REACTIVITY = 'reactive';
6
6
  const COMPILER_NAMESPACE = uid('template');
7
7
  var COMPILER_TYPES;
8
8
  (function (COMPILER_TYPES) {
9
- COMPILER_TYPES[COMPILER_TYPES["ArraySlot"] = 0] = "ArraySlot";
10
- COMPILER_TYPES[COMPILER_TYPES["AttributeSlot"] = 1] = "AttributeSlot";
11
- COMPILER_TYPES[COMPILER_TYPES["AttributeSpreadSlot"] = 2] = "AttributeSpreadSlot";
12
- COMPILER_TYPES[COMPILER_TYPES["DocumentFragment"] = 3] = "DocumentFragment";
13
- COMPILER_TYPES[COMPILER_TYPES["Effect"] = 4] = "Effect";
14
- COMPILER_TYPES[COMPILER_TYPES["NodeSlot"] = 5] = "NodeSlot";
15
- COMPILER_TYPES[COMPILER_TYPES["Primitive"] = 6] = "Primitive";
16
- COMPILER_TYPES[COMPILER_TYPES["Static"] = 7] = "Static";
17
- COMPILER_TYPES[COMPILER_TYPES["Unknown"] = 8] = "Unknown";
9
+ COMPILER_TYPES["ArraySlot"] = "array-slot";
10
+ COMPILER_TYPES["Attributes"] = "attributes";
11
+ COMPILER_TYPES["Attribute"] = "attribute";
12
+ COMPILER_TYPES["DocumentFragment"] = "document-fragment";
13
+ COMPILER_TYPES["Effect"] = "effect";
14
+ COMPILER_TYPES["Node"] = "node";
15
+ COMPILER_TYPES["Primitive"] = "primitive";
16
+ COMPILER_TYPES["Static"] = "static";
17
+ COMPILER_TYPES["Unknown"] = "unknown";
18
18
  })(COMPILER_TYPES || (COMPILER_TYPES = {}));
19
19
  ;
20
20
  const DIRECT_ATTACH_EVENTS = new Set([
@@ -1,11 +1,10 @@
1
1
  import { Element } from '../types.js';
2
- declare const _default: {
3
- delegate: (element: Element, event: string, listener: Function) => void;
4
- direct: (element: Element, event: string, listener: Function) => void;
5
- onconnect: (element: globalThis.Element, listener: Function) => void;
6
- ondisconnect: (element: Element, listener: Function) => void;
7
- onrender: (element: Element, listener: Function) => void;
8
- onresize: (element: Element, listener: Function) => void;
9
- ontick: (element: globalThis.Element, listener: Function) => void;
10
- };
11
- export default _default;
2
+ import onconnect from './onconnect.js';
3
+ import onresize from './onresize.js';
4
+ import ontick from './ontick.js';
5
+ declare const delegate: (element: Element, event: string, listener: Function) => void;
6
+ declare const on: (element: Element, event: string, listener: Function) => void;
7
+ declare const ondisconnect: (element: Element, listener: Function) => void;
8
+ declare const onrender: (element: Element, listener: Function) => void;
9
+ declare const runtime: (element: Element, event: `on${string}`, listener: Function) => void;
10
+ export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
@@ -4,6 +4,7 @@ import { ondisconnect as disconnect } from '../slot/cleanup.js';
4
4
  import onconnect from './onconnect.js';
5
5
  import onresize from './onresize.js';
6
6
  import ontick from './ontick.js';
7
+ import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS } from '../constants.js';
7
8
  let controllers = new Map(), host = window.document, keys = {}, passive = new Set([
8
9
  'animationend', 'animationiteration', 'animationstart',
9
10
  'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'mousewheel',
@@ -61,7 +62,7 @@ function register(element, event) {
61
62
  const delegate = (element, event, listener) => {
62
63
  element[keys[event] || register(element, event)] = listener;
63
64
  };
64
- const direct = (element, event, listener) => {
65
+ const on = (element, event, listener) => {
65
66
  let handler = (e) => listener.call(element, e);
66
67
  element.addEventListener(event, handler, {
67
68
  passive: passive.has(event)
@@ -76,4 +77,19 @@ const ondisconnect = (element, listener) => {
76
77
  const onrender = (element, listener) => {
77
78
  root(() => listener(element));
78
79
  };
79
- export default { delegate, direct, onconnect, ondisconnect, onrender, onresize, ontick };
80
+ const lifecycle = { onconnect, ondisconnect, onrender, onresize, ontick };
81
+ const runtime = (element, event, listener) => {
82
+ let key = event.toLowerCase();
83
+ if (LIFECYCLE_EVENTS.has(key)) {
84
+ lifecycle[key](element, listener);
85
+ return;
86
+ }
87
+ let e = event.slice(2).toLowerCase();
88
+ if (DIRECT_ATTACH_EVENTS.has(key)) {
89
+ on(element, e, listener);
90
+ }
91
+ else {
92
+ delegate(element, e, listener);
93
+ }
94
+ };
95
+ export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
package/build/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import './runtime.js';
2
2
  export { default as html } from './html.js';
3
3
  export { default as render } from './render.js';
4
4
  export { default as svg } from './svg.js';
5
- export { default as attributes } from './attributes.js';
6
- export { default as event } from './event/index.js';
5
+ export * from './attributes.js';
6
+ export * from './event/index.js';
7
7
  export { default as slot } from './slot/index.js';
8
8
  export { ArraySlot } from './slot/array.js';
9
9
  export { EffectSlot } from './slot/effect.js';
package/build/index.js CHANGED
@@ -2,8 +2,8 @@ import './runtime.js';
2
2
  export { default as html } from './html.js';
3
3
  export { default as render } from './render.js';
4
4
  export { default as svg } from './svg.js';
5
- export { default as attributes } from './attributes.js';
6
- export { default as event } from './event/index.js';
5
+ export * from './attributes.js';
6
+ export * from './event/index.js';
7
7
  export { default as slot } from './slot/index.js';
8
8
  export { ArraySlot } from './slot/array.js';
9
9
  export { EffectSlot } from './slot/effect.js';
@@ -4,9 +4,9 @@ type CodegenResult = {
4
4
  changed: boolean;
5
5
  code: string;
6
6
  };
7
- declare const addArraySlotImport: (code: string) => string;
7
+ declare const addImport: (code: string) => string;
8
8
  declare const generateCode: (templates: TemplateInfo[], originalCode: string, sourceFile: ts.SourceFile, checker?: ts.TypeChecker) => CodegenResult;
9
9
  declare const generateReactiveInlining: (calls: ReactiveCallInfo[], code: string, sourceFile: ts.SourceFile) => string;
10
10
  declare const needsArraySlotImport: (sourceFile: ts.SourceFile) => boolean;
11
- export { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport };
11
+ export { addImport, generateCode, generateReactiveInlining, needsArraySlotImport };
12
12
  export type { CodegenResult };
@@ -1,5 +1,5 @@
1
1
  import { ts } from '@esportsplus/typescript';
2
- import { code as c, uid } from '@esportsplus/typescript/transformer';
2
+ import { ast, code as c, uid } from '@esportsplus/typescript/transformer';
3
3
  import { analyzeExpression, generateAttributeBinding, generateSpreadBindings } from './type-analyzer.js';
4
4
  import { COMPILER_ENTRYPOINT, COMPILER_NAMESPACE, COMPILER_TYPES, PACKAGE } from '../constants.js';
5
5
  import parser from './parser.js';
@@ -88,11 +88,11 @@ function generateTemplateCode(ctx, { html, slots }, exprTexts, exprNodes, isArro
88
88
  let elementVar = slots[i].path.length === 0
89
89
  ? root
90
90
  : (nodes.get(slots[i].path.join('.')) || root), slot = slots[i];
91
- if (slot.type === COMPILER_TYPES.AttributeSlot) {
91
+ if (slot.type === COMPILER_TYPES.Attribute) {
92
92
  let names = slot.attributes.names;
93
93
  for (let j = 0, m = names.length; j < m; j++) {
94
94
  let name = names[j];
95
- if (name === 'spread') {
95
+ if (name === COMPILER_TYPES.Attributes) {
96
96
  let bindings = generateSpreadBindings(exprNodes[index], exprTexts[index] || 'undefined', elementVar, ctx.checker, COMPILER_NAMESPACE);
97
97
  for (let k = 0, o = bindings.length; k < o; k++) {
98
98
  code.push(bindings[k]);
@@ -140,42 +140,21 @@ function hasArraySlotImport(sourceFile) {
140
140
  }
141
141
  return false;
142
142
  }
143
- function hasMatch(node, predicate) {
144
- if (predicate(node)) {
145
- return true;
146
- }
147
- let found = false;
148
- ts.forEachChild(node, child => {
149
- if (!found) {
150
- found = hasMatch(child, predicate);
151
- }
152
- });
153
- return found;
154
- }
155
143
  function isNestedHtmlTemplate(expr) {
156
144
  return ts.isTaggedTemplateExpression(expr) && ts.isIdentifier(expr.tag) && expr.tag.text === COMPILER_ENTRYPOINT;
157
145
  }
158
- function isNestedTemplate(template, exprRanges) {
159
- for (let i = 0, n = exprRanges.length; i < n; i++) {
160
- let range = exprRanges[i];
161
- if (template.start >= range.start && template.end <= range.end) {
162
- return true;
163
- }
164
- }
165
- return false;
166
- }
167
146
  function rewriteExpression(ctx, expr) {
168
147
  if (isNestedHtmlTemplate(expr)) {
169
148
  return generateNestedTemplateCode(ctx, expr);
170
149
  }
171
- if (!hasMatch(expr, n => isNestedHtmlTemplate(n))) {
150
+ if (!ast.hasMatch(expr, n => isNestedHtmlTemplate(n))) {
172
151
  return ctx.printer.printNode(ts.EmitHint.Expression, expr, ctx.sourceFile);
173
152
  }
174
153
  let replacements = [];
175
154
  collectNestedTemplateReplacements(ctx, expr, expr.getStart(), replacements);
176
155
  return c.replaceReverse(expr.getText(ctx.sourceFile), replacements);
177
156
  }
178
- const addArraySlotImport = (code) => {
157
+ const addImport = (code) => {
179
158
  return `import * as ${COMPILER_NAMESPACE} from '${PACKAGE}';\n` + code;
180
159
  };
181
160
  const generateCode = (templates, originalCode, sourceFile, checker) => {
@@ -189,7 +168,7 @@ const generateCode = (templates, originalCode, sourceFile, checker) => {
189
168
  ranges.push({ end: exprs[j].end, start: exprs[j].getStart() });
190
169
  }
191
170
  }
192
- let rootTemplates = templates.filter(t => !isNestedTemplate(t, ranges));
171
+ let rootTemplates = templates.filter(t => !ast.inRange(ranges, t.start, t.end));
193
172
  if (rootTemplates.length === 0) {
194
173
  return { changed: false, code: originalCode };
195
174
  }
@@ -229,7 +208,7 @@ const generateCode = (templates, originalCode, sourceFile, checker) => {
229
208
  for (let [id, html] of ctx.hoistedFactories) {
230
209
  factories.push(`const ${id} = ${COMPILER_NAMESPACE}.template(\`${html}\`);`);
231
210
  }
232
- code = `import * as ${COMPILER_NAMESPACE} from '${PACKAGE}';\n\n` + factories.join('\n') + '\n\n' + code;
211
+ code = addImport(factories.join('\n') + code);
233
212
  }
234
213
  return { changed, code };
235
214
  };
@@ -252,8 +231,8 @@ const generateReactiveInlining = (calls, code, sourceFile) => {
252
231
  return c.replaceReverse(code, replacements);
253
232
  };
254
233
  const needsArraySlotImport = (sourceFile) => {
255
- return hasMatch(sourceFile, n => ts.isNewExpression(n) &&
234
+ return ast.hasMatch(sourceFile, n => ts.isNewExpression(n) &&
256
235
  ts.isPropertyAccessExpression(n.expression) &&
257
236
  n.expression.name.text === 'ArraySlot') && !hasArraySlotImport(sourceFile);
258
237
  };
259
- export { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport };
238
+ export { addImport, generateCode, generateReactiveInlining, needsArraySlotImport };
@@ -1,5 +1,5 @@
1
1
  import { code as c } from '@esportsplus/typescript/transformer';
2
- import { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport } from './codegen.js';
2
+ import { addImport, generateCode, generateReactiveInlining, needsArraySlotImport } from './codegen.js';
3
3
  import { COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REACTIVITY } from '../constants.js';
4
4
  import { findHtmlTemplates, findReactiveCalls } from './ts-parser.js';
5
5
  import { ts } from '@esportsplus/typescript';
@@ -36,7 +36,7 @@ const transform = (sourceFile, program) => {
36
36
  }
37
37
  }
38
38
  if (needsImport && !codegenChanged) {
39
- result = addArraySlotImport(result);
39
+ result = addImport(result);
40
40
  }
41
41
  if (changed) {
42
42
  sourceFile = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
@@ -5,14 +5,14 @@ declare const _default: {
5
5
  html: string;
6
6
  slots: ({
7
7
  path: NodePath;
8
- type: COMPILER_TYPES.NodeSlot;
8
+ type: COMPILER_TYPES.Node;
9
9
  } | {
10
10
  attributes: {
11
11
  names: string[];
12
12
  statics: Record<string, string>;
13
13
  };
14
14
  path: NodePath;
15
- type: COMPILER_TYPES.AttributeSlot;
15
+ type: COMPILER_TYPES.Attribute;
16
16
  })[] | null;
17
17
  };
18
18
  };
@@ -53,7 +53,7 @@ const parse = (literals) => {
53
53
  if (n === 0) {
54
54
  return { html, slots: null };
55
55
  }
56
- let attributes = {}, buffer = '', events = false, index = 0, level = 0, levels = [{ children: 0, elements: 0, path: [] }], parsed = html.split(SLOT_MARKER), slot = 0, slots = [];
56
+ let attributes = {}, buffer = '', index = 0, level = 0, levels = [{ children: 0, elements: 0, path: [] }], parsed = html.split(SLOT_MARKER), slot = 0, slots = [];
57
57
  {
58
58
  let attribute = '', buffer = '', char = '', quote = '';
59
59
  for (let match of html.matchAll(REGEX_SLOT_ATTRIBUTES)) {
@@ -102,12 +102,9 @@ const parse = (literals) => {
102
102
  }
103
103
  }
104
104
  else {
105
- names.push('spread');
105
+ names.push(COMPILER_TYPES.Attributes);
106
106
  }
107
107
  }
108
- else if (buffer === 'on') {
109
- events = true;
110
- }
111
108
  }
112
109
  }
113
110
  }
@@ -127,7 +124,7 @@ const parse = (literals) => {
127
124
  if (!attrs) {
128
125
  throw new Error(`${PACKAGE}: attribute metadata could not be found for '${attr}'`);
129
126
  }
130
- slots.push({ attributes: attrs, path, type: COMPILER_TYPES.AttributeSlot });
127
+ slots.push({ attributes: attrs, path, type: COMPILER_TYPES.Attribute });
131
128
  for (let i = 0, n = attrs.names.length; i < n; i++) {
132
129
  buffer += parsed[slot++];
133
130
  }
@@ -139,7 +136,10 @@ const parse = (literals) => {
139
136
  }
140
137
  else if (type === NODE_SLOT) {
141
138
  buffer += parsed[slot++] + SLOT_HTML;
142
- slots.push({ path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'), type: COMPILER_TYPES.NodeSlot });
139
+ slots.push({
140
+ path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'),
141
+ type: COMPILER_TYPES.Node
142
+ });
143
143
  }
144
144
  if (n === slot) {
145
145
  buffer += parsed[slot];
@@ -154,10 +154,9 @@ const parse = (literals) => {
154
154
  index = (match.index || 0) + match[0].length;
155
155
  }
156
156
  }
157
- if (events) {
158
- buffer = buffer.replace(REGEX_EVENTS, '');
159
- }
160
- buffer = buffer.replace(REGEX_EMPTY_ATTRIBUTES, '');
157
+ buffer = buffer
158
+ .replace(REGEX_EVENTS, '')
159
+ .replace(REGEX_EMPTY_ATTRIBUTES, '');
161
160
  return {
162
161
  html: buffer,
163
162
  slots: slots.length ? slots : null
@@ -123,23 +123,23 @@ const generateAttributeBinding = (elementVar, name, expr, staticValue, ns) => {
123
123
  if (name.startsWith('on') && name.length > 2) {
124
124
  let event = name.slice(2).toLowerCase(), key = name.toLowerCase();
125
125
  if (LIFECYCLE_EVENTS.has(key)) {
126
- return `${ns}.event.${key}(${elementVar}, ${expr});`;
126
+ return `${ns}.${key}(${elementVar}, ${expr});`;
127
127
  }
128
128
  if (DIRECT_ATTACH_EVENTS.has(key)) {
129
- return `${ns}.event.direct(${elementVar}, '${event}', ${expr});`;
129
+ return `${ns}.on(${elementVar}, '${event}', ${expr});`;
130
130
  }
131
- return `${ns}.event.delegate(${elementVar}, '${event}', ${expr});`;
131
+ return `${ns}.delegate(${elementVar}, '${event}', ${expr});`;
132
132
  }
133
133
  if (name === 'class') {
134
- return `${ns}.attributes.setClass(${elementVar}, '${staticValue}', ${expr});`;
134
+ return `${ns}.setClass(${elementVar}, '${staticValue}', ${expr});`;
135
135
  }
136
- if (name === 'spread') {
137
- return `${ns}.attributes.spread(${elementVar}, ${expr});`;
136
+ if (name === COMPILER_TYPES.Attributes) {
137
+ return `${ns}.setProperties(${elementVar}, ${expr});`;
138
138
  }
139
139
  if (name === 'style') {
140
- return `${ns}.attributes.setStyle(${elementVar}, '${staticValue}', ${expr});`;
140
+ return `${ns}.setStyle(${elementVar}, '${staticValue}', ${expr});`;
141
141
  }
142
- return `${ns}.attributes.setProperty(${elementVar}, '${name}', ${expr});`;
142
+ return `${ns}.setProperty(${elementVar}, '${name}', ${expr});`;
143
143
  };
144
144
  const generateSpreadBindings = (expr, exprCode, elementVar, checker, ns) => {
145
145
  while (ts.isParenthesizedExpression(expr)) {
@@ -147,7 +147,7 @@ const generateSpreadBindings = (expr, exprCode, elementVar, checker, ns) => {
147
147
  }
148
148
  let analysis = analyzeSpread(expr, checker);
149
149
  if (!analysis.canUnpack) {
150
- return [`${ns}.attributes.spread(${elementVar}, ${exprCode});`];
150
+ return [`${ns}.setProperties(${elementVar}, ${exprCode});`];
151
151
  }
152
152
  let lines = [];
153
153
  if (ts.isObjectLiteralExpression(expr)) {
package/build/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ArraySlot } from './slot/array.js';
2
- import attributes from './attributes.js';
2
+ import { setProperties } from './attributes.js';
3
3
  import slot from './slot/index.js';
4
4
  type Attribute = Effect<Primitive | Primitive[]> | ((...args: any[]) => void) | Primitive;
5
5
  type Attributes<T extends HTMLElement = Element> = {
@@ -27,7 +27,7 @@ type Template = {
27
27
  html: string;
28
28
  literals: TemplateStringsArray;
29
29
  slots: {
30
- fn: typeof attributes.spread | typeof slot;
30
+ fn: typeof setProperties | typeof slot;
31
31
  name: string | null;
32
32
  path: (() => ChildNode | null)[];
33
33
  }[] | null;
package/package.json CHANGED
@@ -2,12 +2,12 @@
2
2
  "author": "ICJR",
3
3
  "dependencies": {
4
4
  "@esportsplus/queue": "^0.2.0",
5
- "@esportsplus/reactivity": "^0.25.12",
5
+ "@esportsplus/reactivity": "^0.25.14",
6
6
  "@esportsplus/utilities": "^0.27.2",
7
7
  "serve": "^14.2.5"
8
8
  },
9
9
  "devDependencies": {
10
- "@esportsplus/typescript": "^0.18.0",
10
+ "@esportsplus/typescript": "^0.20.0",
11
11
  "@types/node": "^25.0.3",
12
12
  "vite": "^7.3.0",
13
13
  "vite-tsconfig-paths": "^6.0.3"
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "type": "module",
42
42
  "types": "./build/index.d.ts",
43
- "version": "0.32.2",
43
+ "version": "0.32.4",
44
44
  "scripts": {
45
45
  "build": "tsc",
46
46
  "build:test": "vite build --config test/vite.config.ts",
package/src/attributes.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { effect } from '@esportsplus/reactivity';
2
2
  import { isArray, isObject } from '@esportsplus/utilities';
3
- import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS, STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants';
3
+ import { STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants';
4
4
  import { Attributes, Element } from './types';
5
5
  import { raf } from './utilities';
6
6
  import q from '@esportsplus/queue';
7
- import event from './event';
7
+ import { runtime } from './event';
8
8
 
9
9
 
10
10
  type Context = {
@@ -221,45 +221,10 @@ function schedule(ctx: Context | null, element: Element, name: string, state: St
221
221
  raf(task);
222
222
  }
223
223
 
224
- function task() {
225
- let context,
226
- n = queue.length;
227
-
228
- while ((context = queue.next()) && n--) {
229
- let { element, updates } = context;
230
-
231
- for (let name in updates) {
232
- apply(element, name, updates[name]);
233
- }
234
-
235
- context.updates = {};
236
- context.updating = false;
237
- }
238
-
239
- if (queue.length) {
240
- raf(task);
241
- }
242
- else {
243
- scheduled = false;
244
- }
245
- }
246
-
247
-
248
- const set = (element: Element, name: string, value: unknown) => {
224
+ function set(element: Element, name: string, value: unknown) {
249
225
  if (typeof value === 'function') {
250
226
  if (name[0] === 'o' && name[1] === 'n') {
251
- let e = name.slice(2).toLowerCase(),
252
- key = name.toLowerCase();
253
-
254
- if (LIFECYCLE_EVENTS.has(key)) {
255
- (event as any)[key](element, value as Function);
256
- }
257
- else if (DIRECT_ATTACH_EVENTS.has(key)) {
258
- event.direct(element, e, value as Function);
259
- }
260
- else {
261
- event.delegate(element, e, value as Function);
262
- }
227
+ runtime(element, name as `on${string}`, value as Function);
263
228
  }
264
229
  else {
265
230
  reactive(element, name, STATE_HYDRATING, value);
@@ -283,7 +248,31 @@ const set = (element: Element, name: string, value: unknown) => {
283
248
  }
284
249
 
285
250
  (name === 'class' || name === 'style' ? list : property)(null, element, null, name, STATE_HYDRATING, value);
286
- };
251
+ }
252
+
253
+ function task() {
254
+ let context,
255
+ n = queue.length;
256
+
257
+ while ((context = queue.next()) && n--) {
258
+ let { element, updates } = context;
259
+
260
+ for (let name in updates) {
261
+ apply(element, name, updates[name]);
262
+ }
263
+
264
+ context.updates = {};
265
+ context.updating = false;
266
+ }
267
+
268
+ if (queue.length) {
269
+ raf(task);
270
+ }
271
+ else {
272
+ scheduled = false;
273
+ }
274
+ }
275
+
287
276
 
288
277
  const setClass = (element: Element, classlist: false | string | undefined, value: unknown) => {
289
278
  let ctx = context(element),
@@ -309,22 +298,7 @@ const setProperty = (element: Element, name: string, value: unknown) => {
309
298
  }
310
299
  };
311
300
 
312
- const setStyle = (element: Element, styles: false | string | undefined, value: unknown) => {
313
- let ctx = context(element),
314
- store = ctx.store ??= {};
315
-
316
- store['style.static'] = styles || '';
317
- store['style'] ??= new Set<string>();
318
-
319
- if (typeof value === 'function') {
320
- reactive(element, 'style', STATE_HYDRATING, value);
321
- }
322
- else {
323
- list(ctx, element, null, 'style', STATE_HYDRATING, value);
324
- }
325
- };
326
-
327
- const spread = function (element: Element, value: Attributes | Attributes[]) {
301
+ const setProperties = function (element: Element, value: Attributes | Attributes[]) {
328
302
  if (isObject(value)) {
329
303
  for (let name in value) {
330
304
  let v = value[name];
@@ -338,11 +312,25 @@ const spread = function (element: Element, value: Attributes | Attributes[]) {
338
312
  }
339
313
  else if (isArray(value)) {
340
314
  for (let i = 0, n = value.length; i < n; i++) {
341
- spread(element, value[i]);
315
+ setProperties(element, value[i]);
342
316
  }
343
317
  }
344
318
  };
345
319
 
320
+ const setStyle = (element: Element, styles: false | string | undefined, value: unknown) => {
321
+ let ctx = context(element),
322
+ store = ctx.store ??= {};
323
+
324
+ store['style.static'] = styles || '';
325
+ store['style'] ??= new Set<string>();
326
+
327
+ if (typeof value === 'function') {
328
+ reactive(element, 'style', STATE_HYDRATING, value);
329
+ }
330
+ else {
331
+ list(ctx, element, null, 'style', STATE_HYDRATING, value);
332
+ }
333
+ };
334
+
346
335
 
347
- export default { set, setClass, setProperty, setStyle, spread };
348
- export { set, setClass, setProperty, setStyle, spread };
336
+ export { setClass, setProperty, setProperties, setStyle };
package/src/constants.ts CHANGED
@@ -13,15 +13,15 @@ const COMPILER_ENTRYPOINT_REACTIVITY = 'reactive';
13
13
  const COMPILER_NAMESPACE = uid('template');
14
14
 
15
15
  const enum COMPILER_TYPES {
16
- ArraySlot,
17
- AttributeSlot,
18
- AttributeSpreadSlot,
19
- DocumentFragment,
20
- Effect,
21
- NodeSlot,
22
- Primitive,
23
- Static,
24
- Unknown
16
+ ArraySlot = 'array-slot',
17
+ Attributes = 'attributes',
18
+ Attribute = 'attribute',
19
+ DocumentFragment = 'document-fragment',
20
+ Effect = 'effect',
21
+ Node = 'node',
22
+ Primitive = 'primitive',
23
+ Static = 'static',
24
+ Unknown = 'unknown'
25
25
  };
26
26
 
27
27
  const DIRECT_ATTACH_EVENTS = new Set<string>([
@@ -5,6 +5,7 @@ import { ondisconnect as disconnect } from '~/slot/cleanup';
5
5
  import onconnect from './onconnect';
6
6
  import onresize from './onresize';
7
7
  import ontick from './ontick';
8
+ import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS } from '~/constants';
8
9
 
9
10
 
10
11
  let controllers = new Map<string, (AbortController & { listeners: number }) | null>(),
@@ -92,7 +93,7 @@ const delegate = (element: Element, event: string, listener: Function): void =>
92
93
  };
93
94
 
94
95
  // DIRECT_ATTACH_EVENTS in ./constants.ts tells compiler to use this function
95
- const direct = (element: Element, event: string, listener: Function): void => {
96
+ const on = (element: Element, event: string, listener: Function): void => {
96
97
  let handler = (e: Event) => listener.call(element, e);
97
98
 
98
99
  element.addEventListener(event, handler, {
@@ -112,5 +113,25 @@ const onrender = (element: Element, listener: Function) => {
112
113
  root(() => listener(element));
113
114
  };
114
115
 
116
+ const lifecycle = { onconnect, ondisconnect, onrender, onresize, ontick };
115
117
 
116
- export default { delegate, direct, onconnect, ondisconnect, onrender, onresize, ontick };
118
+ const runtime = (element: Element, event: `on${string}`, listener: Function): void => {
119
+ let key = event.toLowerCase();
120
+
121
+ if (LIFECYCLE_EVENTS.has(key)) {
122
+ lifecycle[key as keyof typeof lifecycle](element, listener);
123
+ return;
124
+ }
125
+
126
+ let e = event.slice(2).toLowerCase();
127
+
128
+ if (DIRECT_ATTACH_EVENTS.has(key)) {
129
+ on(element, e, listener);
130
+ }
131
+ else {
132
+ delegate(element, e, listener);
133
+ }
134
+ };
135
+
136
+
137
+ export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
package/src/index.ts CHANGED
@@ -4,8 +4,8 @@ export { default as render } from './render';
4
4
  export { default as svg } from './svg';
5
5
 
6
6
  // Must be exported for compilation even if not used directly
7
- export { default as attributes } from './attributes';
8
- export { default as event } from './event';
7
+ export * from './attributes';
8
+ export * from './event';
9
9
  export { default as slot } from './slot';
10
10
  export { ArraySlot } from './slot/array';
11
11
  export { EffectSlot } from './slot/effect';
@@ -1,5 +1,5 @@
1
1
  import { ts } from '@esportsplus/typescript';
2
- import { code as c, uid, type Replacement } from '@esportsplus/typescript/transformer';
2
+ import { ast, code as c, uid, type Replacement } from '@esportsplus/typescript/transformer';
3
3
  import type { ReactiveCallInfo, TemplateInfo } from './ts-parser';
4
4
  import { analyzeExpression, generateAttributeBinding, generateSpreadBindings } from './type-analyzer';
5
5
  import {
@@ -9,13 +9,13 @@ import {
9
9
  import parser from './parser';
10
10
 
11
11
 
12
- type AttributeSlot = {
12
+ type Attribute = {
13
13
  attributes: {
14
14
  names: string[];
15
15
  statics: Record<string, string>;
16
16
  };
17
17
  path: string[];
18
- type: COMPILER_TYPES.AttributeSlot;
18
+ type: COMPILER_TYPES.Attribute;
19
19
  };
20
20
 
21
21
  type CodegenContext = {
@@ -31,14 +31,14 @@ type CodegenResult = {
31
31
  code: string;
32
32
  };
33
33
 
34
- type NodeSlot = {
34
+ type Node = {
35
35
  path: string[];
36
- type: COMPILER_TYPES.NodeSlot;
36
+ type: COMPILER_TYPES.Node;
37
37
  };
38
38
 
39
39
  type ParseResult = {
40
40
  html: string;
41
- slots: (AttributeSlot | NodeSlot)[] | null;
41
+ slots: (Attribute | Node)[] | null;
42
42
  };
43
43
 
44
44
 
@@ -189,13 +189,13 @@ function generateTemplateCode(
189
189
  : (nodes.get(slots[i].path.join('.')) || root),
190
190
  slot = slots[i];
191
191
 
192
- if (slot.type === COMPILER_TYPES.AttributeSlot) {
192
+ if (slot.type === COMPILER_TYPES.Attribute) {
193
193
  let names = slot.attributes.names;
194
194
 
195
195
  for (let j = 0, m = names.length; j < m; j++) {
196
196
  let name = names[j];
197
197
 
198
- if (name === 'spread') {
198
+ if (name === COMPILER_TYPES.Attributes) {
199
199
  let bindings = generateSpreadBindings(
200
200
  exprNodes[index],
201
201
  exprTexts[index] || 'undefined',
@@ -273,44 +273,16 @@ function hasArraySlotImport(sourceFile: ts.SourceFile): boolean {
273
273
  return false;
274
274
  }
275
275
 
276
- function hasMatch(node: ts.Node, predicate: (n: ts.Node) => boolean): boolean {
277
- if (predicate(node)) {
278
- return true;
279
- }
280
-
281
- let found = false;
282
-
283
- ts.forEachChild(node, child => {
284
- if (!found) {
285
- found = hasMatch(child, predicate);
286
- }
287
- });
288
-
289
- return found;
290
- }
291
-
292
276
  function isNestedHtmlTemplate(expr: ts.Expression): expr is ts.TaggedTemplateExpression {
293
277
  return ts.isTaggedTemplateExpression(expr) && ts.isIdentifier(expr.tag) && expr.tag.text === COMPILER_ENTRYPOINT;
294
278
  }
295
279
 
296
- function isNestedTemplate(template: TemplateInfo, exprRanges: { end: number; start: number }[]): boolean {
297
- for (let i = 0, n = exprRanges.length; i < n; i++) {
298
- let range = exprRanges[i];
299
-
300
- if (template.start >= range.start && template.end <= range.end) {
301
- return true;
302
- }
303
- }
304
-
305
- return false;
306
- }
307
-
308
280
  function rewriteExpression(ctx: CodegenContext, expr: ts.Expression): string {
309
281
  if (isNestedHtmlTemplate(expr)) {
310
282
  return generateNestedTemplateCode(ctx, expr);
311
283
  }
312
284
 
313
- if (!hasMatch(expr, n => isNestedHtmlTemplate(n as ts.Expression))) {
285
+ if (!ast.hasMatch(expr, n => isNestedHtmlTemplate(n as ts.Expression))) {
314
286
  return ctx.printer.printNode(ts.EmitHint.Expression, expr, ctx.sourceFile);
315
287
  }
316
288
 
@@ -322,7 +294,7 @@ function rewriteExpression(ctx: CodegenContext, expr: ts.Expression): string {
322
294
  }
323
295
 
324
296
 
325
- const addArraySlotImport = (code: string): string => {
297
+ const addImport = (code: string): string => {
326
298
  return `import * as ${COMPILER_NAMESPACE} from '${PACKAGE}';\n` + code;
327
299
  };
328
300
 
@@ -342,7 +314,7 @@ const generateCode = (templates: TemplateInfo[], originalCode: string, sourceFil
342
314
  }
343
315
  }
344
316
 
345
- let rootTemplates = templates.filter(t => !isNestedTemplate(t, ranges));
317
+ let rootTemplates = templates.filter(t => !ast.inRange(ranges, t.start, t.end));
346
318
 
347
319
  if (rootTemplates.length === 0) {
348
320
  return { changed: false, code: originalCode };
@@ -406,7 +378,7 @@ const generateCode = (templates: TemplateInfo[], originalCode: string, sourceFil
406
378
  factories.push(`const ${id} = ${COMPILER_NAMESPACE}.template(\`${html}\`);`);
407
379
  }
408
380
 
409
- code = `import * as ${COMPILER_NAMESPACE} from '${PACKAGE}';\n\n` + factories.join('\n') + '\n\n' + code;
381
+ code = addImport(factories.join('\n') + code);
410
382
  }
411
383
 
412
384
  return { changed, code };
@@ -436,7 +408,7 @@ const generateReactiveInlining = (calls: ReactiveCallInfo[], code: string, sourc
436
408
  };
437
409
 
438
410
  const needsArraySlotImport = (sourceFile: ts.SourceFile): boolean => {
439
- return hasMatch(sourceFile, n =>
411
+ return ast.hasMatch(sourceFile, n =>
440
412
  ts.isNewExpression(n) &&
441
413
  ts.isPropertyAccessExpression(n.expression) &&
442
414
  n.expression.name.text === 'ArraySlot'
@@ -444,5 +416,5 @@ const needsArraySlotImport = (sourceFile: ts.SourceFile): boolean => {
444
416
  };
445
417
 
446
418
 
447
- export { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport };
419
+ export { addImport, generateCode, generateReactiveInlining, needsArraySlotImport };
448
420
  export type { CodegenResult };
@@ -1,5 +1,5 @@
1
1
  import { code as c } from '@esportsplus/typescript/transformer';
2
- import { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport } from './codegen';
2
+ import { addImport, generateCode, generateReactiveInlining, needsArraySlotImport } from './codegen';
3
3
  import { COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REACTIVITY } from '../constants';
4
4
  import { findHtmlTemplates, findReactiveCalls } from './ts-parser';
5
5
  import { ts } from '@esportsplus/typescript';
@@ -64,7 +64,7 @@ const transform = (sourceFile: ts.SourceFile, program: ts.Program): TransformRes
64
64
  }
65
65
 
66
66
  if (needsImport && !codegenChanged) {
67
- result = addArraySlotImport(result);
67
+ result = addImport(result);
68
68
  }
69
69
 
70
70
  if (changed) {
@@ -1,8 +1,4 @@
1
- import {
2
- COMPILER_TYPES,
3
- PACKAGE,
4
- SLOT_HTML
5
- } from '../constants';
1
+ import { COMPILER_TYPES, PACKAGE, SLOT_HTML } from '../constants';
6
2
 
7
3
 
8
4
  type NodePath = ('firstChild' | 'firstElementChild' | 'nextElementSibling' | 'nextSibling')[];
@@ -88,15 +84,14 @@ const parse = (literals: string[]) => {
88
84
 
89
85
  let attributes: Record<string, { names: string[], statics: Record<string, string> }> = {},
90
86
  buffer = '',
91
- events = false,
92
87
  index = 0,
93
88
  level = 0,
94
89
  levels = [{ children: 0, elements: 0, path: [] as NodePath }],
95
90
  parsed = html.split(SLOT_MARKER),
96
91
  slot = 0,
97
92
  slots: (
98
- { path: NodePath; type: COMPILER_TYPES.NodeSlot } |
99
- { attributes: typeof attributes[string]; path: NodePath; type: COMPILER_TYPES.AttributeSlot }
93
+ { path: NodePath; type: COMPILER_TYPES.Node } |
94
+ { attributes: typeof attributes[string]; path: NodePath; type: COMPILER_TYPES.Attribute }
100
95
  )[] = [];
101
96
 
102
97
  {
@@ -159,12 +154,9 @@ const parse = (literals: string[]) => {
159
154
  }
160
155
  }
161
156
  else {
162
- names.push('spread');
157
+ names.push(COMPILER_TYPES.Attributes);
163
158
  }
164
159
  }
165
- else if (buffer === 'on') {
166
- events = true;
167
- }
168
160
  }
169
161
  }
170
162
  }
@@ -192,7 +184,7 @@ const parse = (literals: string[]) => {
192
184
  throw new Error(`${PACKAGE}: attribute metadata could not be found for '${attr}'`);
193
185
  }
194
186
 
195
- slots.push({ attributes: attrs, path, type: COMPILER_TYPES.AttributeSlot });
187
+ slots.push({ attributes: attrs, path, type: COMPILER_TYPES.Attribute });
196
188
 
197
189
  for (let i = 0, n = attrs.names.length; i < n; i++) {
198
190
  buffer += parsed[slot++];
@@ -207,7 +199,10 @@ const parse = (literals: string[]) => {
207
199
  }
208
200
  else if (type === NODE_SLOT) {
209
201
  buffer += parsed[slot++] + SLOT_HTML;
210
- slots.push({ path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'), type: COMPILER_TYPES.NodeSlot });
202
+ slots.push({
203
+ path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'),
204
+ type: COMPILER_TYPES.Node
205
+ });
211
206
  }
212
207
 
213
208
  if (n === slot) {
@@ -226,11 +221,9 @@ const parse = (literals: string[]) => {
226
221
  }
227
222
  }
228
223
 
229
- if (events) {
230
- buffer = buffer.replace(REGEX_EVENTS, '');
231
- }
232
-
233
- buffer = buffer.replace(REGEX_EMPTY_ATTRIBUTES, '');
224
+ buffer = buffer
225
+ .replace(REGEX_EVENTS, '')
226
+ .replace(REGEX_EMPTY_ATTRIBUTES, '');
234
227
 
235
228
  return {
236
229
  html: buffer,
@@ -178,29 +178,29 @@ const generateAttributeBinding = (elementVar: string, name: string, expr: string
178
178
  key = name.toLowerCase();
179
179
 
180
180
  if (LIFECYCLE_EVENTS.has(key)) {
181
- return `${ns}.event.${key}(${elementVar}, ${expr});`;
181
+ return `${ns}.${key}(${elementVar}, ${expr});`;
182
182
  }
183
183
 
184
184
  if (DIRECT_ATTACH_EVENTS.has(key)) {
185
- return `${ns}.event.direct(${elementVar}, '${event}', ${expr});`;
185
+ return `${ns}.on(${elementVar}, '${event}', ${expr});`;
186
186
  }
187
187
 
188
- return `${ns}.event.delegate(${elementVar}, '${event}', ${expr});`;
188
+ return `${ns}.delegate(${elementVar}, '${event}', ${expr});`;
189
189
  }
190
190
 
191
191
  if (name === 'class') {
192
- return `${ns}.attributes.setClass(${elementVar}, '${staticValue}', ${expr});`;
192
+ return `${ns}.setClass(${elementVar}, '${staticValue}', ${expr});`;
193
193
  }
194
194
 
195
- if (name === 'spread') {
196
- return `${ns}.attributes.spread(${elementVar}, ${expr});`;
195
+ if (name === COMPILER_TYPES.Attributes) {
196
+ return `${ns}.setProperties(${elementVar}, ${expr});`;
197
197
  }
198
198
 
199
199
  if (name === 'style') {
200
- return `${ns}.attributes.setStyle(${elementVar}, '${staticValue}', ${expr});`;
200
+ return `${ns}.setStyle(${elementVar}, '${staticValue}', ${expr});`;
201
201
  }
202
202
 
203
- return `${ns}.attributes.setProperty(${elementVar}, '${name}', ${expr});`;
203
+ return `${ns}.setProperty(${elementVar}, '${name}', ${expr});`;
204
204
  };
205
205
 
206
206
  const generateSpreadBindings = (
@@ -217,7 +217,7 @@ const generateSpreadBindings = (
217
217
  let analysis = analyzeSpread(expr, checker);
218
218
 
219
219
  if (!analysis.canUnpack) {
220
- return [`${ns}.attributes.spread(${elementVar}, ${exprCode});`];
220
+ return [`${ns}.setProperties(${elementVar}, ${exprCode});`];
221
221
  }
222
222
 
223
223
  let lines: string[] = [];
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ArraySlot } from './slot/array';
2
- import attributes from './attributes';
2
+ import { setProperties } from './attributes';
3
3
  import slot from './slot';
4
4
 
5
5
 
@@ -38,7 +38,7 @@ type Template = {
38
38
  html: string;
39
39
  literals: TemplateStringsArray;
40
40
  slots: {
41
- fn: typeof attributes.spread | typeof slot;
41
+ fn: typeof setProperties | typeof slot;
42
42
  name: string | null;
43
43
  path: (() => ChildNode | null)[];
44
44
  }[] | null;