@htmlplus/element 3.2.0 → 3.2.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/README.md CHANGED
@@ -146,6 +146,46 @@ In the `index.html` file.
146
146
  TODO
147
147
  </details>
148
148
 
149
+ <details>
150
+ <summary>Debounce</summary>
151
+
152
+ Ensures that the method executes only after the specified delay, resetting the timer if called again within the delay period.
153
+
154
+ In the `my-element.tsx` file.
155
+
156
+ ```tsx
157
+ import { Debounce, Element, State } from '@htmlplus/element';
158
+
159
+ @Element()
160
+ export class MyCounter {
161
+ @State()
162
+ value: number = 0;
163
+
164
+ @Debounce()
165
+ onClick() {
166
+ this.value++;
167
+ }
168
+
169
+ render() {
170
+ return (
171
+ <host onClick={this.onClick}>
172
+ Count is {this.value}
173
+ </host>
174
+ )
175
+ }
176
+ }
177
+ ```
178
+
179
+ In the `index.html` file.
180
+
181
+ ```html
182
+ <body dir="rtl">
183
+ <my-counter></my-counter>
184
+ </body>
185
+ ```
186
+
187
+ </details>
188
+
149
189
  <details>
150
190
  <summary>Direction</summary>
151
191
 
@@ -540,7 +580,7 @@ export class MyButton {
540
580
  @Query('.btn')
541
581
  buttonRef!: HTMLButtonElement;
542
582
 
543
- loadedCallback() {
583
+ readyCallback() {
544
584
  console.log(this.buttonRef); // <button class="btn"></button>
545
585
  }
546
586
 
@@ -587,7 +627,7 @@ export class MyButton {
587
627
  @QueryAll('span')
588
628
  spanRefs!: NodeList;
589
629
 
590
- loadedCallback() {
630
+ readyCallback() {
591
631
  console.log(this.spanRefs); // [span, span]
592
632
  }
593
633
 
@@ -897,7 +937,7 @@ TODO
897
937
  <details>
898
938
  <summary>connectedCallback</summary>
899
939
 
900
- A lifecycle callback method that is called each time the element is added to the document.
940
+ Invoked when an element is added to the document's DOM.
901
941
 
902
942
  ```js
903
943
  import { Element } from '@htmlplus/element';
@@ -915,7 +955,7 @@ export class MyElement {
915
955
  <details>
916
956
  <summary>disconnectedCallback</summary>
917
957
 
918
- TODO
958
+ Invoked when an element is removed from the document's DOM.
919
959
 
920
960
  ```js
921
961
  import { Element } from '@htmlplus/element';
@@ -931,17 +971,40 @@ export class MyElement {
931
971
  </details>
932
972
 
933
973
  <details>
934
- <summary>loadedCallback</summary>
974
+ <summary>prepareCallback</summary>
935
975
 
936
- TODO
976
+ This lifecycle is asynchronous and is invoked before all other lifecycles.
977
+
978
+ ```js
979
+ import { Element } from '@htmlplus/element';
980
+
981
+ @Element()
982
+ export class MyElement {
983
+ prepareCallback() {
984
+ return new Promise((resolve) => {
985
+ setTimeout(resolve, 2500);
986
+ })
987
+ }
988
+ connectedCallback() {
989
+ console.log('The element connects after 2500 milliseconds!');
990
+ }
991
+ }
992
+ ```
993
+
994
+ </details>
995
+
996
+ <details>
997
+ <summary>readyCallback</summary>
998
+
999
+ Invoked after the elements's DOM has been updated the first time, immediately before `updatedCallback` is called.
937
1000
 
938
1001
  ```js
939
1002
  import { Element } from '@htmlplus/element';
940
1003
 
941
1004
  @Element()
942
1005
  export class MyElement {
943
- loadedCallback() {
944
- console.log('Element is loaded!');
1006
+ readyCallback() {
1007
+ console.log('Element is ready!');
945
1008
  }
946
1009
  }
947
1010
  ```
@@ -951,14 +1014,42 @@ export class MyElement {
951
1014
  <details>
952
1015
  <summary>updateCallback</summary>
953
1016
 
954
- TODO
1017
+ Invoked before the element is rendered, this method receives a Map where keys represent the names of changed properties, and values hold their corresponding previous states. Modifying Properties/State within this method does not trigger an element update.
1018
+
1019
+ ```js
1020
+ import { Element, Property } from '@htmlplus/element';
1021
+
1022
+ @Element()
1023
+ export class MyElement {
1024
+ @Property()
1025
+ value?: number = 0;
1026
+
1027
+ updateCallback(changes) {
1028
+ console.log('Changed properties are: ', changes);
1029
+ }
1030
+ }
1031
+ ```
955
1032
 
956
1033
  </details>
957
1034
 
958
1035
  <details>
959
1036
  <summary>updatedCallback</summary>
960
1037
 
961
- TODO
1038
+ Invoked after the element is rendered, this method receives a Map where keys represent the names of changed properties, and values hold their corresponding previous states.
1039
+
1040
+ ```js
1041
+ import { Element, Property } from '@htmlplus/element';
1042
+
1043
+ @Element()
1044
+ export class MyElement {
1045
+ @Property()
1046
+ value?: number = 0;
1047
+
1048
+ updatedCallback(changes) {
1049
+ console.log('Changed properties are: ', changes);
1050
+ }
1051
+ }
1052
+ ```
962
1053
 
963
1054
  </details>
964
1055
 
@@ -1,21 +1,5 @@
1
- import { kebabCase, camelCase, pascalCase } from 'change-case';
2
- import { API_HOST, STATIC_TAG, API_STACKS, API_REQUEST, API_CONNECTED, LIFECYCLE_UPDATE, STATIC_STYLE, API_STYLE, LIFECYCLE_UPDATED, API_RENDER_COMPLETED, METHOD_RENDER, TYPE_BOOLEAN, TYPE_NUMBER, TYPE_NULL, TYPE_DATE, TYPE_ARRAY, TYPE_OBJECT, TYPE_UNDEFINED, LIFECYCLE_CONNECTED, LIFECYCLE_DISCONNECTED, KEY, API_INSTANCE, MAPPER, LIFECYCLE_CONSTRUCTED, LIFECYCLE_ADOPTED, LIFECYCLE_LOADED } from './constants.js';
3
-
4
- const appendToMethod = (target, key, handler) => {
5
- // Gets the previous function
6
- const previous = target[key];
7
- // Creates new function
8
- function next(...parameters) {
9
- // Calls the previous
10
- const result = previous?.bind(this)(...parameters);
11
- // Calls the appended
12
- handler.bind(this)(...parameters);
13
- // Returns the result
14
- return result;
15
- }
16
- // Replaces the next with the previous one
17
- target[key] = next;
18
- };
1
+ import { kebabCase, pascalCase } from 'change-case';
2
+ import { API_HOST, STATIC_TAG, API_STACKS, API_REQUEST, API_CONNECTED, LIFECYCLE_UPDATE, STATIC_STYLE, API_STYLE, LIFECYCLE_UPDATED, API_RENDER_COMPLETED, METHOD_RENDER, TYPE_BOOLEAN, TYPE_NUMBER, TYPE_NULL, TYPE_DATE, TYPE_ARRAY, TYPE_OBJECT, TYPE_UNDEFINED, LIFECYCLE_CONNECTED, LIFECYCLE_DISCONNECTED, KEY, LIFECYCLE_PREPARE, LIFECYCLE_CONSTRUCTED, LIFECYCLE_ADOPTED, LIFECYCLE_READY } from './constants.js';
19
3
 
20
4
  /**
21
5
  * Indicates the host of the element.
@@ -87,11 +71,12 @@ const toEvent = (input) => {
87
71
 
88
72
  const updateAttribute = (target, key, value) => {
89
73
  const element = host(target);
90
- const name = kebabCase(key);
91
74
  if ([undefined, null, false].includes(value)) {
92
- return element.removeAttribute(name);
75
+ element.removeAttribute(key);
76
+ }
77
+ else {
78
+ element.setAttribute(key, value === true ? '' : value);
93
79
  }
94
- element.setAttribute(name, value === true ? '' : value);
95
80
  };
96
81
 
97
82
  const symbol = Symbol();
@@ -118,13 +103,13 @@ const attributes$2 = (target, attributes) => {
118
103
  if (isEvent(key))
119
104
  on(element, toEvent(key), next[key]);
120
105
  else
121
- updateAttribute(element, key, next[key]);
106
+ updateAttribute(element, kebabCase(key), next[key]);
122
107
  }
123
108
  element[symbol] = { ...next };
124
109
  };
125
110
 
126
- const call = (target, key, ...parameters) => {
127
- return target[key]?.call(target, ...parameters);
111
+ const call = (target, key, ...args) => {
112
+ return target[key]?.apply(target, args);
128
113
  };
129
114
 
130
115
  const typeOf = (input) => {
@@ -1091,7 +1076,7 @@ tag('svg');
1091
1076
  * @param previous The previous value of Property/State.
1092
1077
  * @param callback Invoked when the rendering phase is completed.
1093
1078
  */
1094
- const request = (target, name, previous, callback) => {
1079
+ const requestUpdate = (target, name, previous, callback) => {
1095
1080
  // Creates/Gets a stacks.
1096
1081
  const stacks = (target[API_STACKS] ||= new Map());
1097
1082
  // Creates/Updates a stack.
@@ -1220,11 +1205,11 @@ const toCSSUnit = (input) => {
1220
1205
  }
1221
1206
  };
1222
1207
 
1223
- function toDecorator(util, ...parameters) {
1208
+ function toDecorator(util, ...args) {
1224
1209
  return function (target, key) {
1225
1210
  defineProperty(target, key, {
1226
1211
  get() {
1227
- return util(this, ...parameters);
1212
+ return util(this, ...args);
1228
1213
  }
1229
1214
  });
1230
1215
  };
@@ -1295,22 +1280,49 @@ const toUnit = (input, unit = 'px') => {
1295
1280
  return Number(input) + unit;
1296
1281
  };
1297
1282
 
1283
+ const wrapMethod = (mode, target, key, handler) => {
1284
+ // Gets the original function
1285
+ const original = target[key];
1286
+ // Validate target property
1287
+ if (original && typeof original !== 'function') {
1288
+ throw new TypeError(`Property ${String(key)} is not a function`);
1289
+ }
1290
+ // Creates new function
1291
+ function wrapped(...args) {
1292
+ // Calls the handler before the original
1293
+ if (mode == 'before') {
1294
+ handler.apply(this, args);
1295
+ }
1296
+ // Calls the original
1297
+ const result = original?.apply(this, args);
1298
+ // Calls the handler after the original
1299
+ if (mode == 'after') {
1300
+ handler.apply(this, args);
1301
+ }
1302
+ // Returns the result
1303
+ return result;
1304
+ }
1305
+ // Replaces the wrapped with the original one
1306
+ target[key] = wrapped;
1307
+ };
1308
+
1298
1309
  /**
1299
1310
  * Used to bind a method of a class to the current context,
1300
1311
  * making it easier to reference `this` within the method.
1301
1312
  */
1302
1313
  function Bind() {
1303
1314
  return function (target, key, descriptor) {
1315
+ const original = descriptor.value;
1304
1316
  return {
1305
1317
  configurable: true,
1306
1318
  get() {
1307
- const value = descriptor?.value.bind(this);
1319
+ const next = original.bind(this);
1308
1320
  defineProperty(this, key, {
1309
- value,
1321
+ value: next,
1310
1322
  configurable: true,
1311
1323
  writable: true
1312
1324
  });
1313
- return value;
1325
+ return next;
1314
1326
  }
1315
1327
  };
1316
1328
  };
@@ -1334,7 +1346,7 @@ function Provider(namespace) {
1334
1346
  dispatch(instance, `${prefix}:${instance[SUB]}:update`, options);
1335
1347
  };
1336
1348
  // TODO
1337
- appendToMethod(target, LIFECYCLE_CONNECTED, function () {
1349
+ wrapMethod('after', target, LIFECYCLE_CONNECTED, function () {
1338
1350
  const cleanup = () => {
1339
1351
  off(this, `${prefix}:presence`, onPresence);
1340
1352
  cleanups(this).delete(prefix);
@@ -1346,7 +1358,7 @@ function Provider(namespace) {
1346
1358
  on(this, `${prefix}:presence`, onPresence);
1347
1359
  cleanups(this).set(prefix, cleanup);
1348
1360
  });
1349
- appendToMethod(target, LIFECYCLE_UPDATE, function (states) {
1361
+ wrapMethod('after', target, LIFECYCLE_UPDATE, function (states) {
1350
1362
  update(this);
1351
1363
  if (cleanups(this).size && !states.has(SUB))
1352
1364
  return;
@@ -1363,7 +1375,7 @@ function Provider(namespace) {
1363
1375
  on(window, `${type}:presence`, onPresence);
1364
1376
  cleanups(this).set(type, cleanup);
1365
1377
  });
1366
- appendToMethod(target, LIFECYCLE_DISCONNECTED, function () {
1378
+ wrapMethod('after', target, LIFECYCLE_DISCONNECTED, function () {
1367
1379
  cleanups(this).forEach((cleanup) => cleanup());
1368
1380
  });
1369
1381
  };
@@ -1380,7 +1392,7 @@ function Consumer(namespace) {
1380
1392
  instance[key] = state;
1381
1393
  };
1382
1394
  // TODO
1383
- appendToMethod(target, LIFECYCLE_CONNECTED, function () {
1395
+ wrapMethod('after', target, LIFECYCLE_CONNECTED, function () {
1384
1396
  // TODO
1385
1397
  if (SUB && this[SUB])
1386
1398
  return;
@@ -1408,7 +1420,7 @@ function Consumer(namespace) {
1408
1420
  // TODO: When the `Provider` element is activated after the `Consumer` element.
1409
1421
  !connected && setTimeout(() => dispatch(this, `${prefix}:presence`, options));
1410
1422
  });
1411
- appendToMethod(target, LIFECYCLE_UPDATE, function (states) {
1423
+ wrapMethod('after', target, LIFECYCLE_UPDATE, function (states) {
1412
1424
  if (cleanups(this).size && !states.has(SUB))
1413
1425
  return;
1414
1426
  cleanups(this).get(`${prefix}:${states.get(SUB)}`)?.();
@@ -1430,12 +1442,41 @@ function Consumer(namespace) {
1430
1442
  cleanups(this).set(type, cleanup);
1431
1443
  dispatch(window, `${type}:presence`);
1432
1444
  });
1433
- appendToMethod(target, LIFECYCLE_DISCONNECTED, function () {
1445
+ wrapMethod('after', target, LIFECYCLE_DISCONNECTED, function () {
1434
1446
  cleanups(this).forEach((cleanup) => cleanup());
1435
1447
  });
1436
1448
  };
1437
1449
  }
1438
1450
 
1451
+ /**
1452
+ * A method decorator that applies debounce behavior to a class method.
1453
+ * Ensures that the method executes only after the specified delay,
1454
+ * resetting the timer if called again within the delay period.
1455
+ *
1456
+ * @param {number} delay - The debounce delay in milliseconds.
1457
+ */
1458
+ function Debounce(delay = 0) {
1459
+ return function (target, key, descriptor) {
1460
+ const KEY = Symbol();
1461
+ const original = descriptor.value;
1462
+ function clear() {
1463
+ if (!Object.hasOwn(this, KEY))
1464
+ return;
1465
+ clearTimeout(this[KEY]);
1466
+ delete this[KEY];
1467
+ }
1468
+ function debounced(...args) {
1469
+ clear.call(this);
1470
+ this[KEY] = window.setTimeout(() => {
1471
+ clear.call(this);
1472
+ original.apply(this, args);
1473
+ }, delay);
1474
+ }
1475
+ descriptor.value = debounced;
1476
+ return Bind()(target, key, descriptor);
1477
+ };
1478
+ }
1479
+
1439
1480
  /**
1440
1481
  * Indicates whether the [Direction](https://mdn.io/css-direction)
1441
1482
  * of the element is `Right-To-Left` or `Left-To-Right`.
@@ -1461,6 +1502,7 @@ function Element() {
1461
1502
  }
1462
1503
  const proxy = (constructor) => {
1463
1504
  return class Plus extends HTMLElement {
1505
+ #instance;
1464
1506
  static formAssociated = constructor['formAssociated'];
1465
1507
  static observedAttributes = constructor['observedAttributes'];
1466
1508
  constructor() {
@@ -1470,39 +1512,39 @@ const proxy = (constructor) => {
1470
1512
  delegatesFocus: constructor['delegatesFocus'],
1471
1513
  slotAssignment: constructor['slotAssignment']
1472
1514
  });
1473
- const instance = (this[API_INSTANCE] = new constructor());
1474
- instance[API_HOST] = () => this;
1475
- call(instance, LIFECYCLE_CONSTRUCTED);
1515
+ this.#instance = new constructor();
1516
+ this.#instance[API_HOST] = () => this;
1517
+ call(this.#instance, LIFECYCLE_CONSTRUCTED);
1476
1518
  }
1477
1519
  adoptedCallback() {
1478
- call(this[API_INSTANCE], LIFECYCLE_ADOPTED);
1520
+ call(this.#instance, LIFECYCLE_ADOPTED);
1479
1521
  }
1480
1522
  attributeChangedCallback(key, prev, next) {
1481
- // Ensures the integrity of readonly properties to prevent potential errors.
1482
- try {
1483
- const attribute = constructor[MAPPER]?.[key];
1484
- const property = attribute || camelCase(key);
1485
- this[property] = next;
1523
+ if (prev != next) {
1524
+ this.#instance['RAW:' + key] = next;
1486
1525
  }
1487
- catch { }
1488
1526
  }
1489
1527
  connectedCallback() {
1490
- const instance = this[API_INSTANCE];
1491
1528
  // TODO: experimental for global config
1492
- Object.assign(instance, getConfig('element', getTag(instance), 'property'));
1493
- instance[API_CONNECTED] = true;
1529
+ Object.assign(this.#instance, getConfig('element', getTag(this.#instance), 'property'));
1494
1530
  const connect = () => {
1495
- request(instance, undefined, undefined, () => {
1496
- call(instance, LIFECYCLE_LOADED);
1531
+ this.#instance[API_CONNECTED] = true;
1532
+ call(this.#instance, LIFECYCLE_CONNECTED);
1533
+ requestUpdate(this.#instance, undefined, undefined, () => {
1534
+ call(this.#instance, LIFECYCLE_READY);
1497
1535
  });
1498
1536
  };
1499
- const callback = call(instance, LIFECYCLE_CONNECTED);
1500
- if (!callback?.then)
1537
+ const hasPrepare = LIFECYCLE_PREPARE in this.#instance;
1538
+ if (!hasPrepare)
1501
1539
  return connect();
1502
- callback.then(() => connect());
1540
+ call(this.#instance, LIFECYCLE_PREPARE)
1541
+ .then(() => connect())
1542
+ .catch((error) => {
1543
+ throw new Error(`Failed to prepare <${getTag(this.#instance)}> element before connection.`, { cause: error });
1544
+ });
1503
1545
  }
1504
1546
  disconnectedCallback() {
1505
- call(this[API_INSTANCE], LIFECYCLE_DISCONNECTED);
1547
+ call(this.#instance, LIFECYCLE_DISCONNECTED);
1506
1548
  }
1507
1549
  };
1508
1550
  };
@@ -1515,47 +1557,43 @@ const proxy = (constructor) => {
1515
1557
  */
1516
1558
  function Event(options = {}) {
1517
1559
  return function (target, key) {
1518
- defineProperty(target, key, {
1519
- get() {
1520
- return (detail) => {
1521
- const element = host(this);
1522
- const framework = getFramework(this);
1523
- options.bubbles ??= false;
1524
- let type = String(key);
1525
- switch (framework) {
1526
- // TODO: Experimental
1527
- case 'blazor':
1528
- options.bubbles = true;
1529
- type = pascalCase(type);
1530
- try {
1531
- window['Blazor'].registerCustomEventType(type, {
1532
- createEventArgs: (event) => ({
1533
- detail: event.detail
1534
- })
1535
- });
1536
- }
1537
- catch { }
1538
- break;
1539
- case 'qwik':
1540
- case 'solid':
1541
- type = pascalCase(type).toLowerCase();
1542
- break;
1543
- case 'react':
1544
- case 'preact':
1545
- type = pascalCase(type);
1546
- break;
1547
- default:
1548
- type = kebabCase(type);
1549
- break;
1560
+ target[key] = function (detail) {
1561
+ const element = host(this);
1562
+ const framework = getFramework(this);
1563
+ options.bubbles ??= false;
1564
+ let type = String(key);
1565
+ switch (framework) {
1566
+ // TODO: Experimental
1567
+ case 'blazor':
1568
+ options.bubbles = true;
1569
+ type = pascalCase(type);
1570
+ try {
1571
+ window['Blazor'].registerCustomEventType(type, {
1572
+ createEventArgs: (event) => ({
1573
+ detail: event.detail
1574
+ })
1575
+ });
1550
1576
  }
1551
- let event;
1552
- event ||= getConfig('event', 'resolver')?.({ detail, element, framework, options, type });
1553
- event && element.dispatchEvent(event);
1554
- event ||= dispatch(this, type, { ...options, detail });
1555
- return event;
1556
- };
1577
+ catch { }
1578
+ break;
1579
+ case 'qwik':
1580
+ case 'solid':
1581
+ type = pascalCase(type).toLowerCase();
1582
+ break;
1583
+ case 'react':
1584
+ case 'preact':
1585
+ type = pascalCase(type);
1586
+ break;
1587
+ default:
1588
+ type = kebabCase(type);
1589
+ break;
1557
1590
  }
1558
- });
1591
+ let event;
1592
+ event ||= getConfig('event', 'resolver')?.({ detail, element, framework, options, type });
1593
+ event && element.dispatchEvent(event);
1594
+ event ||= dispatch(this, type, { ...options, detail });
1595
+ return event;
1596
+ };
1559
1597
  };
1560
1598
  }
1561
1599
 
@@ -1598,10 +1636,10 @@ function Listen(type, options) {
1598
1636
  return instance;
1599
1637
  }
1600
1638
  };
1601
- appendToMethod(target, LIFECYCLE_CONNECTED, function () {
1639
+ wrapMethod('before', target, LIFECYCLE_CONNECTED, function () {
1602
1640
  on(element(this), type, this[key], options);
1603
1641
  });
1604
- appendToMethod(target, LIFECYCLE_DISCONNECTED, function () {
1642
+ wrapMethod('before', target, LIFECYCLE_DISCONNECTED, function () {
1605
1643
  off(element(this), type, this[key], options);
1606
1644
  });
1607
1645
  return Bind()(target, key, descriptor);
@@ -1613,11 +1651,9 @@ function Listen(type, options) {
1613
1651
  * and invoke it as needed, both internally and externally.
1614
1652
  */
1615
1653
  function Method() {
1616
- return function (target, key) {
1617
- appendToMethod(target, LIFECYCLE_CONSTRUCTED, function () {
1618
- defineProperty(host(this), key, {
1619
- get: () => this[key].bind(this)
1620
- });
1654
+ return function (target, key, descriptor) {
1655
+ wrapMethod('before', target, LIFECYCLE_CONSTRUCTED, function () {
1656
+ host(this)[key] = this[key].bind(this);
1621
1657
  });
1622
1658
  };
1623
1659
  }
@@ -1628,89 +1664,110 @@ function Method() {
1628
1664
  */
1629
1665
  function Property(options) {
1630
1666
  return function (target, key, descriptor) {
1631
- // Creates a unique symbol for the lock flag.
1632
- const locked = Symbol();
1633
- // Converts property name to string.
1634
- const name = String(key);
1635
- // Calculates attribute.
1636
- const attribute = options?.attribute || kebabCase(name);
1637
- // Registers an attribute that is intricately linked to the property.
1667
+ // Unique symbol for property storage to avoid naming conflicts
1668
+ const KEY = Symbol();
1669
+ // Unique symbol for the lock flag to prevent infinite loops during updates
1670
+ const LOCKED = Symbol();
1671
+ // Calculate attribute name from the property key if not explicitly provided
1672
+ const attribute = options?.attribute || kebabCase(key);
1673
+ // Store the original setter (if it exists) to preserve its behavior
1674
+ const originalSetter = descriptor?.set;
1675
+ // Register the attribute in the observedAttributes array for the element
1638
1676
  (target.constructor['observedAttributes'] ||= []).push(attribute);
1639
- // TODO
1640
- if (attribute) {
1641
- // TODO
1642
- target.constructor[MAPPER] ||= {};
1643
- // TODO
1644
- target.constructor[MAPPER][attribute] = name;
1677
+ // Getter function to retrieve the property value
1678
+ function get() {
1679
+ return this[KEY];
1645
1680
  }
1646
- // TODO: This feature is an experimental
1647
- // When the property is a getter function.
1648
- if (descriptor) {
1649
- // Checks the reflection.
1650
- if (options?.reflect) {
1651
- // Stores the original getter function.
1652
- const getter = descriptor.get;
1653
- // Defines a new getter function.
1654
- descriptor.get = function () {
1655
- const value = getter?.apply(this);
1656
- this[locked] = true;
1657
- updateAttribute(this, attribute, value);
1658
- this[locked] = false;
1659
- return value;
1660
- };
1661
- // TODO: Check the lifecycle
1662
- appendToMethod(target, LIFECYCLE_UPDATED, function () {
1663
- // Calls the getter function to update the related attribute.
1664
- this[key];
1665
- });
1681
+ // Setter function to update the property value and trigger updates
1682
+ function set(value) {
1683
+ // Store the previous value
1684
+ const previous = this[KEY];
1685
+ // Store the new value
1686
+ const next = value;
1687
+ // Skip updates if the value hasn't changed and no custom setter is defined
1688
+ if (!originalSetter && next === previous)
1689
+ return;
1690
+ // If a custom setter exists, call it with the new value
1691
+ if (originalSetter) {
1692
+ originalSetter.call(this, next);
1666
1693
  }
1667
- }
1668
- // When the property is normal.
1669
- else {
1670
- // Creates a unique symbol.
1671
- const symbol = Symbol();
1672
- // Defines a getter function to use in the target class.
1673
- function get() {
1674
- return this[symbol];
1694
+ // Otherwise, update the property directly
1695
+ else {
1696
+ this[KEY] = next;
1675
1697
  }
1676
- // Defines a setter function to use in the target class.
1677
- function set(next) {
1678
- const previous = this[symbol];
1679
- if (next === previous)
1698
+ // Request an update
1699
+ requestUpdate(this, key, previous, (skipped) => {
1700
+ // Skip if the update was aborted
1701
+ if (skipped)
1680
1702
  return;
1681
- this[symbol] = next;
1682
- request(this, name, previous, (skipped) => {
1683
- if (skipped)
1684
- return;
1685
- if (!options?.reflect)
1686
- return;
1687
- this[locked] = true;
1688
- updateAttribute(this, attribute, next);
1689
- this[locked] = false;
1690
- });
1691
- }
1692
- // Attaches the getter and setter functions to the current property of the target class.
1693
- defineProperty(target, key, { get, set });
1703
+ // If reflection is enabled, update the corresponding attribute
1704
+ if (!options?.reflect)
1705
+ return;
1706
+ // Lock to prevent infinite loops
1707
+ this[LOCKED] = true;
1708
+ // Update the attribute
1709
+ updateAttribute(this, attribute, next);
1710
+ // Unlock
1711
+ this[LOCKED] = false;
1712
+ });
1694
1713
  }
1695
- // TODO: Check the lifecycle
1696
- appendToMethod(target, LIFECYCLE_CONSTRUCTED, function () {
1697
- // Defines a getter function to use in the host element.
1714
+ // Override the property descriptor if a custom setter exists
1715
+ if (originalSetter) {
1716
+ descriptor.set = set;
1717
+ }
1718
+ // Attach the getter and setter to the target class property if no descriptor exists
1719
+ if (!descriptor) {
1720
+ defineProperty(target, key, { configurable: true, get, set });
1721
+ }
1722
+ /**
1723
+ * Define a raw property setter to handle updates that trigger from the `attributeChangedCallback`,
1724
+ * To intercept and process raw attribute values before they are assigned to the property
1725
+ */
1726
+ defineProperty(target, 'RAW:' + attribute, {
1727
+ set(value) {
1728
+ if (!this[LOCKED]) {
1729
+ // Convert the raw value and set it to the corresponding property
1730
+ this[key] = toProperty(value, options?.type);
1731
+ }
1732
+ }
1733
+ });
1734
+ // Attach getter and setter to the host element on construction
1735
+ wrapMethod('before', target, LIFECYCLE_CONSTRUCTED, function () {
1698
1736
  const get = () => {
1737
+ if (descriptor && !descriptor.get) {
1738
+ throw new Error(`Property '${key}' does not have a getter. Unable to retrieve value.`);
1739
+ }
1699
1740
  return this[key];
1700
1741
  };
1701
- // Defines a setter function to use in the host element.
1702
- const set = descriptor
1703
- ? undefined
1704
- : (input) => {
1705
- if (this[locked]) {
1706
- return;
1707
- }
1708
- this[key] = toProperty(input, options?.type);
1709
- };
1710
- // TODO: Check the configuration.
1711
- // Attaches the getter and setter functions to the current property of the host element.
1712
- defineProperty(host(this), key, { get, set, configurable: true });
1742
+ const set = (value) => {
1743
+ if (descriptor && !descriptor.set) {
1744
+ throw new Error(`Property '${key}' does not have a setter. Unable to assign value.`);
1745
+ }
1746
+ this[key] = value;
1747
+ };
1748
+ defineProperty(host(this), key, { configurable: true, get, set });
1713
1749
  });
1750
+ /**
1751
+ * TODO: Review these behaviors again.
1752
+ *
1753
+ * When a property has a reflect and either a getter, a setter, or both are available,
1754
+ * three approaches are possible:
1755
+ *
1756
+ * 1. Only a getter is present: The attribute updates after each render is completed.
1757
+ * 2. Only a setter is present: The attribute updates after each setter call.
1758
+ * 3. Both getter and setter are present: The attribute is updated via the setter call
1759
+ * and also after each render is completed, resulting in two attribute update processes.
1760
+ */
1761
+ if (options?.reflect && descriptor?.get) {
1762
+ wrapMethod('before', target, LIFECYCLE_UPDATED, function () {
1763
+ // Lock to prevent infinite loops
1764
+ this[LOCKED] = true;
1765
+ // Update the attribute
1766
+ updateAttribute(this, attribute, this[key]);
1767
+ // Unlock
1768
+ this[LOCKED] = false;
1769
+ });
1770
+ }
1714
1771
  };
1715
1772
  }
1716
1773
 
@@ -1754,20 +1811,22 @@ function Slots() {
1754
1811
  */
1755
1812
  function State() {
1756
1813
  return function (target, key) {
1814
+ const KEY = Symbol();
1757
1815
  const name = String(key);
1758
- const symbol = Symbol();
1759
- function get() {
1760
- return this[symbol];
1761
- }
1762
- function set(next) {
1763
- const previous = this[symbol];
1764
- if (next === previous)
1765
- return;
1766
- this[symbol] = next;
1767
- request(this, name, previous);
1768
- }
1769
- // TODO: configurable
1770
- defineProperty(target, key, { get, set, configurable: true });
1816
+ defineProperty(target, key, {
1817
+ enumerable: true,
1818
+ configurable: true,
1819
+ get() {
1820
+ return this[KEY];
1821
+ },
1822
+ set(next) {
1823
+ const previous = this[KEY];
1824
+ if (next === previous)
1825
+ return;
1826
+ this[KEY] = next;
1827
+ requestUpdate(this, name, previous);
1828
+ }
1829
+ });
1771
1830
  };
1772
1831
  }
1773
1832
 
@@ -1776,7 +1835,7 @@ function Style() {
1776
1835
  return function (target, key) {
1777
1836
  const LAST = Symbol();
1778
1837
  const SHEET = Symbol();
1779
- appendToMethod(target, LIFECYCLE_UPDATED, function () {
1838
+ wrapMethod('before', target, LIFECYCLE_UPDATED, function () {
1780
1839
  let sheet = this[SHEET];
1781
1840
  let value = this[key];
1782
1841
  const update = (value) => (result) => {
@@ -1794,9 +1853,7 @@ function Style() {
1794
1853
  value = value.call(this);
1795
1854
  }
1796
1855
  if (value instanceof Promise) {
1797
- value
1798
- .then(update(this[LAST] = value))
1799
- .catch((error) => {
1856
+ value.then(update((this[LAST] = value))).catch((error) => {
1800
1857
  throw new Error('TODO', { cause: error });
1801
1858
  });
1802
1859
  }
@@ -1849,7 +1906,7 @@ function Watch(keys, immediate) {
1849
1906
  // Gets all keys
1850
1907
  const all = [keys].flat().filter((item) => item);
1851
1908
  // Registers a lifecycle to detect changes.
1852
- appendToMethod(target, LIFECYCLE_UPDATED, function (states) {
1909
+ wrapMethod('after', target, LIFECYCLE_UPDATED, function (states) {
1853
1910
  // Skips the logic if 'immediate' wasn't passed.
1854
1911
  if (!immediate && !this[API_RENDER_COMPLETED])
1855
1912
  return;
@@ -1869,4 +1926,4 @@ const attributes = attributes$2;
1869
1926
  const html = html$1;
1870
1927
  const styles = styles$1;
1871
1928
 
1872
- export { Bind as B, Consumer as C, Direction as D, Element as E, Host as H, IsRTL as I, Listen as L, Method as M, Provider as P, Query as Q, Slots as S, Watch as W, dispatch as a, toCSSUnit as b, classes as c, direction as d, isRTL as e, queryAll as f, getConfig as g, host as h, isCSSColor as i, off as j, toUnit as k, setConfig as l, Event as m, Property as n, on as o, QueryAll as p, query as q, State as r, slots as s, toCSSColor as t, Style as u, attributes as v, html as w, styles as x };
1929
+ export { Bind as B, Consumer as C, Debounce as D, Element as E, Host as H, IsRTL as I, Listen as L, Method as M, Provider as P, Query as Q, Slots as S, Watch as W, dispatch as a, toCSSUnit as b, classes as c, direction as d, isRTL as e, queryAll as f, getConfig as g, host as h, isCSSColor as i, off as j, toUnit as k, setConfig as l, Direction as m, Event as n, on as o, Property as p, query as q, QueryAll as r, slots as s, toCSSColor as t, State as u, Style as v, attributes as w, html as x, styles as y };
@@ -13,6 +13,18 @@ interface HTMLPlusElement {
13
13
  declare function Provider(namespace: string): (target: HTMLPlusElement, key: PropertyKey, descriptor: PropertyDescriptor) => void;
14
14
  declare function Consumer(namespace: string): (target: HTMLPlusElement, key: PropertyKey) => void;
15
15
 
16
+ /**
17
+ * A method decorator that applies debounce behavior to a class method.
18
+ * Ensures that the method executes only after the specified delay,
19
+ * resetting the timer if called again within the delay period.
20
+ *
21
+ * @param {number} delay - The debounce delay in milliseconds.
22
+ */
23
+ declare function Debounce(delay?: number): (target: Object, key: PropertyKey, descriptor: PropertyDescriptor) => {
24
+ configurable: boolean;
25
+ get(): any;
26
+ };
27
+
16
28
  /**
17
29
  * Indicates whether the [Direction](https://mdn.io/css-direction)
18
30
  * of the element is `Right-To-Left` or `Left-To-Right`.
@@ -127,7 +139,7 @@ declare function Listen(type: string, options?: ListenOptions): (target: HTMLPlu
127
139
  * Provides a way to encapsulate functionality within an element
128
140
  * and invoke it as needed, both internally and externally.
129
141
  */
130
- declare function Method(): (target: HTMLPlusElement, key: PropertyKey) => void;
142
+ declare function Method(): (target: HTMLPlusElement, key: PropertyKey, descriptor: PropertyDescriptor) => void;
131
143
 
132
144
  /**
133
145
  * The configuration for property decorator.
@@ -152,7 +164,7 @@ interface PropertyOptions {
152
164
  * Creates a reactive property, reflecting a corresponding attribute value,
153
165
  * and updates the element when the property is set.
154
166
  */
155
- declare function Property(options?: PropertyOptions): (target: HTMLPlusElement, key: PropertyKey, descriptor?: PropertyDescriptor) => void;
167
+ declare function Property(options?: PropertyOptions): (target: HTMLPlusElement, key: string, descriptor?: PropertyDescriptor) => void;
156
168
 
157
169
  /**
158
170
  * Selects the first element in the shadow dom that matches a specified CSS selector.
@@ -312,4 +324,4 @@ declare const attributes: any;
312
324
  declare const html: any;
313
325
  declare const styles: any;
314
326
 
315
- export { Style as A, Bind as B, type Config as C, Direction as D, Element$1 as E, attributes as F, html as G, Host as H, IsRTL as I, styles as J, type ListenOptions as L, Method as M, Provider as P, Query as Q, Slots$1 as S, Watch as W, dispatch as a, toCSSUnit as b, classes as c, direction as d, isRTL as e, queryAll as f, getConfig as g, host as h, isCSSColor as i, off as j, toUnit as k, setConfig as l, type ConfigOptions as m, Consumer as n, on as o, type EventEmitter as p, query as q, type EventOptions as r, slots as s, toCSSColor as t, Event as u, Listen as v, type PropertyOptions as w, Property as x, QueryAll as y, State as z };
327
+ export { State as A, Bind as B, type Config as C, Debounce as D, Element$1 as E, Style as F, attributes as G, Host as H, IsRTL as I, html as J, styles as K, type ListenOptions as L, Method as M, Provider as P, Query as Q, Slots$1 as S, Watch as W, type ConfigOptions as a, dispatch as b, classes as c, direction as d, toCSSUnit as e, isRTL as f, getConfig as g, host as h, isCSSColor as i, queryAll as j, off as k, toUnit as l, setConfig as m, Consumer as n, on as o, Direction as p, query as q, type EventEmitter as r, slots as s, toCSSColor as t, type EventOptions as u, Event as v, Listen as w, type PropertyOptions as x, Property as y, QueryAll as z };
package/dist/client.d.ts CHANGED
@@ -1 +1 @@
1
- export { B as Bind, C as Config, m as ConfigOptions, n as Consumer, D as Direction, E as Element, u as Event, p as EventEmitter, r as EventOptions, H as Host, I as IsRTL, v as Listen, L as ListenOptions, M as Method, x as Property, w as PropertyOptions, P as Provider, Q as Query, y as QueryAll, S as Slots, z as State, A as Style, W as Watch, c as classes, d as direction, a as dispatch, g as getConfig, h as host, i as isCSSColor, e as isRTL, j as off, o as on, q as query, f as queryAll, l as setConfig, s as slots, t as toCSSColor, b as toCSSUnit, k as toUnit } from './client-DdIyknz4.js';
1
+ export { B as Bind, C as Config, a as ConfigOptions, n as Consumer, D as Debounce, p as Direction, E as Element, v as Event, r as EventEmitter, u as EventOptions, H as Host, I as IsRTL, w as Listen, L as ListenOptions, M as Method, y as Property, x as PropertyOptions, P as Provider, Q as Query, z as QueryAll, S as Slots, A as State, F as Style, W as Watch, c as classes, d as direction, b as dispatch, g as getConfig, h as host, i as isCSSColor, f as isRTL, k as off, o as on, q as query, j as queryAll, m as setConfig, s as slots, t as toCSSColor, e as toCSSUnit, l as toUnit } from './client-JA8zqh-l.js';
package/dist/client.js CHANGED
@@ -1,3 +1,3 @@
1
- export { B as Bind, C as Consumer, D as Direction, E as Element, m as Event, H as Host, I as IsRTL, L as Listen, M as Method, n as Property, P as Provider, Q as Query, p as QueryAll, S as Slots, r as State, u as Style, W as Watch, c as classes, d as direction, a as dispatch, g as getConfig, h as host, i as isCSSColor, e as isRTL, j as off, o as on, q as query, f as queryAll, l as setConfig, s as slots, t as toCSSColor, b as toCSSUnit, k as toUnit } from './client-Cu3jtWIP.js';
1
+ export { B as Bind, C as Consumer, D as Debounce, m as Direction, E as Element, n as Event, H as Host, I as IsRTL, L as Listen, M as Method, p as Property, P as Provider, Q as Query, r as QueryAll, S as Slots, u as State, v as Style, W as Watch, c as classes, d as direction, a as dispatch, g as getConfig, h as host, i as isCSSColor, e as isRTL, j as off, o as on, q as query, f as queryAll, l as setConfig, s as slots, t as toCSSColor, b as toCSSUnit, k as toUnit } from './client-DgXF8gQw.js';
2
2
  import 'change-case';
3
3
  import './constants.js';
@@ -1,9 +1,7 @@
1
1
  declare const KEY = "htmlplus";
2
2
  declare const PACKAGE_NAME = "@htmlplus/element";
3
- declare const MAPPER: unique symbol;
4
3
  declare const API_CONNECTED: unique symbol;
5
4
  declare const API_HOST: unique symbol;
6
- declare const API_INSTANCE: unique symbol;
7
5
  declare const API_REQUEST: unique symbol;
8
6
  declare const API_RENDER_COMPLETED: unique symbol;
9
7
  declare const API_STACKS: unique symbol;
@@ -21,7 +19,8 @@ declare const LIFECYCLE_ADOPTED = "adoptedCallback";
21
19
  declare const LIFECYCLE_CONNECTED = "connectedCallback";
22
20
  declare const LIFECYCLE_CONSTRUCTED = "constructedCallback";
23
21
  declare const LIFECYCLE_DISCONNECTED = "disconnectedCallback";
24
- declare const LIFECYCLE_LOADED = "loadedCallback";
22
+ declare const LIFECYCLE_READY = "readyCallback";
23
+ declare const LIFECYCLE_PREPARE = "prepareCallback";
25
24
  declare const LIFECYCLE_UPDATE = "updateCallback";
26
25
  declare const LIFECYCLE_UPDATED = "updatedCallback";
27
26
  declare const METHOD_RENDER = "render";
@@ -47,4 +46,4 @@ declare const UTILS_STYLES_IMPORTED = "styles";
47
46
  declare const UTILS_STYLES_LOCAL = "UTILS_STYLES";
48
47
  declare const UTILS_PATH = "@htmlplus/element/internal.js";
49
48
 
50
- export { API_CONNECTED, API_HOST, API_INSTANCE, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_LOADED, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, MAPPER, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
49
+ export { API_CONNECTED, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_PREPARE, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
package/dist/constants.js CHANGED
@@ -1,11 +1,8 @@
1
1
  const KEY = 'htmlplus';
2
2
  const PACKAGE_NAME = '@htmlplus/element';
3
- // TODO
4
- const MAPPER = Symbol();
5
3
  // APIs
6
4
  const API_CONNECTED = Symbol();
7
5
  const API_HOST = Symbol();
8
- const API_INSTANCE = Symbol();
9
6
  const API_REQUEST = Symbol();
10
7
  const API_RENDER_COMPLETED = Symbol();
11
8
  const API_STACKS = Symbol();
@@ -28,7 +25,8 @@ const LIFECYCLE_ADOPTED = 'adoptedCallback';
28
25
  const LIFECYCLE_CONNECTED = 'connectedCallback';
29
26
  const LIFECYCLE_CONSTRUCTED = 'constructedCallback';
30
27
  const LIFECYCLE_DISCONNECTED = 'disconnectedCallback';
31
- const LIFECYCLE_LOADED = 'loadedCallback';
28
+ const LIFECYCLE_READY = 'readyCallback';
29
+ const LIFECYCLE_PREPARE = 'prepareCallback';
32
30
  const LIFECYCLE_UPDATE = 'updateCallback';
33
31
  const LIFECYCLE_UPDATED = 'updatedCallback';
34
32
  // methods
@@ -59,4 +57,4 @@ const UTILS_STYLES_IMPORTED = 'styles';
59
57
  const UTILS_STYLES_LOCAL = 'UTILS_STYLES';
60
58
  const UTILS_PATH = '@htmlplus/element/internal.js';
61
59
 
62
- export { API_CONNECTED, API_HOST, API_INSTANCE, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_LOADED, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, MAPPER, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
60
+ export { API_CONNECTED, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_PREPARE, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
@@ -1 +1 @@
1
- export { F as attributes, G as html, J as styles } from './client-DdIyknz4.js';
1
+ export { G as attributes, J as html, K as styles } from './client-JA8zqh-l.js';
package/dist/internal.js CHANGED
@@ -1,3 +1,3 @@
1
- export { v as attributes, w as html, x as styles } from './client-Cu3jtWIP.js';
1
+ export { w as attributes, x as html, y as styles } from './client-DgXF8gQw.js';
2
2
  import 'change-case';
3
3
  import './constants.js';
@@ -1,6 +1,8 @@
1
1
  import 'react';
2
2
 
3
- type WithPart<K extends keyof React.JSX.IntrinsicElements> = React.JSX.IntrinsicElements[K] & { part?: string };
3
+ type WithPart<K extends keyof React.JSX.IntrinsicElements> = React.JSX.IntrinsicElements[K] & {
4
+ part?: string;
5
+ };
4
6
 
5
7
  declare namespace JSX {
6
8
  interface IntrinsicElements {
@@ -461,6 +461,10 @@ const customElement = (options) => {
461
461
  name.name = '.' + name.name;
462
462
  return;
463
463
  }
464
+ if (name.name == 'disabled') {
465
+ name.name = '.' + name.name;
466
+ return;
467
+ }
464
468
  const key = ['tabIndex', 'viewBox'];
465
469
  if (!key.includes(name.name))
466
470
  return;
@@ -512,9 +516,7 @@ const customElement = (options) => {
512
516
  return attribute.type == 'JSXSpreadAttribute';
513
517
  });
514
518
  if (hasSpreadAttribute) {
515
- parts.push(' ', 'ref=', t.arrowFunctionExpression([
516
- t.identifier('$element')
517
- ], TODO(t.identifier('$element'), attributes)));
519
+ parts.push(' ', 'ref=', t.arrowFunctionExpression([t.identifier('$element')], TODO(t.identifier('$element'), attributes)));
518
520
  }
519
521
  else {
520
522
  for (const attribute of attributes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlplus/element",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "author": "Masood Abdolian <m.abdolian@gmail.com>",