@thepassle/app-tools 0.7.9 → 0.8.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.
package/dialog/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { APP_TOOLS } from '../utils/CONSTANTS.js';
1
+ import { APP_TOOLS, VERSION } from '../utils/CONSTANTS.js';
2
2
  import { setupGlobalDialogStyles } from './utils.js';
3
3
  import { DialogStateEvent } from './events.js';
4
4
  import { onePaint, animationsComplete } from '../utils/async.js';
@@ -10,6 +10,7 @@ const log = createLogger('dialog');
10
10
  * @typedef {import('./types.js').DialogCallbacks} DialogCallbacks
11
11
  * @typedef {import('./types.js').Config} Config
12
12
  * @typedef {import('./types.js').OpenDialogOptions} OpenDialogOptions
13
+ * @typedef {import('./types.js').Context} Context
13
14
  */
14
15
 
15
16
  setupGlobalDialogStyles();
@@ -21,6 +22,12 @@ export class Dialog extends EventTarget {
21
22
  isOpen = false;
22
23
  opened = new Promise((resolve) => {this.__resolveOpened = resolve;});
23
24
  closed = new Promise((resolve) => {this.__resolveClosed = resolve;});
25
+ /** @type {Context} */
26
+ context = {
27
+ dialog: undefined,
28
+ id: '',
29
+ parameters: {}
30
+ }
24
31
 
25
32
  /**
26
33
  *
@@ -37,11 +44,13 @@ export class Dialog extends EventTarget {
37
44
  __initDialogNode() {
38
45
  const dialogNode = /** @type {DialogNode} */ (document.createElement('dialog'));
39
46
  dialogNode.setAttribute(APP_TOOLS, '');
47
+ dialogNode.setAttribute('version', VERSION);
40
48
  dialogNode.addEventListener('close', this.__onDialogClose);
41
49
  dialogNode.addEventListener('mousedown', this.__onLightDismiss);
42
50
 
43
51
  const form = document.createElement('form');
44
52
  form.setAttribute(APP_TOOLS, '');
53
+ form.setAttribute('version', VERSION);
45
54
  form.setAttribute('method', 'dialog');
46
55
  dialogNode.form = form;
47
56
 
@@ -64,20 +73,13 @@ export class Dialog extends EventTarget {
64
73
  const id = this.#id;
65
74
  const d = /** @type {DialogNode} */ (this.__dialog);
66
75
 
67
- log(`Closing dialog "${id}"`, {
68
- id,
69
- dialog: d,
70
- returnValue: d?.returnValue
71
- });
76
+ log(`Closing dialog "${id}"`, this.context);
72
77
 
73
78
  d.removeAttribute('opened');
74
79
  d.setAttribute('closing', '');
75
- this.dispatchEvent(new DialogStateEvent('closing', {
76
- id,
77
- dialog: d,
78
- }));
80
+ this.dispatchEvent(new DialogStateEvent('closing', this.context));
79
81
  try {
80
- await this.#config[id]?.closing?.({dialog: d});
82
+ await this.#config[id]?.closing?.(this.context);
81
83
  } catch(e) {
82
84
  log(`Dialog "${id}" error on closing hook`);
83
85
  throw e;
@@ -89,25 +91,23 @@ export class Dialog extends EventTarget {
89
91
  d.setAttribute('closed', '');
90
92
 
91
93
  // @ts-ignore
92
- this.__resolveClosed(d);
94
+ this.__resolveClosed(this.context);
93
95
 
94
- this.dispatchEvent(new DialogStateEvent('closed', {
95
- id,
96
- dialog: d
97
- }));
96
+ this.dispatchEvent(new DialogStateEvent('closed', this.context));
98
97
  try {
99
- await this.#config[id]?.closed?.({dialog: d});
98
+ await this.#config[id]?.closed?.(this.context);
100
99
  } catch(e) {
101
100
  log(`Dialog "${id}" error on closed hook`);
102
101
  throw e;
103
102
  }
104
- log(`Closed dialog "${id}"`, {
105
- id,
106
- dialog: d,
107
- returnValue: d?.returnValue
108
- });
103
+ log(`Closed dialog "${id}"`, this.context);
109
104
 
110
105
  d?.remove();
106
+ this.context = {
107
+ dialog: undefined,
108
+ id: '',
109
+ parameters: {}
110
+ }
111
111
  this.__dialog = undefined;
112
112
 
113
113
  this.opened = new Promise((resolve) => {this.__resolveOpened = resolve;});
@@ -130,14 +130,19 @@ export class Dialog extends EventTarget {
130
130
  }
131
131
 
132
132
  this.__dialog = this.__initDialogNode();
133
+ this.context = {
134
+ dialog: this.__dialog,
135
+ id,
136
+ parameters,
137
+ }
133
138
  document.body.appendChild(this.__dialog);
134
-
135
- log(`Openening dialog "${id}"`, { id, parameters, dialog: this.__dialog });
139
+
140
+ log(`Openening dialog "${id}"`, this.context);
136
141
  this.__dialog.setAttribute('opening', '');
137
- this.dispatchEvent(new DialogStateEvent('opening', { id, dialog: this.__dialog }));
142
+ this.dispatchEvent(new DialogStateEvent('opening', this.context));
138
143
 
139
144
  try {
140
- await this.#config?.[id]?.opening?.({dialog: this.__dialog, parameters});
145
+ await this.#config?.[id]?.opening?.(this.context);
141
146
  } catch(e) {
142
147
  log(`Dialog "${this.#id}" error on opening hook`);
143
148
  throw e;
@@ -152,15 +157,15 @@ export class Dialog extends EventTarget {
152
157
  this.__dialog.removeAttribute('opening');
153
158
  this.__dialog.setAttribute('opened', '');
154
159
  // @ts-ignore
155
- this.__resolveOpened(this.__dialog);
156
- this.dispatchEvent(new DialogStateEvent('opened', { id, dialog: this.__dialog }));
160
+ this.__resolveOpened(this.context);
161
+ this.dispatchEvent(new DialogStateEvent('opened', this.context));
157
162
  try {
158
- await this.#config?.[id]?.opened?.({dialog: this.__dialog, parameters});
163
+ await this.#config?.[id]?.opened?.(this.context);
159
164
  } catch(e) {
160
165
  log(`Dialog "${this.#id}" error on opened hook`);
161
166
  throw e;
162
167
  }
163
- log(`Opened dialog "${id}"`, { id, parameters, dialog: this.__dialog });
168
+ log(`Opened dialog "${id}"`, this.context);
164
169
  this.closed = new Promise((resolve) => {this.__resolveClosed = resolve;});
165
170
  }
166
171
 
package/dialog/types.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export type DialogNode = HTMLDialogElement & { form: HTMLFormElement };
2
2
 
3
3
  export interface DialogCallbacks {
4
- opening?: <Parameters>(opts: {dialog: DialogNode, parameters: Parameters}) => void;
5
- opened?: <Parameters>(opts: {dialog: DialogNode, parameters: Parameters}) => void;
6
- closing?: (opts: {dialog: DialogNode}) => void;
7
- closed?: (opts: {dialog: DialogNode}) => void;
4
+ opening?: <Parameters>(context: Context) => void;
5
+ opened?: <Parameters>(context: Context) => void;
6
+ closing?: (context: Context) => void;
7
+ closed?: (context: Context) => void;
8
8
  }
9
9
 
10
10
  export type Config = Record<string, DialogCallbacks>;
@@ -12,4 +12,10 @@ export type Config = Record<string, DialogCallbacks>;
12
12
  export interface OpenDialogOptions {
13
13
  id: string;
14
14
  parameters?: object;
15
+ }
16
+
17
+ export interface Context {
18
+ dialog: DialogNode,
19
+ id: string,
20
+ parameters: Record<string, any>
15
21
  }
package/dialog/utils.js CHANGED
@@ -1,19 +1,25 @@
1
- import { APP_TOOLS } from '../utils/CONSTANTS.js';
1
+ import { APP_TOOLS, VERSION } from '../utils/CONSTANTS.js';
2
2
 
3
3
  const DIALOG_STYLES_ID = 'dialog-styles';
4
4
 
5
5
  export function setupGlobalDialogStyles() {
6
- let el = document.head.querySelector(`style[${APP_TOOLS}]#${DIALOG_STYLES_ID}`);
6
+ let el = document.head.querySelector(`style[${APP_TOOLS}][version="${VERSION}"]#${DIALOG_STYLES_ID}`);
7
7
  if (!el) {
8
8
  el = document.createElement('style');
9
9
  el.setAttribute(APP_TOOLS, '');
10
+ el.setAttribute('version', VERSION);
10
11
  el.id = DIALOG_STYLES_ID;
11
12
  el.innerHTML = `
12
- html:has(dialog[${APP_TOOLS}][open]) {
13
+ html:has(dialog[${APP_TOOLS}][version="${VERSION}"][open]) {
13
14
  overflow: hidden;
14
15
  }
15
16
 
16
- dialog[${APP_TOOLS}] {
17
+ dialog[${APP_TOOLS}][version="${VERSION}"]:modal {
18
+ max-width: 100%;
19
+ max-height: 100%;
20
+ }
21
+
22
+ dialog[${APP_TOOLS}][version="${VERSION}"] {
17
23
  pointer-events: none;
18
24
  inset: 0;
19
25
  position: fixed;
@@ -24,14 +30,14 @@ export function setupGlobalDialogStyles() {
24
30
  height: 200px;
25
31
  }
26
32
 
27
- dialog[${APP_TOOLS}] > form[${APP_TOOLS}] {
33
+ dialog[${APP_TOOLS}][version="${VERSION}"] > form[${APP_TOOLS}][version="${VERSION}"] {
28
34
  width: calc(100% - 10px);
29
35
  height: calc(100% - 10px);
30
36
  margin: 0;
31
37
  padding: 5px;
32
38
  }
33
39
 
34
- dialog[${APP_TOOLS}][open] {
40
+ dialog[${APP_TOOLS}][version="${VERSION}"][open] {
35
41
  pointer-events: auto;
36
42
  }
37
43
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thepassle/app-tools",
3
- "version": "0.7.9",
3
+ "version": "0.8.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
- import { APP_TOOLS } from '../../utils/CONSTANTS.js';
1
+ import { APP_TOOLS, VERSION } from '../../utils/CONSTANTS.js';
2
2
 
3
3
  const FOCUS_ELEMENT_ID = 'router-focus';
4
4
  const SR_ONLY_STYLE = `position:absolute;top:0;width:1px;height:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);clip-path:inset(50%);margin:-1px;`;
@@ -9,10 +9,11 @@ const SR_ONLY_STYLE = `position:absolute;top:0;width:1px;height:1px;overflow:hid
9
9
  export const resetFocus = {
10
10
  name: 'resetFocus',
11
11
  afterNavigation: ({title}) => {
12
- let el = /** @type {HTMLElement} */ (document.querySelector(`div[${APP_TOOLS}]#${FOCUS_ELEMENT_ID}`));
12
+ let el = /** @type {HTMLElement} */ (document.querySelector(`div[${APP_TOOLS}][version="${VERSION}"]#${FOCUS_ELEMENT_ID}`));
13
13
  if (!el) {
14
14
  el = document.createElement('div');
15
15
  el.setAttribute(APP_TOOLS, '');
16
+ el.setAttribute('version', VERSION);
16
17
  el.id = FOCUS_ELEMENT_ID;
17
18
  el.setAttribute('tabindex', '-1');
18
19
  el.setAttribute('aria-live', 'polite');
@@ -1 +1,2 @@
1
- export const APP_TOOLS = 'app-tools';
1
+ export const APP_TOOLS = 'app-tools';
2
+ export const VERSION = '1.x';
package/utils/async.js CHANGED
@@ -1,19 +1,18 @@
1
- /**
2
- * @param {Function} f
3
- * @returns {<Args>(...args: Args[]) => void}
4
- */
5
- export function debounce(f) {
6
- let timeoutId;
1
+ export function debounce(f, scheduleTask, cancelTask) {
2
+ let task;
7
3
 
8
4
  return (...args) => {
9
- clearTimeout(timeoutId);
10
- timeoutId = setTimeout(() => {
11
- timeoutId = null;
5
+ cancelTask(task);
6
+ task = scheduleTask(() => {
7
+ task = null;
12
8
  f(...args);
13
9
  });
14
10
  };
15
11
  }
16
12
 
13
+ export const debounceAtTimeout = (f, ms) => debounce(f, task => setTimeout(task, ms), clearTimeout);
14
+ export const debounceAtFrame = (f) => debounce(f, requestAnimationFrame, cancelAnimationFrame);
15
+
17
16
  /**
18
17
  * @returns {Promise<number>}
19
18
  */