@xtia/jel 0.6.3 → 0.6.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.
@@ -2,7 +2,7 @@ import { attribsProxy, eventsProxy, styleProxy } from "./proxy";
2
2
  import { entityDataSymbol, isContent, isJelEntity } from "./util";
3
3
  const elementWrapCache = new WeakMap();
4
4
  const recursiveAppend = (parent, c) => {
5
- if (c === null)
5
+ if (c === null || c === undefined)
6
6
  return;
7
7
  if (Array.isArray(c)) {
8
8
  c.forEach(item => recursiveAppend(parent, item));
@@ -52,8 +52,9 @@ function createElement(tag, descriptor = {}) {
52
52
  domElement.setAttribute(k, v === true ? k : v);
53
53
  });
54
54
  }
55
- if (descriptor.content !== undefined)
56
- recursiveAppend(domElement, descriptor.content);
55
+ if ("content" in descriptor) {
56
+ ent.content = descriptor.content;
57
+ }
57
58
  if (descriptor.style) {
58
59
  ent.style(descriptor.style);
59
60
  }
@@ -127,6 +128,9 @@ function observeMutations() {
127
128
  subtree: true
128
129
  });
129
130
  }
131
+ function isReactiveSource(value) {
132
+ return typeof value == "object" && value && ("listen" in value || "subscribe" in value);
133
+ }
130
134
  function getWrappedElement(element) {
131
135
  if (!elementWrapCache.has(element)) {
132
136
  const setCSSVariable = (k, v) => {
@@ -137,53 +141,69 @@ function getWrappedElement(element) {
137
141
  element.style.setProperty("--" + k, v);
138
142
  }
139
143
  };
140
- const styleListeners = {};
141
- function addStyleListener(prop, source) {
144
+ const listeners = {
145
+ style: {},
146
+ cssVariable: {},
147
+ content: {},
148
+ };
149
+ function addListener(type, prop, source) {
150
+ const set = {
151
+ style: (v) => element.style[prop] = v,
152
+ cssVariable: (v) => setCSSVariable(prop, v),
153
+ content: (v) => {
154
+ element.innerHTML = "";
155
+ recursiveAppend(element, v);
156
+ }
157
+ }[type];
142
158
  const subscribe = "subscribe" in source
143
- ? () => source.subscribe(v => element.style[prop] = v)
144
- : () => source.listen(v => element.style[prop] = v);
145
- styleListeners[prop] = {
159
+ ? () => source.subscribe(set)
160
+ : () => source.listen(set);
161
+ listeners[type][prop] = {
146
162
  subscribe,
147
163
  unsubscribe: element.isConnected ? subscribe() : null,
148
164
  };
149
165
  if (!elementMutationMap.has(element)) {
150
166
  elementMutationMap.set(element, {
151
167
  add: () => {
152
- Object.values(styleListeners).forEach(l => { var _a; return l.unsubscribe = (_a = l.subscribe) === null || _a === void 0 ? void 0 : _a.call(l); });
168
+ Object.values(listeners).forEach(group => {
169
+ Object.values(group).forEach(l => { var _a; return l.unsubscribe = (_a = l.subscribe) === null || _a === void 0 ? void 0 : _a.call(l); });
170
+ });
153
171
  },
154
172
  remove: () => {
155
- Object.values(styleListeners).forEach(l => {
156
- var _a;
157
- (_a = l.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(l);
158
- l.unsubscribe = null;
173
+ Object.values(listeners).forEach(group => {
174
+ Object.values(group).forEach(l => {
175
+ var _a;
176
+ (_a = l.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(l);
177
+ l.unsubscribe = null;
178
+ });
159
179
  });
160
180
  }
161
181
  });
162
182
  }
163
183
  observeMutations();
164
184
  }
165
- function removeStyleListener(prop) {
166
- if (styleListeners[prop].unsubscribe) {
167
- styleListeners[prop].unsubscribe();
185
+ function removeListener(type, prop) {
186
+ if (listeners[type][prop].unsubscribe) {
187
+ listeners[type][prop].unsubscribe();
168
188
  }
169
- delete styleListeners[prop];
170
- if (Object.keys(styleListeners).length == 0) {
189
+ delete listeners[type][prop];
190
+ if (!Object.keys(listeners).some(group => Object.keys(group).length == 0)) {
171
191
  elementMutationMap.delete(element);
172
192
  }
173
193
  }
174
194
  function setStyle(prop, value) {
175
- if (styleListeners[prop])
176
- removeStyleListener(prop);
195
+ if (listeners.style[prop])
196
+ removeListener("style", prop);
177
197
  if (typeof value == "object" && value) {
178
198
  if ("listen" in value || "subscribe" in value) {
179
- addStyleListener(prop, value);
199
+ addListener("style", prop, value);
180
200
  return;
181
201
  }
182
202
  value = value.toString();
183
203
  }
184
204
  if (value === undefined) {
185
- return prop in styleListeners
186
- ? styleListeners[prop].subscribe
205
+ return prop in listeners
206
+ ? listeners.style[prop].subscribe
187
207
  : element.style[prop];
188
208
  }
189
209
  element.style[prop] = value;
@@ -199,12 +219,27 @@ function getWrappedElement(element) {
199
219
  });
200
220
  },
201
221
  append(...content) {
222
+ var _a;
223
+ if ((_a = listeners.content) === null || _a === void 0 ? void 0 : _a[""])
224
+ removeListener("content", "");
202
225
  recursiveAppend(element, content);
203
226
  },
204
227
  remove: () => element.remove(),
205
228
  setCSSVariable(variableNameOrTable, value) {
206
229
  if (typeof variableNameOrTable == "object") {
207
- Object.entries(variableNameOrTable).forEach(([k, v]) => setCSSVariable(k, v));
230
+ Object.entries(variableNameOrTable).forEach(([k, v]) => {
231
+ if (isReactiveSource(v)) {
232
+ addListener("cssVariable", k, v);
233
+ return;
234
+ }
235
+ setCSSVariable(k, v);
236
+ });
237
+ return;
238
+ }
239
+ if (listeners.cssVariable[variableNameOrTable])
240
+ removeListener("cssVariable", variableNameOrTable);
241
+ if (isReactiveSource(value)) {
242
+ addListener("cssVariable", variableNameOrTable, value);
208
243
  return;
209
244
  }
210
245
  setCSSVariable(variableNameOrTable, value);
@@ -231,6 +266,13 @@ function getWrappedElement(element) {
231
266
  });
232
267
  },
233
268
  set content(v) {
269
+ var _a;
270
+ if ((_a = listeners.content) === null || _a === void 0 ? void 0 : _a[""])
271
+ removeListener("content", "");
272
+ if (isReactiveSource(v)) {
273
+ addListener("content", "", v);
274
+ return;
275
+ }
234
276
  element.innerHTML = "";
235
277
  recursiveAppend(element, v);
236
278
  },
@@ -38,7 +38,7 @@ export type ElementDescriptor<Tag extends string> = {
38
38
  [E in keyof HTMLElementEventMap]+?: (event: HTMLElementEventMap[E]) => void;
39
39
  };
40
40
  style?: StylesDescriptor;
41
- cssVariables?: Record<string, CSSValue>;
41
+ cssVariables?: Record<string, CSSValue | ReactiveSource<CSSValue>>;
42
42
  } & (Tag extends TagWithValue ? {
43
43
  value?: string | number;
44
44
  } : {}) & (Tag extends ContentlessTag ? {} : {
@@ -63,8 +63,8 @@ type ElementAPI<T extends HTMLElement> = {
63
63
  };
64
64
  readonly events: EventsAccessor;
65
65
  readonly style: StyleAccessor;
66
- setCSSVariable(variableName: string, value: CSSValue): void;
67
- setCSSVariable(table: Record<string, CSSValue>): void;
66
+ setCSSVariable(variableName: string, value: CSSValue | ReactiveSource<CSSValue>): void;
67
+ setCSSVariable(table: Record<string, CSSValue | ReactiveSource<CSSValue>>): void;
68
68
  qsa(selector: string): (Element | DomEntity<HTMLElement>)[];
69
69
  remove(): void;
70
70
  getRect(): DOMRect;
@@ -74,7 +74,7 @@ type ElementAPI<T extends HTMLElement> = {
74
74
  } & (T extends ContentlessElement ? {} : {
75
75
  append(...content: DOMContent[]): void;
76
76
  innerHTML: string;
77
- content: DOMContent;
77
+ content: DOMContent | ReactiveSource<DOMContent>;
78
78
  }) & (T extends HTMLElementTagNameMap[TagWithValue] ? {
79
79
  value: string;
80
80
  select(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtia/jel",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "repository": {
5
5
  "url": "https://github.com/tiadrop/jel-ts",
6
6
  "type": "github"