@webjsdev/core 0.7.24 → 0.7.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webjsdev/core",
3
- "version": "0.7.24",
3
+ "version": "0.7.26",
4
4
  "type": "module",
5
5
  "description": "webjs core runtime - html/css tags, WebComponent base, isomorphic renderers",
6
6
  "types": "./index.d.ts",
package/src/component.js CHANGED
@@ -482,8 +482,8 @@ class WebComponentBase extends Base {
482
482
  static get observedAttributes() {
483
483
  const props = this.properties || {};
484
484
  return Object.keys(props)
485
- .filter((k) => !props[k].state)
486
- .map(hyphenate);
485
+ .filter((k) => !(typeof props[k] === 'object' && props[k].state))
486
+ .map((k) => (typeof props[k] === 'object' && props[k].attribute) || hyphenate(k));
487
487
  }
488
488
 
489
489
  constructor() {
@@ -572,8 +572,8 @@ class WebComponentBase extends Base {
572
572
  `${name}: \`static properties\` is no longer supported. Declare reactive ` +
573
573
  `properties via the factory instead: \`class ${name} extends WebComponent({ ` +
574
574
  `count: Number })\`. Use the \`prop()\` helper for options ` +
575
- `(\`prop(Number, { reflect: true })\`) and set defaults via the \`default\` ` +
576
- `option or in the constructor. See https://docs.webjs.com/docs/components.`,
575
+ `(\`prop(Number, { reflect: true })\`) and set defaults in the ` +
576
+ `constructor after \`super()\`. See https://docs.webjs.com/docs/components.`,
577
577
  );
578
578
  }
579
579
  C = Object.getPrototypeOf(C);
@@ -630,6 +630,13 @@ class WebComponentBase extends Base {
630
630
 
631
631
  if (initial !== undefined) {
632
632
  this.__propValues[propName] = initial;
633
+ } else if (d.default !== undefined) {
634
+ // Declarative `default` option (lit-parity). A function default is
635
+ // CALLED per instance, so an object / array default is a fresh value
636
+ // per element. Written straight to the backing store; an applied
637
+ // attribute (attributeChangedCallback runs later) overrides it.
638
+ this.__propValues[propName] =
639
+ typeof d.default === 'function' ? d.default() : d.default;
633
640
  }
634
641
  }
635
642
  }
@@ -645,7 +652,8 @@ class WebComponentBase extends Base {
645
652
  * @private
646
653
  */
647
654
  _reflectAttribute(propName, value, decl) {
648
- const attrName = hyphenate(propName);
655
+ // A custom `attribute` option wins over the kebab-cased property name.
656
+ const attrName = decl.attribute || hyphenate(propName);
649
657
  // Guard against re-entrant loops: attributeChangedCallback fires when
650
658
  // we call setAttribute, which would call the setter again.
651
659
  if (this.__reflectingAttribute) return;
@@ -938,9 +946,17 @@ class WebComponentBase extends Base {
938
946
  if (this.__reflectingAttribute) return;
939
947
 
940
948
  const Ctor = /** @type any */ (this.constructor);
941
- const propName = camelCase(name);
942
- const raw = Ctor.properties && (Ctor.properties[propName] || Ctor.properties[name]);
943
- if (!raw) return;
949
+ const allProps = (Ctor.properties || {});
950
+ // Resolve the incoming attribute name to its property. A custom
951
+ // `attribute` option wins; otherwise the kebab-cased property name. Falls
952
+ // back to the camelCase of the attribute for the common (kebab) case.
953
+ let propName, raw;
954
+ for (const [k, decl] of Object.entries(allProps)) {
955
+ const d = typeof decl === 'object' ? decl : { type: decl };
956
+ if ((d.attribute || hyphenate(k)) === name) { propName = k; raw = decl; break; }
957
+ }
958
+ if (raw === undefined) { propName = camelCase(name); raw = allProps[propName] || allProps[name]; }
959
+ if (raw === undefined) return;
944
960
  // A declaration is either a full descriptor (`{ type: Number, … }`) or the
945
961
  // bare-constructor shorthand the factory accepts (`count: Number`), in which
946
962
  // case the value IS the type. Normalise so type-based coercion fires either
@@ -1052,8 +1052,19 @@ function appendReflectedAttrs(opening, instance, presentAttrNames) {
1052
1052
  function applyAttrsToInstance(instance, attrs, Cls) {
1053
1053
  const props = Cls.properties || {};
1054
1054
  for (const [key, raw] of Object.entries(attrs)) {
1055
- const rawDef = props[key] || props[camelCase(key)];
1056
- const propName = props[key] ? key : camelCase(key);
1055
+ // Resolve the source attribute name to its property: a custom `attribute`
1056
+ // option wins, else the kebab-cased property name, else the camelCase of
1057
+ // the attribute (the common case). Mirrors the client attributeChangedCallback
1058
+ // so a custom-attribute prop gets the right value in the SSR'd first paint.
1059
+ let propName, rawDef;
1060
+ for (const [k, decl] of Object.entries(props)) {
1061
+ const d = typeof decl === 'object' ? decl : { type: decl };
1062
+ if ((d.attribute || hyphenate(k)) === key) { propName = k; rawDef = decl; break; }
1063
+ }
1064
+ if (rawDef === undefined) {
1065
+ rawDef = props[key] || props[camelCase(key)];
1066
+ propName = props[key] ? key : camelCase(key);
1067
+ }
1057
1068
  if (!rawDef) {
1058
1069
  instance[propName] = raw;
1059
1070
  continue;
@@ -1080,6 +1091,11 @@ function camelCase(s) {
1080
1091
  return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1081
1092
  }
1082
1093
 
1094
+ /** Kebab-case a property name for its default HTML attribute (matches component.js). @param {string} s */
1095
+ function hyphenate(s) {
1096
+ return s.replace(/([A-Z])/g, '-$1').toLowerCase();
1097
+ }
1098
+
1083
1099
  /**
1084
1100
  * Inverse of camelCase. `userName` -> `user-name`, `userID` -> `user-i-d`.
1085
1101
  * Used to serialize property-binding names into HTML attribute names,
@@ -145,6 +145,16 @@ export interface WebjsConfig {
145
145
  */
146
146
  seed?: boolean;
147
147
 
148
+ /**
149
+ * Bun zero-install dependency version-pinning switch (#685). Default `true`,
150
+ * Bun only. When on, an `onLoad` transform rewrites a declared dep's bare
151
+ * import specifier to its package.json / `bun.lock` version, so Bun's
152
+ * auto-install fetches the pinned version instead of latest (#684). Set to
153
+ * `false` to leave specifiers bare (zero-install resolves to latest). The
154
+ * `WEBJS_PIN` env override wins over this. No effect on Node.
155
+ */
156
+ pin?: boolean;
157
+
148
158
  /**
149
159
  * Client-router switch (#629). Default `true`: the client router auto-enables
150
160
  * in the browser whenever `@webjsdev/core` loads, so any page that ships a