@xtia/jel 0.4.0 → 0.4.1

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 (4) hide show
  1. package/README.md +2 -6
  2. package/index.d.ts +25 -10
  3. package/index.js +31 -16
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -27,9 +27,7 @@ body.append($.form([
27
27
  $.button("Sign in"),
28
28
  $.a({
29
29
  content: ["Having trouble? ", $.strong("Recover account")],
30
- attribs: {
31
- href: "/recover-account",
32
- }
30
+ href: "/recover-account",
33
31
  })
34
32
  ]));
35
33
 
@@ -39,9 +37,7 @@ body.append([
39
37
  files.map(file => $.li(
40
38
  $.a({
41
39
  content: file.name,
42
- attribs: {
43
- href: `/files/${file.name}`,
44
- }
40
+ href: `/files/${file.name}`,
45
41
  })
46
42
  ))
47
43
  )
package/index.d.ts CHANGED
@@ -18,19 +18,28 @@ type StylesDescriptor = {
18
18
  ] extends [string, string] ? K : never]+?: CSSValue;
19
19
  };
20
20
  type StyleAccessor = StylesDescriptor & ((styles: StylesDescriptor) => void) & ((property: keyof StylesDescriptor, value: CSSValue) => void);
21
- interface ElementDescriptor {
21
+ type ContentlessTag = "area" | "base" | "basefont" | "br" | "col" | "frame" | "hr" | "img" | "input" | "isindex" | "link" | "meta" | "param" | "textarea";
22
+ type TagWithHref = "a" | "link";
23
+ type TagWithSrc = "img" | "script" | "iframe";
24
+ type ElementDescriptor<Tag extends string> = {
22
25
  classes?: ElementClassDescriptor;
23
- content?: DOMContent;
24
26
  attribs?: Record<string, string | number | boolean>;
25
27
  on?: {
26
28
  [E in keyof HTMLElementEventMap]+?: (event: HTMLElementEventMap[E]) => void;
27
29
  };
28
30
  style?: StylesDescriptor;
29
31
  cssVariables?: Record<string, CSSValue>;
30
- }
32
+ } & (Tag extends "input" | "textarea" ? {
33
+ value?: string | number;
34
+ } : Tag extends ContentlessTag ? {} : {
35
+ content?: DOMContent;
36
+ }) & (Tag extends TagWithSrc ? {
37
+ src: string;
38
+ } : Tag extends TagWithHref ? {
39
+ href: string;
40
+ } : {});
31
41
  type ElementAPI<T extends HTMLElement> = EventHost<{
32
42
  readonly element: T;
33
- content: DOMContent;
34
43
  classes: DOMTokenList;
35
44
  attribs: {
36
45
  [key: string]: string | null;
@@ -45,18 +54,24 @@ type ElementAPI<T extends HTMLElement> = EventHost<{
45
54
  getRect(): DOMRect;
46
55
  focus(): void;
47
56
  blur(): void;
48
- } & (T extends HTMLInputElement ? {
57
+ } & (T extends ContentlessTag ? {} : {
58
+ content: DOMContent;
59
+ }) & (T extends HTMLInputElement ? {
49
60
  value: string;
50
61
  select(): void;
51
62
  } : T extends HTMLCanvasElement ? {
52
63
  width: number;
53
64
  height: number;
54
65
  getContext: HTMLCanvasElement["getContext"];
66
+ } : T extends HTMLElementTagNameMap[TagWithSrc] ? {
67
+ src: string;
68
+ } : T extends HTMLElementTagNameMap[TagWithHref] ? {
69
+ href: string;
55
70
  } : {}), HTMLElementEventMap>;
56
- type DomHelper = ((<T extends keyof HTMLElementTagNameMap>(tagName: T, descriptor: ElementDescriptor) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}#${string}`, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}.${string}`, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: T, content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends HTMLElement>(element: T) => DomEntity<T>) & {
57
- [T in keyof HTMLElementTagNameMap]: (descriptor: ElementDescriptor) => DomEntity<HTMLElementTagNameMap[T]>;
71
+ type DomHelper = ((<T extends keyof HTMLElementTagNameMap>(tagName: T, descriptor: ElementDescriptor<T>) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}#${string}`, content?: T extends ContentlessTag ? void : DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: `${T}.${string}`, content?: T extends ContentlessTag ? void : DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends keyof HTMLElementTagNameMap>(selector: T, content?: T extends ContentlessTag ? void : DOMContent) => DomEntity<HTMLElementTagNameMap[T]>) & (<T extends HTMLElement>(element: T) => DomEntity<T>) & {
72
+ [T in keyof HTMLElementTagNameMap]: (descriptor: ElementDescriptor<T>) => DomEntity<HTMLElementTagNameMap[T]>;
58
73
  } & {
59
- [T in keyof HTMLElementTagNameMap]: (content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>;
74
+ [T in keyof HTMLElementTagNameMap]: T extends ContentlessTag ? () => DomEntity<HTMLElementTagNameMap[T]> : (content?: DOMContent) => DomEntity<HTMLElementTagNameMap[T]>;
60
75
  });
61
76
  type JelEntityData = {
62
77
  dom: DOMContent;
@@ -74,6 +89,6 @@ type EventHost<API extends object | void, EventDataMap> = (API extends object ?
74
89
  export declare const $: DomHelper;
75
90
  declare const entityDataSymbol: unique symbol;
76
91
  export declare function createEntity<API extends object>(content: DOMContent, api: API extends DOMContent ? never : API): JelEntity<API>;
77
- export declare function createEntity(content: DOMContent, api?: undefined): JelEntity<undefined>;
78
- export declare function definePart<Spec extends ForbidKey<"on">, API extends ForbidKey<"on"> | void = void, EventDataMap extends Record<string, any> = {}>(defaultOptions: Optionals<Spec>, init: (spec: Required<Spec>, append: (content: DOMContent) => void, trigger: <K extends keyof EventDataMap>(eventId: K, eventData: EventDataMap[K]) => void) => API): PartConstructor<Spec, API, EventDataMap>;
92
+ export declare function createEntity(content: DOMContent): JelEntity<void>;
93
+ export declare function definePart<Spec extends ForbidKey<"on">, API extends ForbidKey<"on"> | void = void, EventDataMap extends Record<string, any> = {}>(defaultOptions: Optionals<Spec>, init: (spec: Required<Spec>, append: (...content: DOMContent[]) => void, trigger: <K extends keyof EventDataMap>(eventId: K, eventData: EventDataMap[K]) => void) => API): PartConstructor<Spec, API, EventDataMap>;
79
94
  export {};
package/index.js CHANGED
@@ -26,8 +26,11 @@ const styleProxy = {
26
26
  };
27
27
  function createElement(tag, descriptor = {}) {
28
28
  if (isContent(descriptor))
29
- descriptor = { content: descriptor };
30
- const ent = getWrappedElement(document.createElement(tag));
29
+ return createElement(tag, {
30
+ content: descriptor,
31
+ });
32
+ const domElement = document.createElement(tag);
33
+ const ent = getWrappedElement(domElement);
31
34
  const applyClasses = (classes) => {
32
35
  if (Array.isArray(classes)) {
33
36
  return classes.forEach(c => applyClasses(c));
@@ -42,16 +45,21 @@ function createElement(tag, descriptor = {}) {
42
45
  });
43
46
  };
44
47
  applyClasses(descriptor.classes || []);
48
+ ["value", "src", "href"].forEach(prop => {
49
+ if (descriptor[prop] !== undefined)
50
+ domElement.setAttribute(prop, descriptor[prop]);
51
+ });
52
+ // attribs.value / attribs.src / attribs.href override descriptor.*
45
53
  if (descriptor.attribs) {
46
54
  Object.entries(descriptor.attribs).forEach(([k, v]) => {
47
55
  if (v === false) {
48
56
  return;
49
57
  }
50
- ent.element.setAttribute(k, v === true ? k : v);
58
+ domElement.setAttribute(k, v === true ? k : v);
51
59
  });
52
60
  }
53
61
  if (descriptor.content !== undefined)
54
- recursiveAppend(ent.element, descriptor.content);
62
+ recursiveAppend(domElement, descriptor.content);
55
63
  if (descriptor.style) {
56
64
  ent.style(descriptor.style);
57
65
  }
@@ -205,6 +213,18 @@ function getWrappedElement(element) {
205
213
  set value(v) {
206
214
  element.value = v;
207
215
  },
216
+ get href() {
217
+ return element.href;
218
+ },
219
+ set href(v) {
220
+ element.href = v;
221
+ },
222
+ get src() {
223
+ return element.src;
224
+ },
225
+ set src(v) {
226
+ element.src = v;
227
+ },
208
228
  get width() {
209
229
  return element.width;
210
230
  },
@@ -252,6 +272,7 @@ function createEntity(content, api) {
252
272
  ;
253
273
  function definePart(defaultOptions, init) {
254
274
  return ((spec) => {
275
+ var _a;
255
276
  const fullSpec = Object.assign(Object.assign({}, defaultOptions), spec);
256
277
  const eventHandlers = {};
257
278
  const addEventListener = (eventId, fn) => {
@@ -265,27 +286,21 @@ function definePart(defaultOptions, init) {
265
286
  });
266
287
  let entity;
267
288
  const content = [];
268
- const append = (c) => {
289
+ const append = (...c) => {
269
290
  if (entity)
270
291
  throw new Error("Component root content can only be added during initialisation");
271
- content.push(c);
292
+ content.push(...c);
272
293
  };
273
294
  const trigger = (eventId, data) => {
274
295
  var _a;
275
296
  (_a = eventHandlers[eventId]) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn.call(entity, data));
276
297
  };
277
- const api = init(fullSpec, append, trigger);
278
- Object.defineProperties(api, {
279
- [entityDataSymbol]: {
280
- value: {
281
- dom: content
282
- }
283
- },
298
+ const api = (_a = init(fullSpec, append, trigger)) !== null && _a !== void 0 ? _a : {};
299
+ entity = createEntity(content, Object.create(api, {
284
300
  on: {
285
- get: () => addEventListener
301
+ value: addEventListener,
286
302
  }
287
- });
288
- entity = api;
303
+ }));
289
304
  return entity;
290
305
  });
291
306
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtia/jel",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "repository": {
5
5
  "url": "https://github.com/tiadrop/jel-ts",
6
6
  "type": "github"