@dxos/ui 0.8.4-main.c85a9c8dae → 0.8.4-main.e00bdcdb52

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/ui",
3
- "version": "0.8.4-main.c85a9c8dae",
3
+ "version": "0.8.4-main.e00bdcdb52",
4
4
  "description": "Core UI.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -21,16 +21,13 @@
21
21
  }
22
22
  },
23
23
  "types": "dist/types/src/index.d.ts",
24
- "typesVersions": {
25
- "*": {}
26
- },
27
24
  "files": [
28
25
  "dist",
29
26
  "src"
30
27
  ],
31
28
  "dependencies": {
32
- "@dxos/ui-types": "0.8.4-main.c85a9c8dae",
33
- "@dxos/ui-theme": "0.8.4-main.c85a9c8dae"
29
+ "@dxos/ui-types": "0.8.4-main.e00bdcdb52",
30
+ "@dxos/ui-theme": "0.8.4-main.e00bdcdb52"
34
31
  },
35
32
  "publishConfig": {
36
33
  "access": "public"
@@ -69,7 +69,35 @@ describe('domino', () => {
69
69
  });
70
70
 
71
71
  test('Domino creates nested SVG elements', () => {
72
- const svg = Domino.of('svg', Domino.SVG).children(Domino.of('circle', Domino.SVG)).root;
72
+ const svg = Domino.of('svg', Domino.SVG).append(Domino.of('circle', Domino.SVG)).root;
73
73
  expect(svg.querySelector('circle')).toBeTruthy();
74
74
  });
75
+
76
+ test('Domino on() respects AddEventListenerOptions (once)', () => {
77
+ let count = 0;
78
+ const el = Domino.of('button').on('click', () => count++, { once: true }).root;
79
+ el.click();
80
+ el.click();
81
+ expect(count).toBe(1);
82
+ });
83
+
84
+ test('Domino mount() attaches to parent and stays chainable', () => {
85
+ const parent = document.createElement('div');
86
+ const el = Domino.of('span').text('hi').mount(parent).classNames('mounted').root;
87
+ expect(parent.firstChild).toBe(el);
88
+ expect(el.textContent).toBe('hi');
89
+ expect(el.classList.contains('mounted')).toBe(true);
90
+ });
91
+
92
+ test('Domino.iconsUrl can be overridden at module level', () => {
93
+ const original = Domino.iconsUrl;
94
+ try {
95
+ Domino.iconsUrl = 'https://example.test/icons.svg';
96
+ expect(Domino.icon('foo')).toBe('https://example.test/icons.svg#foo');
97
+ const svg = Domino.svg('foo').root;
98
+ expect(svg.querySelector('use')?.getAttribute('href')).toBe('https://example.test/icons.svg#foo');
99
+ } finally {
100
+ Domino.iconsUrl = original;
101
+ }
102
+ });
75
103
  });
package/src/domino.ts CHANGED
@@ -5,8 +5,14 @@
5
5
  import { mx } from '@dxos/ui-theme';
6
6
  import { type ClassNameValue } from '@dxos/ui-types';
7
7
 
8
- // From icon-plugin.
9
- const ICONS_URL = '/icons.svg';
8
+ /**
9
+ * Base URL of the icon sprite sheet emitted by `@dxos/vite-plugin-icons`.
10
+ * Defaults to `/icons.svg` which works inside hosted apps served at the
11
+ * site root. Callers running in a different origin context (e.g. browser
12
+ * extensions that inject into arbitrary pages) can override by assigning
13
+ * `Domino.iconsUrl` before first use.
14
+ */
15
+ const DEFAULT_ICONS_URL = '/icons.svg';
10
16
 
11
17
  /**
12
18
  * Super lightweight chainable DOM builder.
@@ -14,16 +20,21 @@ const ICONS_URL = '/icons.svg';
14
20
  export class Domino<T extends HTMLElement | SVGElement> {
15
21
  static SVG = 'http://www.w3.org/2000/svg';
16
22
 
17
- static icon = (icon: string) => ICONS_URL + '#' + icon;
23
+ /** Overridable at module level so `Domino.svg()` can resolve from any origin. */
24
+ static iconsUrl: string = DEFAULT_ICONS_URL;
25
+
26
+ // TODO(burdon): Make private.
27
+ static icon = (icon: string) => Domino.iconsUrl + '#' + icon;
18
28
 
19
29
  /**
20
30
  * Creates an SVG icon element from the icon sprite sheet.
21
31
  */
32
+ // TODO(burdon): Rename icon.
22
33
  static svg = (icon: string) =>
23
34
  Domino.of('svg', Domino.SVG)
24
35
  .classNames('shrink-0 h-[1em] w-[1em]')
25
36
  .attributes({ viewBox: '0 0 256 256' })
26
- .children(Domino.of('use', Domino.SVG).attributes({ href: Domino.icon(icon) }));
37
+ .append(Domino.of('use', Domino.SVG).attributes({ href: Domino.icon(icon) }));
27
38
 
28
39
  /**
29
40
  * Create builder from DOM node.
@@ -76,13 +87,32 @@ export class Domino<T extends HTMLElement | SVGElement> {
76
87
  return this;
77
88
  }
78
89
 
79
- children<C extends HTMLElement | SVGElement>(...children: Domino<C>[]): this {
90
+ append<C extends HTMLElement | SVGElement>(...children: Domino<C>[]): this {
80
91
  children.forEach((child) => this._el.appendChild(child.root));
81
92
  return this;
82
93
  }
83
94
 
84
- on(event: string, handler: (e: Event) => void): this {
85
- this._el.addEventListener(event, handler);
95
+ /**
96
+ * Typed event listener. Accepts the standard `AddEventListenerOptions`
97
+ * third argument so callers can opt into `capture`, `once`, `passive`.
98
+ */
99
+ on<K extends keyof HTMLElementEventMap>(
100
+ event: K,
101
+ handler: (e: HTMLElementEventMap[K]) => void,
102
+ options?: boolean | AddEventListenerOptions,
103
+ ): this;
104
+ on(event: string, handler: (e: Event) => void, options?: boolean | AddEventListenerOptions): this;
105
+ on(event: string, handler: (e: Event) => void, options?: boolean | AddEventListenerOptions): this {
106
+ this._el.addEventListener(event, handler, options);
107
+ return this;
108
+ }
109
+
110
+ /**
111
+ * Convenience for attaching the root element to a parent node — useful at
112
+ * the end of a chain to avoid a trailing `.root` / `parent.appendChild()`.
113
+ */
114
+ mount(parent: Node): this {
115
+ parent.appendChild(this._el);
86
116
  return this;
87
117
  }
88
118