@brandup/ui 1.0.2 → 1.0.3

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/README.md CHANGED
@@ -21,25 +21,24 @@ npm i @brandup/ui@latest
21
21
  ```
22
22
  abstract class UIElement {
23
23
  abstract typeName: string;
24
- readonly element: HTMLElement;
24
+ readonly element: HTMLElement | undefined;
25
25
 
26
26
  protected setElement(elem: HTMLElement): void;
27
27
 
28
- protected defineEvent(eventName: string, eventOptions?: IEventOptions): void;
28
+ protected defineEvent(eventName: string, eventOptions?: EventInit): void;
29
29
  protected raiseEvent(eventName: string, eventArgs?: any): boolean;
30
30
 
31
31
  addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
32
32
  removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
33
33
  dispatchEvent(event: Event): boolean;
34
34
 
35
- registerCommand(name: string, execute: CommandDelegate, canExecute: CommandCanExecuteDelegate = null): void;
36
- registerAsyncCommand(name: string, delegate: CommandAsyncDelegate): void;
35
+ registerCommand(name: string, execute: CommandDelegate, canExecute?: CommandCanExecuteDelegate): void;
37
36
  hasCommand(name: string): boolean;
38
- execCommand(name: string, elem: HTMLElement): CommandExecutionResult;
39
37
 
40
38
  protected _onRenderElement(_elem: HTMLElement);
41
39
  protected _onCanExecCommand(_name: string, _elem: HTMLElement): boolean;
42
40
 
41
+ onDestroy(callback: VoidFunction | UIElement | Element);
43
42
  destroy(): void;
44
43
  }
45
44
  ```
@@ -51,27 +50,23 @@ abstract class UIElement {
51
50
  ```
52
51
  <button data-command="send">Send</button>
53
52
 
54
- this.registerCommand("send", (elem: HTMLElement, context: CommandContext) => { elem.innerHTML = "ok"; });
53
+ this.registerCommand("send", (context: CommandContext) => { context.target.innerHTML = "ok"; });
55
54
  ```
56
55
 
57
56
  Так же можно регистрировать асинхронные команды:
58
57
 
59
58
  ```
60
- this.registerAsyncCommand("command1-async", (context: CommandAsyncContext) => {
61
- context.timeout = 3000;
62
-
63
- context.target.innerHTML = "Loading...";
64
- const t = window.setTimeout(() => {
65
- context.target.innerHTML = "Ok";
66
- context.complate();
67
- }, 2000);
68
-
69
- context.timeoutCallback = () => {
70
- clearTimeout(t);
71
- };
59
+ this.registerCommand("command1-async", (context: CommandContext) => {
60
+ return Promise<void>(resolve => {
61
+ context.target.innerHTML = "Loading...";
62
+ const t = window.setTimeout(() => {
63
+ context.target.innerHTML = "Ok";
64
+ resolve();
65
+ }, 2000);
66
+ });
72
67
  });
73
68
  ```
74
69
 
75
- Команды вызываются по событию click.
70
+ Команды срабатывают по событию `click`.
76
71
 
77
72
  Во время выполнения команды, у элемента добавляется стиль **executing**.
package/dist/cjs/index.js CHANGED
@@ -1,13 +1,18 @@
1
1
  'use strict';
2
2
 
3
- const ElemAttributeName = "uiElement";
4
- const ElemPropertyName = "brandupUiElement";
5
- const CommandAttributeName = "command";
6
- const CommandExecutingCssClassName = "executing";
3
+ const constants = {
4
+ ElemAttributeName: "uiElement",
5
+ ElemPropertyName: "uielement",
6
+ CommandAttributeName: "command",
7
+ CommandExecutingCssClassName: "executing",
8
+ CommandEventName: "uicommand"
9
+ };
10
+
7
11
  class UIElement {
8
- __element = null;
9
- __events = {};
10
- __commandHandlers = {};
12
+ __element;
13
+ __events;
14
+ __commands;
15
+ __destroyCallbacks;
11
16
  // Element members
12
17
  get element() { return this.__element; }
13
18
  setElement(elem) {
@@ -16,35 +21,33 @@ class UIElement {
16
21
  if (this.__element || UIElement.hasElement(elem))
17
22
  throw "UIElement already defined";
18
23
  this.__element = elem;
19
- this.__element[ElemPropertyName] = this;
20
- this.__element.dataset[ElemAttributeName] = this.typeName;
21
- this.defineEvent("command", { cancelable: false, bubbles: true });
24
+ elem[constants.ElemPropertyName] = this;
25
+ elem.dataset[constants.ElemAttributeName] = this.typeName;
26
+ this.defineEvent(constants.CommandEventName, { cancelable: false, bubbles: true });
22
27
  this._onRenderElement(elem);
23
28
  }
24
29
  // static members
25
30
  static hasElement(elem) {
26
- return !!elem.dataset[ElemAttributeName];
31
+ return !!elem.dataset[constants.ElemAttributeName];
27
32
  }
28
33
  // HTMLElement event members
29
34
  defineEvent(eventName, eventOptions) {
35
+ if (!this.__events)
36
+ this.__events = {};
30
37
  this.__events[eventName] = eventOptions ? eventOptions : null;
31
38
  }
32
39
  raiseEvent(eventName, eventArgs) {
33
- if (!(eventName in this.__events))
40
+ if (!this.__events || !(eventName in this.__events))
34
41
  throw new Error(`Not found event "${eventName}".`);
35
42
  const eventOptions = this.__events[eventName];
36
43
  const eventInit = {};
37
44
  if (eventOptions) {
38
- if (eventOptions.bubbles)
39
- eventInit.bubbles = eventOptions.bubbles;
40
- if (eventOptions.cancelable)
41
- eventInit.cancelable = eventOptions.cancelable;
42
- if (eventOptions.composed)
43
- eventInit.composed = eventOptions.composed;
45
+ eventInit.bubbles = eventOptions.bubbles;
46
+ eventInit.cancelable = eventOptions.cancelable;
47
+ eventInit.composed = eventOptions.composed;
44
48
  }
45
- eventInit.detail = eventArgs ? eventArgs : {};
46
- const event = new CustomEvent(eventName, eventInit);
47
- return this.dispatchEvent(event);
49
+ eventInit.detail = eventArgs;
50
+ return this.dispatchEvent(new CustomEvent(eventName, eventInit));
48
51
  }
49
52
  addEventListener(type, listener, options) {
50
53
  this.__element?.addEventListener(type, listener, options);
@@ -59,89 +62,112 @@ class UIElement {
59
62
  }
60
63
  // Command members
61
64
  registerCommand(name, execute, canExecute) {
62
- name = this.verifyCommandName(name);
63
- this.__commandHandlers[name] = {
65
+ if (!this.__commands)
66
+ this.__commands = {};
67
+ const nornalizedName = name.toLowerCase();
68
+ if (nornalizedName in this.__commands)
69
+ throw new Error(`Command "${name}" already registered.`);
70
+ this.__commands[nornalizedName] = {
64
71
  name: name,
65
72
  execute,
66
- canExecute,
67
- isExecuting: false
73
+ canExecute
68
74
  };
69
75
  }
70
76
  hasCommand(name) {
71
- return name.toLowerCase() in this.__commandHandlers;
77
+ return this.__commands && name.toLowerCase() in this.__commands;
72
78
  }
73
- execCommand(name, elem) {
74
- if (!this.__element)
79
+ /** @internal */
80
+ __execCommand(name, target) {
81
+ if (!this.__element || !this.__commands)
75
82
  throw new Error("UIElement is not set HTMLElement.");
76
83
  const key = name.toLowerCase();
77
- const handler = this.__commandHandlers[key];
78
- if (!handler)
84
+ const command = this.__commands[key];
85
+ if (!command)
79
86
  throw new Error(`Command "${name}" is not registered.`);
80
87
  const context = {
81
- target: elem,
82
- uiElem: this,
83
- transparent: false
88
+ target,
89
+ uiElem: this
84
90
  };
85
- if (handler.isExecuting)
91
+ if (command.isExecuting)
86
92
  return { status: "already", context };
87
- handler.isExecuting = true;
88
- if (!this._onCanExecCommand(name, elem)) {
89
- handler.isExecuting = false;
93
+ command.isExecuting = true;
94
+ if (!this._onCanExecCommand(name, target)) {
95
+ delete command.isExecuting;
90
96
  return { status: "disallow", context };
91
97
  }
92
- if (handler.canExecute && !handler.canExecute(context)) {
93
- handler.isExecuting = false;
98
+ if (command.canExecute && !command.canExecute(context)) {
99
+ delete command.isExecuting;
94
100
  return { status: "disallow", context };
95
101
  }
96
- this.raiseEvent("command", {
97
- name: handler.name,
102
+ this.raiseEvent(constants.CommandEventName, {
103
+ name: command.name,
98
104
  uiElem: this,
99
105
  elem: this.__element
100
106
  });
101
107
  let isAsync;
102
108
  try {
103
- const handlerResult = handler.execute(context);
104
- if (handlerResult && handlerResult instanceof Promise) {
109
+ const commandResult = command.execute(context);
110
+ if (commandResult && commandResult instanceof Promise) {
105
111
  isAsync = true;
106
- elem.classList.add(CommandExecutingCssClassName);
107
- handlerResult
112
+ target.classList.add(constants.CommandExecutingCssClassName);
113
+ commandResult
108
114
  .finally(() => {
109
- elem.classList.remove(CommandExecutingCssClassName);
110
- handler.isExecuting = false;
115
+ target.classList.remove(constants.CommandExecutingCssClassName);
116
+ delete command.isExecuting;
111
117
  });
112
118
  }
113
119
  }
114
120
  finally {
115
121
  if (!isAsync)
116
- handler.isExecuting = false;
122
+ delete command.isExecuting;
117
123
  }
118
124
  return { status: "success", context: context };
119
125
  }
120
- verifyCommandName(name) {
121
- const key = name.toLowerCase();
122
- if (key in this.__commandHandlers)
123
- throw new Error(`Command "${name}" already registered.`);
124
- return key;
125
- }
126
- _onRenderElement(_elem) {
127
- return;
128
- }
126
+ _onRenderElement(_elem) { }
129
127
  _onCanExecCommand(_name, _elem) {
130
128
  return true;
131
129
  }
130
+ onDestroy(callback) {
131
+ if (!this.__element)
132
+ return;
133
+ if (!this.__destroyCallbacks)
134
+ this.__destroyCallbacks = [];
135
+ if (callback instanceof UIElement)
136
+ this.__destroyCallbacks.push(() => callback.destroy());
137
+ else if (callback instanceof Element)
138
+ this.__destroyCallbacks.push(() => callback.remove());
139
+ else
140
+ this.__destroyCallbacks.push(callback);
141
+ }
142
+ toString() {
143
+ return this.typeName;
144
+ }
132
145
  destroy() {
133
146
  const elem = this.__element;
134
147
  if (!elem)
135
148
  return;
136
- this.__element = null;
137
- delete elem.dataset[ElemAttributeName];
138
- delete elem[ElemPropertyName];
149
+ delete elem.dataset[constants.ElemAttributeName];
150
+ delete elem[constants.ElemPropertyName];
151
+ delete this.__element;
152
+ delete this.__events;
153
+ delete this.__commands;
154
+ if (this.__destroyCallbacks) {
155
+ this.__destroyCallbacks.map(callback => {
156
+ try {
157
+ callback();
158
+ }
159
+ catch (reason) {
160
+ console.error(`Error in call "${this.typeName}" destroy callback.`);
161
+ }
162
+ });
163
+ delete this.__destroyCallbacks;
164
+ }
139
165
  }
140
166
  }
141
167
  const fundUiElementByCommand = (elem, commandName) => {
142
168
  while (elem) {
143
- if (elem.dataset[ElemAttributeName]) {
144
- const uiElem = elem[ElemPropertyName];
169
+ if (elem.dataset[constants.ElemAttributeName]) {
170
+ const uiElem = elem[constants.ElemPropertyName];
145
171
  if (uiElem.hasCommand(commandName))
146
172
  return uiElem;
147
173
  }
@@ -157,7 +183,7 @@ const fundUiElementByCommand = (elem, commandName) => {
157
183
  const commandClickHandler = (e) => {
158
184
  let commandElem = e.target;
159
185
  while (commandElem) {
160
- if (commandElem.dataset[CommandAttributeName])
186
+ if (commandElem.dataset[constants.CommandAttributeName])
161
187
  break;
162
188
  if (commandElem === e.currentTarget)
163
189
  return;
@@ -165,12 +191,12 @@ const commandClickHandler = (e) => {
165
191
  }
166
192
  if (!commandElem)
167
193
  return;
168
- const commandName = commandElem.dataset[CommandAttributeName];
194
+ const commandName = commandElem.dataset[constants.CommandAttributeName];
169
195
  if (!commandName)
170
196
  throw new Error("Command data attribute is not have value.");
171
197
  const uiElem = fundUiElementByCommand(commandElem, commandName);
172
198
  if (uiElem) {
173
- const result = uiElem.execCommand(commandName, commandElem);
199
+ const result = uiElem.__execCommand(commandName, commandElem);
174
200
  if (result.status == "success" && result.context.transparent)
175
201
  return;
176
202
  }
@@ -182,9 +208,13 @@ const commandClickHandler = (e) => {
182
208
  };
183
209
  window.addEventListener("click", commandClickHandler, false);
184
210
 
185
- exports.CommandAttributeName = CommandAttributeName;
186
- exports.CommandExecutingCssClassName = CommandExecutingCssClassName;
187
- exports.ElemAttributeName = ElemAttributeName;
188
- exports.ElemPropertyName = ElemPropertyName;
211
+ HTMLElement.prototype.ui = function (factory) {
212
+ factory(this);
213
+ return this;
214
+ };
215
+
216
+ const UICONSTANTS = constants;
217
+
218
+ exports.UICONSTANTS = UICONSTANTS;
189
219
  exports.UIElement = UIElement;
190
220
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/mjs/index.js CHANGED
@@ -1,11 +1,16 @@
1
- const ElemAttributeName = "uiElement";
2
- const ElemPropertyName = "brandupUiElement";
3
- const CommandAttributeName = "command";
4
- const CommandExecutingCssClassName = "executing";
1
+ const constants = {
2
+ ElemAttributeName: "uiElement",
3
+ ElemPropertyName: "uielement",
4
+ CommandAttributeName: "command",
5
+ CommandExecutingCssClassName: "executing",
6
+ CommandEventName: "uicommand"
7
+ };
8
+
5
9
  class UIElement {
6
- __element = null;
7
- __events = {};
8
- __commandHandlers = {};
10
+ __element;
11
+ __events;
12
+ __commands;
13
+ __destroyCallbacks;
9
14
  // Element members
10
15
  get element() { return this.__element; }
11
16
  setElement(elem) {
@@ -14,35 +19,33 @@ class UIElement {
14
19
  if (this.__element || UIElement.hasElement(elem))
15
20
  throw "UIElement already defined";
16
21
  this.__element = elem;
17
- this.__element[ElemPropertyName] = this;
18
- this.__element.dataset[ElemAttributeName] = this.typeName;
19
- this.defineEvent("command", { cancelable: false, bubbles: true });
22
+ elem[constants.ElemPropertyName] = this;
23
+ elem.dataset[constants.ElemAttributeName] = this.typeName;
24
+ this.defineEvent(constants.CommandEventName, { cancelable: false, bubbles: true });
20
25
  this._onRenderElement(elem);
21
26
  }
22
27
  // static members
23
28
  static hasElement(elem) {
24
- return !!elem.dataset[ElemAttributeName];
29
+ return !!elem.dataset[constants.ElemAttributeName];
25
30
  }
26
31
  // HTMLElement event members
27
32
  defineEvent(eventName, eventOptions) {
33
+ if (!this.__events)
34
+ this.__events = {};
28
35
  this.__events[eventName] = eventOptions ? eventOptions : null;
29
36
  }
30
37
  raiseEvent(eventName, eventArgs) {
31
- if (!(eventName in this.__events))
38
+ if (!this.__events || !(eventName in this.__events))
32
39
  throw new Error(`Not found event "${eventName}".`);
33
40
  const eventOptions = this.__events[eventName];
34
41
  const eventInit = {};
35
42
  if (eventOptions) {
36
- if (eventOptions.bubbles)
37
- eventInit.bubbles = eventOptions.bubbles;
38
- if (eventOptions.cancelable)
39
- eventInit.cancelable = eventOptions.cancelable;
40
- if (eventOptions.composed)
41
- eventInit.composed = eventOptions.composed;
43
+ eventInit.bubbles = eventOptions.bubbles;
44
+ eventInit.cancelable = eventOptions.cancelable;
45
+ eventInit.composed = eventOptions.composed;
42
46
  }
43
- eventInit.detail = eventArgs ? eventArgs : {};
44
- const event = new CustomEvent(eventName, eventInit);
45
- return this.dispatchEvent(event);
47
+ eventInit.detail = eventArgs;
48
+ return this.dispatchEvent(new CustomEvent(eventName, eventInit));
46
49
  }
47
50
  addEventListener(type, listener, options) {
48
51
  this.__element?.addEventListener(type, listener, options);
@@ -57,89 +60,112 @@ class UIElement {
57
60
  }
58
61
  // Command members
59
62
  registerCommand(name, execute, canExecute) {
60
- name = this.verifyCommandName(name);
61
- this.__commandHandlers[name] = {
63
+ if (!this.__commands)
64
+ this.__commands = {};
65
+ const nornalizedName = name.toLowerCase();
66
+ if (nornalizedName in this.__commands)
67
+ throw new Error(`Command "${name}" already registered.`);
68
+ this.__commands[nornalizedName] = {
62
69
  name: name,
63
70
  execute,
64
- canExecute,
65
- isExecuting: false
71
+ canExecute
66
72
  };
67
73
  }
68
74
  hasCommand(name) {
69
- return name.toLowerCase() in this.__commandHandlers;
75
+ return this.__commands && name.toLowerCase() in this.__commands;
70
76
  }
71
- execCommand(name, elem) {
72
- if (!this.__element)
77
+ /** @internal */
78
+ __execCommand(name, target) {
79
+ if (!this.__element || !this.__commands)
73
80
  throw new Error("UIElement is not set HTMLElement.");
74
81
  const key = name.toLowerCase();
75
- const handler = this.__commandHandlers[key];
76
- if (!handler)
82
+ const command = this.__commands[key];
83
+ if (!command)
77
84
  throw new Error(`Command "${name}" is not registered.`);
78
85
  const context = {
79
- target: elem,
80
- uiElem: this,
81
- transparent: false
86
+ target,
87
+ uiElem: this
82
88
  };
83
- if (handler.isExecuting)
89
+ if (command.isExecuting)
84
90
  return { status: "already", context };
85
- handler.isExecuting = true;
86
- if (!this._onCanExecCommand(name, elem)) {
87
- handler.isExecuting = false;
91
+ command.isExecuting = true;
92
+ if (!this._onCanExecCommand(name, target)) {
93
+ delete command.isExecuting;
88
94
  return { status: "disallow", context };
89
95
  }
90
- if (handler.canExecute && !handler.canExecute(context)) {
91
- handler.isExecuting = false;
96
+ if (command.canExecute && !command.canExecute(context)) {
97
+ delete command.isExecuting;
92
98
  return { status: "disallow", context };
93
99
  }
94
- this.raiseEvent("command", {
95
- name: handler.name,
100
+ this.raiseEvent(constants.CommandEventName, {
101
+ name: command.name,
96
102
  uiElem: this,
97
103
  elem: this.__element
98
104
  });
99
105
  let isAsync;
100
106
  try {
101
- const handlerResult = handler.execute(context);
102
- if (handlerResult && handlerResult instanceof Promise) {
107
+ const commandResult = command.execute(context);
108
+ if (commandResult && commandResult instanceof Promise) {
103
109
  isAsync = true;
104
- elem.classList.add(CommandExecutingCssClassName);
105
- handlerResult
110
+ target.classList.add(constants.CommandExecutingCssClassName);
111
+ commandResult
106
112
  .finally(() => {
107
- elem.classList.remove(CommandExecutingCssClassName);
108
- handler.isExecuting = false;
113
+ target.classList.remove(constants.CommandExecutingCssClassName);
114
+ delete command.isExecuting;
109
115
  });
110
116
  }
111
117
  }
112
118
  finally {
113
119
  if (!isAsync)
114
- handler.isExecuting = false;
120
+ delete command.isExecuting;
115
121
  }
116
122
  return { status: "success", context: context };
117
123
  }
118
- verifyCommandName(name) {
119
- const key = name.toLowerCase();
120
- if (key in this.__commandHandlers)
121
- throw new Error(`Command "${name}" already registered.`);
122
- return key;
123
- }
124
- _onRenderElement(_elem) {
125
- return;
126
- }
124
+ _onRenderElement(_elem) { }
127
125
  _onCanExecCommand(_name, _elem) {
128
126
  return true;
129
127
  }
128
+ onDestroy(callback) {
129
+ if (!this.__element)
130
+ return;
131
+ if (!this.__destroyCallbacks)
132
+ this.__destroyCallbacks = [];
133
+ if (callback instanceof UIElement)
134
+ this.__destroyCallbacks.push(() => callback.destroy());
135
+ else if (callback instanceof Element)
136
+ this.__destroyCallbacks.push(() => callback.remove());
137
+ else
138
+ this.__destroyCallbacks.push(callback);
139
+ }
140
+ toString() {
141
+ return this.typeName;
142
+ }
130
143
  destroy() {
131
144
  const elem = this.__element;
132
145
  if (!elem)
133
146
  return;
134
- this.__element = null;
135
- delete elem.dataset[ElemAttributeName];
136
- delete elem[ElemPropertyName];
147
+ delete elem.dataset[constants.ElemAttributeName];
148
+ delete elem[constants.ElemPropertyName];
149
+ delete this.__element;
150
+ delete this.__events;
151
+ delete this.__commands;
152
+ if (this.__destroyCallbacks) {
153
+ this.__destroyCallbacks.map(callback => {
154
+ try {
155
+ callback();
156
+ }
157
+ catch (reason) {
158
+ console.error(`Error in call "${this.typeName}" destroy callback.`);
159
+ }
160
+ });
161
+ delete this.__destroyCallbacks;
162
+ }
137
163
  }
138
164
  }
139
165
  const fundUiElementByCommand = (elem, commandName) => {
140
166
  while (elem) {
141
- if (elem.dataset[ElemAttributeName]) {
142
- const uiElem = elem[ElemPropertyName];
167
+ if (elem.dataset[constants.ElemAttributeName]) {
168
+ const uiElem = elem[constants.ElemPropertyName];
143
169
  if (uiElem.hasCommand(commandName))
144
170
  return uiElem;
145
171
  }
@@ -155,7 +181,7 @@ const fundUiElementByCommand = (elem, commandName) => {
155
181
  const commandClickHandler = (e) => {
156
182
  let commandElem = e.target;
157
183
  while (commandElem) {
158
- if (commandElem.dataset[CommandAttributeName])
184
+ if (commandElem.dataset[constants.CommandAttributeName])
159
185
  break;
160
186
  if (commandElem === e.currentTarget)
161
187
  return;
@@ -163,12 +189,12 @@ const commandClickHandler = (e) => {
163
189
  }
164
190
  if (!commandElem)
165
191
  return;
166
- const commandName = commandElem.dataset[CommandAttributeName];
192
+ const commandName = commandElem.dataset[constants.CommandAttributeName];
167
193
  if (!commandName)
168
194
  throw new Error("Command data attribute is not have value.");
169
195
  const uiElem = fundUiElementByCommand(commandElem, commandName);
170
196
  if (uiElem) {
171
- const result = uiElem.execCommand(commandName, commandElem);
197
+ const result = uiElem.__execCommand(commandName, commandElem);
172
198
  if (result.status == "success" && result.context.transparent)
173
199
  return;
174
200
  }
@@ -180,5 +206,12 @@ const commandClickHandler = (e) => {
180
206
  };
181
207
  window.addEventListener("click", commandClickHandler, false);
182
208
 
183
- export { CommandAttributeName, CommandExecutingCssClassName, ElemAttributeName, ElemPropertyName, UIElement };
209
+ HTMLElement.prototype.ui = function (factory) {
210
+ factory(this);
211
+ return this;
212
+ };
213
+
214
+ const UICONSTANTS = constants;
215
+
216
+ export { UICONSTANTS, UIElement };
184
217
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/types.d.ts CHANGED
@@ -1,55 +1,66 @@
1
- declare const ElemAttributeName = "uiElement";
2
- declare const ElemPropertyName = "brandupUiElement";
3
- declare const CommandAttributeName = "command";
4
- declare const CommandExecutingCssClassName = "executing";
5
- type CommandDelegate = (context: CommandContext) => void | Promise<void | any>;
6
- type CommandCanExecuteDelegate = (context: CommandContext) => boolean;
1
+ interface UiConstants {
2
+ readonly ElemAttributeName: string;
3
+ readonly ElemPropertyName: string;
4
+ readonly CommandAttributeName: string;
5
+ readonly CommandExecutingCssClassName: string;
6
+ readonly CommandEventName: string;
7
+ }
8
+
9
+ type CommandExecuteFunction = (context: CommandContext) => void | Promise<void | any>;
10
+ type CommandCanExecuteFunction = (context: CommandContext) => boolean;
7
11
  declare abstract class UIElement {
8
- private __element;
9
- private __events;
10
- private __commandHandlers;
12
+ private __element?;
13
+ private __events?;
14
+ private __commands?;
15
+ private __destroyCallbacks;
11
16
  abstract typeName: string;
12
- get element(): HTMLElement | null;
17
+ get element(): HTMLElement | undefined;
13
18
  protected setElement(elem: HTMLElement): void;
14
19
  static hasElement(elem: HTMLElement): boolean;
15
- protected defineEvent(eventName: string, eventOptions?: EventOptions): void;
20
+ protected defineEvent(eventName: string, eventOptions?: EventInit): void;
16
21
  protected raiseEvent<T = {}>(eventName: string, eventArgs?: T): boolean;
17
22
  addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
18
23
  removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
19
24
  dispatchEvent(event: Event): boolean;
20
- registerCommand(name: string, execute: CommandDelegate, canExecute?: CommandCanExecuteDelegate): void;
21
- hasCommand(name: string): boolean;
22
- execCommand(name: string, elem: HTMLElement): CommandExecutionResult;
23
- private verifyCommandName;
25
+ registerCommand(name: string, execute: CommandExecuteFunction, canExecute?: CommandCanExecuteFunction): void;
26
+ hasCommand(name: string): boolean | undefined;
24
27
  protected _onRenderElement(_elem: HTMLElement): void;
25
28
  protected _onCanExecCommand(_name: string, _elem: HTMLElement): boolean;
29
+ onDestroy(callback: VoidFunction | UIElement | Element): void;
30
+ toString(): string;
26
31
  destroy(): void;
27
32
  }
28
- interface EventOptions {
29
- bubbles?: boolean;
30
- cancelable?: boolean;
31
- composed?: boolean;
32
- }
33
33
  interface CommandEventArgs {
34
34
  name: string;
35
35
  uiElem: UIElement;
36
36
  elem: HTMLElement;
37
37
  }
38
38
  interface CommandContext {
39
- /** Елемент, который принял команду. */
39
+ /** HTMLElement on which the command is executed */
40
40
  target: HTMLElement;
41
+ /** UIElement in which the command handler is registered. */
41
42
  uiElem: UIElement;
42
- transparent: boolean;
43
+ /** Don't stop the click event chain of target. */
44
+ transparent?: boolean;
43
45
  }
44
- interface CommandExecutionResult {
46
+ interface CommandResult {
45
47
  status: CommandExecStatus;
46
48
  context: CommandContext;
47
49
  }
48
- interface CommandAsyncContext extends CommandContext {
49
- timeout?: number;
50
- complate: VoidFunction;
51
- timeoutCallback?: VoidFunction;
52
- }
53
50
  type CommandExecStatus = "disallow" | "already" | "success";
54
51
 
55
- export { type CommandAsyncContext, CommandAttributeName, type CommandCanExecuteDelegate, type CommandContext, type CommandDelegate, type CommandEventArgs, type CommandExecStatus, CommandExecutingCssClassName, type CommandExecutionResult, ElemAttributeName, ElemPropertyName, type EventOptions, UIElement };
52
+ declare global {
53
+ interface HTMLElement {
54
+ ui(factory: (elem: HTMLElement) => UIElement): HTMLElement;
55
+ }
56
+ interface Node {
57
+ readonly uielement: UIElement | undefined;
58
+ }
59
+ interface HTMLElementEventMap {
60
+ "uicommand": CustomEvent<CommandEventArgs>;
61
+ }
62
+ }
63
+
64
+ declare const UICONSTANTS: UiConstants;
65
+
66
+ export { type CommandCanExecuteFunction, type CommandContext, type CommandEventArgs, type CommandExecStatus, type CommandExecuteFunction, type CommandResult, UICONSTANTS, UIElement };
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "email": "it@brandup.online"
23
23
  },
24
24
  "license": "Apache-2.0",
25
- "version": "1.0.2",
25
+ "version": "1.0.3",
26
26
  "main": "dist/cjs/index.js",
27
27
  "module": "dist/mjs/index.js",
28
28
  "types": "dist/types.d.ts",