@zeus-js/runtime-dom 0.1.0-beta.0 → 0.1.0-beta.2

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * runtime-dom v0.1.0-beta.0
2
+ * runtime-dom v0.1.0-beta.2
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -324,17 +324,43 @@ function stringifyText(value) {
324
324
  return String(value);
325
325
  }
326
326
  function setAttr(el, name, value) {
327
+ const attrName = normalizeAttrName(name);
328
+ const propName = getBooleanDomPropertyName(name);
329
+ if (propName && el instanceof HTMLElement) {
330
+ el[propName] = Boolean(value);
331
+ if (value == null || value === false) el.removeAttribute(attrName);
332
+ else if (value === true) el.setAttribute(attrName, "");
333
+ else el.setAttribute(attrName, String(value));
334
+ return;
335
+ }
327
336
  if (value == null || value === false) {
328
- el.removeAttribute(normalizeAttrName(name));
337
+ el.removeAttribute(attrName);
329
338
  return;
330
339
  }
331
- const attrName = normalizeAttrName(name);
332
340
  if (value === true) {
333
341
  el.setAttribute(attrName, "");
334
342
  return;
335
343
  }
336
344
  el.setAttribute(attrName, String(value));
337
345
  }
346
+ function getBooleanDomPropertyName(name) {
347
+ return BOOLEAN_DOM_PROPERTY_NAME[name];
348
+ }
349
+ const BOOLEAN_DOM_PROPERTY_NAME = {
350
+ hidden: "hidden",
351
+ disabled: "disabled",
352
+ readonly: "readOnly",
353
+ readOnly: "readOnly",
354
+ multiple: "multiple",
355
+ selected: "selected",
356
+ checked: "checked",
357
+ open: "open",
358
+ autofocus: "autofocus",
359
+ autoFocus: "autofocus",
360
+ indeterminate: "indeterminate",
361
+ noValidate: "noValidate",
362
+ novalidate: "noValidate"
363
+ };
338
364
  function normalizeAttrName(name) {
339
365
  return name === "className" ? "class" : name;
340
366
  }
@@ -606,6 +632,42 @@ function mountFor(parent, marker, each, key, render) {
606
632
  }
607
633
  //#endregion
608
634
  //#region packages/core/runtime-dom/src/defineElement.ts
635
+ function createPropStore(defs) {
636
+ const slots = /* @__PURE__ */ new Map();
637
+ const props = {};
638
+ for (const def of defs) {
639
+ const slot = (0, _zeus_js_signal.state)();
640
+ slots.set(def.key, slot);
641
+ Object.defineProperty(props, def.key, {
642
+ configurable: false,
643
+ enumerable: true,
644
+ get() {
645
+ return slot.value;
646
+ },
647
+ set(value) {
648
+ slot.value = value;
649
+ }
650
+ });
651
+ }
652
+ return {
653
+ props,
654
+ get(key) {
655
+ var _slots$get;
656
+ return (_slots$get = slots.get(key)) === null || _slots$get === void 0 ? void 0 : _slots$get.value;
657
+ },
658
+ set(key, value) {
659
+ const slot = slots.get(key);
660
+ if (!slot) {
661
+ console.warn(`[Zeus custom-element] Unknown prop "${key}" was written.`);
662
+ return;
663
+ }
664
+ slot.value = value;
665
+ },
666
+ has(key) {
667
+ return slots.has(key);
668
+ }
669
+ };
670
+ }
609
671
  function defineElement(tagName, options, setup) {
610
672
  var _options$props;
611
673
  const propDefs = normalizePropDefinitions((_options$props = options.props) !== null && _options$props !== void 0 ? _options$props : {});
@@ -616,12 +678,13 @@ function defineElement(tagName, options, setup) {
616
678
  }
617
679
  constructor() {
618
680
  super();
619
- this.props = (0, _zeus_js_signal.state)({});
620
681
  this.lightChildren = [];
621
682
  this.capturedLightChildren = false;
622
683
  this.reflecting = false;
623
- applyPropDefaults(this.props, propDefs);
624
- definePropAccessors(this, this.props, propDefs);
684
+ this.propStore = createPropStore(propDefs);
685
+ this.props = this.propStore.props;
686
+ applyPropDefaults(this.propStore, propDefs);
687
+ definePropAccessors(this, this.propStore, propDefs);
625
688
  }
626
689
  connectedCallback() {
627
690
  var _options$shadow, _options$consumes;
@@ -669,7 +732,7 @@ function defineElement(tagName, options, setup) {
669
732
  if (oldValue === newValue || this.reflecting) return;
670
733
  const def = propDefs.find((item) => item.attr === name);
671
734
  if (!def) return;
672
- this.props[def.key] = castAttributeValue(newValue, def);
735
+ this.propStore.set(def.key, castAttributeValue(newValue, def));
673
736
  }
674
737
  resolveRenderTarget(shadow) {
675
738
  if (this.target) return this.target;
@@ -684,12 +747,12 @@ function defineElement(tagName, options, setup) {
684
747
  for (const def of defs) {
685
748
  if (def.attr === false) continue;
686
749
  const value = this.getAttribute(def.attr);
687
- if (value !== null || def.type === Boolean) this.props[def.key] = castAttributeValue(value, def);
750
+ if (value !== null || def.type === Boolean) this.propStore.set(def.key, castAttributeValue(value, def));
688
751
  }
689
752
  }
690
753
  _writePropFromProperty(key, value) {
691
754
  const def = propDefs.find((item) => item.key === key);
692
- this.props[key] = value;
755
+ this.propStore.set(key, value);
693
756
  if ((def === null || def === void 0 ? void 0 : def.reflect) && def.attr !== false) {
694
757
  this.reflecting = true;
695
758
  try {
@@ -721,26 +784,35 @@ function normalizePropDefinitions(props) {
721
784
  };
722
785
  });
723
786
  }
724
- function applyPropDefaults(props, defs) {
787
+ function applyPropDefaults(store, defs) {
725
788
  for (const def of defs) {
726
789
  if (!("default" in def)) continue;
727
790
  const value = typeof def.default === "function" ? def.default() : def.default;
728
- props[def.key] = value;
791
+ store.set(def.key, value);
729
792
  }
730
793
  }
731
- function definePropAccessors(element, props, defs) {
794
+ function definePropAccessors(element, store, defs) {
732
795
  for (const def of defs) {
733
- if (def.key in element) continue;
734
- Object.defineProperty(element, def.key, {
796
+ const key = def.key;
797
+ const hadOwnValue = Object.prototype.hasOwnProperty.call(element, key);
798
+ const ownValue = hadOwnValue ? element[key] : void 0;
799
+ if (hadOwnValue) delete element[key];
800
+ const existing = Object.getOwnPropertyDescriptor(element, key);
801
+ if (existing && existing.configurable === false) {
802
+ console.warn(`[Zeus custom-element] Cannot define prop "${key}" because an own non-configurable property already exists.`);
803
+ continue;
804
+ }
805
+ Object.defineProperty(element, key, {
735
806
  configurable: true,
736
807
  enumerable: true,
737
808
  get() {
738
- return props[def.key];
809
+ return store.get(key);
739
810
  },
740
811
  set(value) {
741
- element._writePropFromProperty(def.key, value);
812
+ element._writePropFromProperty(key, value);
742
813
  }
743
814
  });
815
+ if (hadOwnValue) element._writePropFromProperty(key, ownValue);
744
816
  }
745
817
  }
746
818
  function castAttributeValue(value, def) {
@@ -823,7 +895,8 @@ const HOST_RESERVED_KEYS = new Set([
823
895
  "ref",
824
896
  "class",
825
897
  "className",
826
- "style"
898
+ "style",
899
+ "_elements"
827
900
  ]);
828
901
  function Host(props) {
829
902
  const context = getCurrentHostContext();
@@ -838,6 +911,7 @@ function bindHostProps(host, props) {
838
911
  bindHostClass(host, props);
839
912
  bindHostStyle(host, props);
840
913
  bindHostAttributes(host, props);
914
+ if ("_elements" in props) bindHostElementBindings(host, props);
841
915
  }
842
916
  function bindHostRef(host, props) {
843
917
  if (!("ref" in props)) return;
@@ -845,9 +919,6 @@ function bindHostRef(host, props) {
845
919
  }
846
920
  function bindHostClass(host, props) {
847
921
  if (!("class" in props) && !("className" in props)) return;
848
- /**
849
- * className has higher priority than class when both exist.
850
- */
851
922
  const value = props.className !== void 0 ? props.className : props.class;
852
923
  bindClass(host, () => {
853
924
  return resolveHostValue(value);
@@ -869,13 +940,25 @@ function bindHostAttributes(host, props) {
869
940
  });
870
941
  }
871
942
  }
943
+ function bindHostElementBindings(host, props) {
944
+ const elements = props._elements;
945
+ for (const _key of Object.keys(elements)) {
946
+ const getEl = elements[_key];
947
+ const el = getEl();
948
+ if (!el) continue;
949
+ for (const attrKey of Object.keys(props)) {
950
+ if (HOST_RESERVED_KEYS.has(attrKey)) continue;
951
+ if (isEventLikeProp(attrKey)) continue;
952
+ const value = props[attrKey];
953
+ bindAttr(el, normalizeHostAttrName(attrKey), () => {
954
+ return resolveHostValue(value);
955
+ });
956
+ }
957
+ }
958
+ }
872
959
  function resolveHostValue(value) {
873
- /**
874
- * JSX component props may be direct values or lazy getters.
875
- * Function values are treated as getters except event-like props,
876
- * which are filtered before this function is called.
877
- */
878
- return typeof value === "function" ? value() : value;
960
+ if (typeof value === "function") return value();
961
+ return value;
879
962
  }
880
963
  function resolveValue$1(value) {
881
964
  return typeof value === "function" ? value() : value;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * runtime-dom v0.1.0-beta.0
2
+ * runtime-dom v0.1.0-beta.2
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -318,17 +318,43 @@ function stringifyText(value) {
318
318
  return String(value);
319
319
  }
320
320
  function setAttr(el, name, value) {
321
+ const attrName = normalizeAttrName(name);
322
+ const propName = getBooleanDomPropertyName(name);
323
+ if (propName && el instanceof HTMLElement) {
324
+ el[propName] = Boolean(value);
325
+ if (value == null || value === false) el.removeAttribute(attrName);
326
+ else if (value === true) el.setAttribute(attrName, "");
327
+ else el.setAttribute(attrName, String(value));
328
+ return;
329
+ }
321
330
  if (value == null || value === false) {
322
- el.removeAttribute(normalizeAttrName(name));
331
+ el.removeAttribute(attrName);
323
332
  return;
324
333
  }
325
- const attrName = normalizeAttrName(name);
326
334
  if (value === true) {
327
335
  el.setAttribute(attrName, "");
328
336
  return;
329
337
  }
330
338
  el.setAttribute(attrName, String(value));
331
339
  }
340
+ function getBooleanDomPropertyName(name) {
341
+ return BOOLEAN_DOM_PROPERTY_NAME[name];
342
+ }
343
+ const BOOLEAN_DOM_PROPERTY_NAME = {
344
+ hidden: "hidden",
345
+ disabled: "disabled",
346
+ readonly: "readOnly",
347
+ readOnly: "readOnly",
348
+ multiple: "multiple",
349
+ selected: "selected",
350
+ checked: "checked",
351
+ open: "open",
352
+ autofocus: "autofocus",
353
+ autoFocus: "autofocus",
354
+ indeterminate: "indeterminate",
355
+ noValidate: "noValidate",
356
+ novalidate: "noValidate"
357
+ };
332
358
  function normalizeAttrName(name) {
333
359
  return name === "className" ? "class" : name;
334
360
  }
@@ -599,6 +625,39 @@ function mountFor(parent, marker, each, key, render) {
599
625
  }
600
626
  //#endregion
601
627
  //#region packages/core/runtime-dom/src/defineElement.ts
628
+ function createPropStore(defs) {
629
+ const slots = /* @__PURE__ */ new Map();
630
+ const props = {};
631
+ for (const def of defs) {
632
+ const slot = (0, _zeus_js_signal.state)();
633
+ slots.set(def.key, slot);
634
+ Object.defineProperty(props, def.key, {
635
+ configurable: false,
636
+ enumerable: true,
637
+ get() {
638
+ return slot.value;
639
+ },
640
+ set(value) {
641
+ slot.value = value;
642
+ }
643
+ });
644
+ }
645
+ return {
646
+ props,
647
+ get(key) {
648
+ var _slots$get;
649
+ return (_slots$get = slots.get(key)) === null || _slots$get === void 0 ? void 0 : _slots$get.value;
650
+ },
651
+ set(key, value) {
652
+ const slot = slots.get(key);
653
+ if (!slot) return;
654
+ slot.value = value;
655
+ },
656
+ has(key) {
657
+ return slots.has(key);
658
+ }
659
+ };
660
+ }
602
661
  function defineElement(tagName, options, setup) {
603
662
  var _options$props;
604
663
  const propDefs = normalizePropDefinitions((_options$props = options.props) !== null && _options$props !== void 0 ? _options$props : {});
@@ -609,12 +668,13 @@ function defineElement(tagName, options, setup) {
609
668
  }
610
669
  constructor() {
611
670
  super();
612
- this.props = (0, _zeus_js_signal.state)({});
613
671
  this.lightChildren = [];
614
672
  this.capturedLightChildren = false;
615
673
  this.reflecting = false;
616
- applyPropDefaults(this.props, propDefs);
617
- definePropAccessors(this, this.props, propDefs);
674
+ this.propStore = createPropStore(propDefs);
675
+ this.props = this.propStore.props;
676
+ applyPropDefaults(this.propStore, propDefs);
677
+ definePropAccessors(this, this.propStore, propDefs);
618
678
  }
619
679
  connectedCallback() {
620
680
  var _options$shadow, _options$consumes;
@@ -662,7 +722,7 @@ function defineElement(tagName, options, setup) {
662
722
  if (oldValue === newValue || this.reflecting) return;
663
723
  const def = propDefs.find((item) => item.attr === name);
664
724
  if (!def) return;
665
- this.props[def.key] = castAttributeValue(newValue, def);
725
+ this.propStore.set(def.key, castAttributeValue(newValue, def));
666
726
  }
667
727
  resolveRenderTarget(shadow) {
668
728
  if (this.target) return this.target;
@@ -677,12 +737,12 @@ function defineElement(tagName, options, setup) {
677
737
  for (const def of defs) {
678
738
  if (def.attr === false) continue;
679
739
  const value = this.getAttribute(def.attr);
680
- if (value !== null || def.type === Boolean) this.props[def.key] = castAttributeValue(value, def);
740
+ if (value !== null || def.type === Boolean) this.propStore.set(def.key, castAttributeValue(value, def));
681
741
  }
682
742
  }
683
743
  _writePropFromProperty(key, value) {
684
744
  const def = propDefs.find((item) => item.key === key);
685
- this.props[key] = value;
745
+ this.propStore.set(key, value);
686
746
  if ((def === null || def === void 0 ? void 0 : def.reflect) && def.attr !== false) {
687
747
  this.reflecting = true;
688
748
  try {
@@ -714,26 +774,32 @@ function normalizePropDefinitions(props) {
714
774
  };
715
775
  });
716
776
  }
717
- function applyPropDefaults(props, defs) {
777
+ function applyPropDefaults(store, defs) {
718
778
  for (const def of defs) {
719
779
  if (!("default" in def)) continue;
720
780
  const value = typeof def.default === "function" ? def.default() : def.default;
721
- props[def.key] = value;
781
+ store.set(def.key, value);
722
782
  }
723
783
  }
724
- function definePropAccessors(element, props, defs) {
784
+ function definePropAccessors(element, store, defs) {
725
785
  for (const def of defs) {
726
- if (def.key in element) continue;
727
- Object.defineProperty(element, def.key, {
786
+ const key = def.key;
787
+ const hadOwnValue = Object.prototype.hasOwnProperty.call(element, key);
788
+ const ownValue = hadOwnValue ? element[key] : void 0;
789
+ if (hadOwnValue) delete element[key];
790
+ const existing = Object.getOwnPropertyDescriptor(element, key);
791
+ if (existing && existing.configurable === false) continue;
792
+ Object.defineProperty(element, key, {
728
793
  configurable: true,
729
794
  enumerable: true,
730
795
  get() {
731
- return props[def.key];
796
+ return store.get(key);
732
797
  },
733
798
  set(value) {
734
- element._writePropFromProperty(def.key, value);
799
+ element._writePropFromProperty(key, value);
735
800
  }
736
801
  });
802
+ if (hadOwnValue) element._writePropFromProperty(key, ownValue);
737
803
  }
738
804
  }
739
805
  function castAttributeValue(value, def) {
@@ -815,7 +881,8 @@ const HOST_RESERVED_KEYS = new Set([
815
881
  "ref",
816
882
  "class",
817
883
  "className",
818
- "style"
884
+ "style",
885
+ "_elements"
819
886
  ]);
820
887
  function Host(props) {
821
888
  const context = getCurrentHostContext();
@@ -830,6 +897,7 @@ function bindHostProps(host, props) {
830
897
  bindHostClass(host, props);
831
898
  bindHostStyle(host, props);
832
899
  bindHostAttributes(host, props);
900
+ if ("_elements" in props) bindHostElementBindings(host, props);
833
901
  }
834
902
  function bindHostRef(host, props) {
835
903
  if (!("ref" in props)) return;
@@ -837,9 +905,6 @@ function bindHostRef(host, props) {
837
905
  }
838
906
  function bindHostClass(host, props) {
839
907
  if (!("class" in props) && !("className" in props)) return;
840
- /**
841
- * className has higher priority than class when both exist.
842
- */
843
908
  const value = props.className !== void 0 ? props.className : props.class;
844
909
  bindClass(host, () => {
845
910
  return resolveHostValue(value);
@@ -861,13 +926,25 @@ function bindHostAttributes(host, props) {
861
926
  });
862
927
  }
863
928
  }
929
+ function bindHostElementBindings(host, props) {
930
+ const elements = props._elements;
931
+ for (const _key of Object.keys(elements)) {
932
+ const getEl = elements[_key];
933
+ const el = getEl();
934
+ if (!el) continue;
935
+ for (const attrKey of Object.keys(props)) {
936
+ if (HOST_RESERVED_KEYS.has(attrKey)) continue;
937
+ if (isEventLikeProp(attrKey)) continue;
938
+ const value = props[attrKey];
939
+ bindAttr(el, normalizeHostAttrName(attrKey), () => {
940
+ return resolveHostValue(value);
941
+ });
942
+ }
943
+ }
944
+ }
864
945
  function resolveHostValue(value) {
865
- /**
866
- * JSX component props may be direct values or lazy getters.
867
- * Function values are treated as getters except event-like props,
868
- * which are filtered before this function is called.
869
- */
870
- return typeof value === "function" ? value() : value;
946
+ if (typeof value === "function") return value();
947
+ return value;
871
948
  }
872
949
  function resolveValue$1(value) {
873
950
  return typeof value === "function" ? value() : value;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * runtime-dom v0.1.0-beta.0
2
+ * runtime-dom v0.1.0-beta.2
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -1672,17 +1672,43 @@ function stringifyText(value) {
1672
1672
  return String(value);
1673
1673
  }
1674
1674
  function setAttr(el, name, value) {
1675
+ const attrName = normalizeAttrName(name);
1676
+ const propName = getBooleanDomPropertyName(name);
1677
+ if (propName && el instanceof HTMLElement) {
1678
+ el[propName] = Boolean(value);
1679
+ if (value == null || value === false) el.removeAttribute(attrName);
1680
+ else if (value === true) el.setAttribute(attrName, "");
1681
+ else el.setAttribute(attrName, String(value));
1682
+ return;
1683
+ }
1675
1684
  if (value == null || value === false) {
1676
- el.removeAttribute(normalizeAttrName(name));
1685
+ el.removeAttribute(attrName);
1677
1686
  return;
1678
1687
  }
1679
- const attrName = normalizeAttrName(name);
1680
1688
  if (value === true) {
1681
1689
  el.setAttribute(attrName, "");
1682
1690
  return;
1683
1691
  }
1684
1692
  el.setAttribute(attrName, String(value));
1685
1693
  }
1694
+ function getBooleanDomPropertyName(name) {
1695
+ return BOOLEAN_DOM_PROPERTY_NAME[name];
1696
+ }
1697
+ const BOOLEAN_DOM_PROPERTY_NAME = {
1698
+ hidden: "hidden",
1699
+ disabled: "disabled",
1700
+ readonly: "readOnly",
1701
+ readOnly: "readOnly",
1702
+ multiple: "multiple",
1703
+ selected: "selected",
1704
+ checked: "checked",
1705
+ open: "open",
1706
+ autofocus: "autofocus",
1707
+ autoFocus: "autofocus",
1708
+ indeterminate: "indeterminate",
1709
+ noValidate: "noValidate",
1710
+ novalidate: "noValidate"
1711
+ };
1686
1712
  function normalizeAttrName(name) {
1687
1713
  return name === "className" ? "class" : name;
1688
1714
  }
@@ -2015,6 +2041,42 @@ function _objectSpread2(e) {
2015
2041
  }
2016
2042
  //#endregion
2017
2043
  //#region packages/core/runtime-dom/src/defineElement.ts
2044
+ function createPropStore(defs) {
2045
+ const slots = /* @__PURE__ */ new Map();
2046
+ const props = {};
2047
+ for (const def of defs) {
2048
+ const slot = state();
2049
+ slots.set(def.key, slot);
2050
+ Object.defineProperty(props, def.key, {
2051
+ configurable: false,
2052
+ enumerable: true,
2053
+ get() {
2054
+ return slot.value;
2055
+ },
2056
+ set(value) {
2057
+ slot.value = value;
2058
+ }
2059
+ });
2060
+ }
2061
+ return {
2062
+ props,
2063
+ get(key) {
2064
+ var _slots$get;
2065
+ return (_slots$get = slots.get(key)) === null || _slots$get === void 0 ? void 0 : _slots$get.value;
2066
+ },
2067
+ set(key, value) {
2068
+ const slot = slots.get(key);
2069
+ if (!slot) {
2070
+ console.warn(`[Zeus custom-element] Unknown prop "${key}" was written.`);
2071
+ return;
2072
+ }
2073
+ slot.value = value;
2074
+ },
2075
+ has(key) {
2076
+ return slots.has(key);
2077
+ }
2078
+ };
2079
+ }
2018
2080
  function defineElement(tagName, options, setup) {
2019
2081
  var _options$props;
2020
2082
  const propDefs = normalizePropDefinitions((_options$props = options.props) !== null && _options$props !== void 0 ? _options$props : {});
@@ -2025,12 +2087,13 @@ function defineElement(tagName, options, setup) {
2025
2087
  }
2026
2088
  constructor() {
2027
2089
  super();
2028
- this.props = state({});
2029
2090
  this.lightChildren = [];
2030
2091
  this.capturedLightChildren = false;
2031
2092
  this.reflecting = false;
2032
- applyPropDefaults(this.props, propDefs);
2033
- definePropAccessors(this, this.props, propDefs);
2093
+ this.propStore = createPropStore(propDefs);
2094
+ this.props = this.propStore.props;
2095
+ applyPropDefaults(this.propStore, propDefs);
2096
+ definePropAccessors(this, this.propStore, propDefs);
2034
2097
  }
2035
2098
  connectedCallback() {
2036
2099
  var _options$shadow, _options$consumes;
@@ -2076,7 +2139,7 @@ function defineElement(tagName, options, setup) {
2076
2139
  if (oldValue === newValue || this.reflecting) return;
2077
2140
  const def = propDefs.find((item) => item.attr === name);
2078
2141
  if (!def) return;
2079
- this.props[def.key] = castAttributeValue(newValue, def);
2142
+ this.propStore.set(def.key, castAttributeValue(newValue, def));
2080
2143
  }
2081
2144
  resolveRenderTarget(shadow) {
2082
2145
  if (this.target) return this.target;
@@ -2091,12 +2154,12 @@ function defineElement(tagName, options, setup) {
2091
2154
  for (const def of defs) {
2092
2155
  if (def.attr === false) continue;
2093
2156
  const value = this.getAttribute(def.attr);
2094
- if (value !== null || def.type === Boolean) this.props[def.key] = castAttributeValue(value, def);
2157
+ if (value !== null || def.type === Boolean) this.propStore.set(def.key, castAttributeValue(value, def));
2095
2158
  }
2096
2159
  }
2097
2160
  _writePropFromProperty(key, value) {
2098
2161
  const def = propDefs.find((item) => item.key === key);
2099
- this.props[key] = value;
2162
+ this.propStore.set(key, value);
2100
2163
  if ((def === null || def === void 0 ? void 0 : def.reflect) && def.attr !== false) {
2101
2164
  this.reflecting = true;
2102
2165
  try {
@@ -2128,26 +2191,35 @@ function normalizePropDefinitions(props) {
2128
2191
  };
2129
2192
  });
2130
2193
  }
2131
- function applyPropDefaults(props, defs) {
2194
+ function applyPropDefaults(store, defs) {
2132
2195
  for (const def of defs) {
2133
2196
  if (!("default" in def)) continue;
2134
2197
  const value = typeof def.default === "function" ? def.default() : def.default;
2135
- props[def.key] = value;
2198
+ store.set(def.key, value);
2136
2199
  }
2137
2200
  }
2138
- function definePropAccessors(element, props, defs) {
2201
+ function definePropAccessors(element, store, defs) {
2139
2202
  for (const def of defs) {
2140
- if (def.key in element) continue;
2141
- Object.defineProperty(element, def.key, {
2203
+ const key = def.key;
2204
+ const hadOwnValue = Object.prototype.hasOwnProperty.call(element, key);
2205
+ const ownValue = hadOwnValue ? element[key] : void 0;
2206
+ if (hadOwnValue) delete element[key];
2207
+ const existing = Object.getOwnPropertyDescriptor(element, key);
2208
+ if (existing && existing.configurable === false) {
2209
+ console.warn(`[Zeus custom-element] Cannot define prop "${key}" because an own non-configurable property already exists.`);
2210
+ continue;
2211
+ }
2212
+ Object.defineProperty(element, key, {
2142
2213
  configurable: true,
2143
2214
  enumerable: true,
2144
2215
  get() {
2145
- return props[def.key];
2216
+ return store.get(key);
2146
2217
  },
2147
2218
  set(value) {
2148
- element._writePropFromProperty(def.key, value);
2219
+ element._writePropFromProperty(key, value);
2149
2220
  }
2150
2221
  });
2222
+ if (hadOwnValue) element._writePropFromProperty(key, ownValue);
2151
2223
  }
2152
2224
  }
2153
2225
  function castAttributeValue(value, def) {
@@ -2230,7 +2302,8 @@ const HOST_RESERVED_KEYS = new Set([
2230
2302
  "ref",
2231
2303
  "class",
2232
2304
  "className",
2233
- "style"
2305
+ "style",
2306
+ "_elements"
2234
2307
  ]);
2235
2308
  function Host(props) {
2236
2309
  const context = getCurrentHostContext();
@@ -2245,6 +2318,7 @@ function bindHostProps(host, props) {
2245
2318
  bindHostClass(host, props);
2246
2319
  bindHostStyle(host, props);
2247
2320
  bindHostAttributes(host, props);
2321
+ if ("_elements" in props) bindHostElementBindings(host, props);
2248
2322
  }
2249
2323
  function bindHostRef(host, props) {
2250
2324
  if (!("ref" in props)) return;
@@ -2252,9 +2326,6 @@ function bindHostRef(host, props) {
2252
2326
  }
2253
2327
  function bindHostClass(host, props) {
2254
2328
  if (!("class" in props) && !("className" in props)) return;
2255
- /**
2256
- * className has higher priority than class when both exist.
2257
- */
2258
2329
  const value = props.className !== void 0 ? props.className : props.class;
2259
2330
  bindClass(host, () => {
2260
2331
  return resolveHostValue(value);
@@ -2276,13 +2347,25 @@ function bindHostAttributes(host, props) {
2276
2347
  });
2277
2348
  }
2278
2349
  }
2350
+ function bindHostElementBindings(host, props) {
2351
+ const elements = props._elements;
2352
+ for (const _key of Object.keys(elements)) {
2353
+ const getEl = elements[_key];
2354
+ const el = getEl();
2355
+ if (!el) continue;
2356
+ for (const attrKey of Object.keys(props)) {
2357
+ if (HOST_RESERVED_KEYS.has(attrKey)) continue;
2358
+ if (isEventLikeProp(attrKey)) continue;
2359
+ const value = props[attrKey];
2360
+ bindAttr(el, normalizeHostAttrName(attrKey), () => {
2361
+ return resolveHostValue(value);
2362
+ });
2363
+ }
2364
+ }
2365
+ }
2279
2366
  function resolveHostValue(value) {
2280
- /**
2281
- * JSX component props may be direct values or lazy getters.
2282
- * Function values are treated as getters except event-like props,
2283
- * which are filtered before this function is called.
2284
- */
2285
- return typeof value === "function" ? value() : value;
2367
+ if (typeof value === "function") return value();
2368
+ return value;
2286
2369
  }
2287
2370
  function resolveValue$1(value) {
2288
2371
  return typeof value === "function" ? value() : value;