@yahoo/uds-v5-wip 1.46.0 → 1.48.0

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.
@@ -95,16 +95,16 @@ interface CompositeBinding {
95
95
  layers: Record<string, string>;
96
96
  }
97
97
  /**
98
- * Forward an existing surface key from one of the component's layers as
99
- * a public JSX prop. If the target layer is a primitive, `from` is an
100
- * HTML attr / event name; if it's a composed component, `from` is one
101
- * of that component's existing props.
98
+ * Forward a JSX prop value to one of the component's layers as an
99
+ * existing surface key. If the target layer is a primitive, `from` is
100
+ * an HTML attr / event name; if it's a composed component, `from` is
101
+ * one of that component's existing props.
102
102
  *
103
- * `from` is a bare string (no braces) — the leading-brace check on the
104
- * binding shape's `from` is how the framework dispatches "bind a
105
- * registered thing" vs "forward an existing surface key".
103
+ * `from` is a bare string (no braces) — the absence of `styleProp` /
104
+ * `composite` keys is how the framework discriminates this shape from
105
+ * the registered-binding shapes.
106
106
  */
107
- interface SurfaceForward {
107
+ interface ForwardBinding {
108
108
  layer: string;
109
109
  from: string;
110
110
  }
@@ -144,7 +144,7 @@ type StylePropShorthand = StylePropRef;
144
144
  * `'{bg}'` is allowed only in the primitive form's props (see
145
145
  * `PrimitivePropBinding`).
146
146
  */
147
- type VerbosePropBinding = StylePropBinding | SingleLayerCompositeBinding | CompositeBinding | SurfaceForward | BoolMarker | EnumMarker<any>;
147
+ type VerbosePropBinding = StylePropBinding | SingleLayerCompositeBinding | CompositeBinding | ForwardBinding | BoolMarker | EnumMarker<any>;
148
148
  /**
149
149
  * All allowed shapes for a single entry in the primitive form's `props`
150
150
  * block. Primitive form adds the `StylePropShorthand` brace-ref
@@ -198,4 +198,4 @@ interface ComponentConfigValue<TLayers extends Record<string, LayerInput>, TProp
198
198
  * function destructures `props.<layerName>` into the JSX position.
199
199
  */
200
200
  //#endregion
201
- export { BoolMarker, ComponentConfigValue, ComposedLayer, CompositeBinding, EnumMarker, HtmlTag, LayerInput, PrimitiveLayer, PrimitivePropBinding, PropBinding, RootTag, SingleLayerCompositeBinding, StylePropBinding, StylePropShorthand, SurfaceForward, VerbosePropBinding };
201
+ export { BoolMarker, ComponentConfigValue, ComposedLayer, CompositeBinding, EnumMarker, ForwardBinding, HtmlTag, LayerInput, PrimitiveLayer, PrimitivePropBinding, PropBinding, RootTag, SingleLayerCompositeBinding, StylePropBinding, StylePropShorthand, VerbosePropBinding };
@@ -1,5 +1,5 @@
1
1
  import { ComponentRef, CompositeRef, RegisteredComponents, RegisteredComposites, RegisteredStyleProps, StylePropRef } from "./component-refs.js";
2
- import { BoolMarker, ComponentConfigValue, ComposedLayer, CompositeBinding, EnumMarker, HtmlTag, LayerInput, PrimitiveLayer, PrimitivePropBinding, PropBinding, RootTag, SingleLayerCompositeBinding, StylePropBinding, StylePropShorthand, SurfaceForward, VerbosePropBinding } from "./component-config.js";
2
+ import { BoolMarker, ComponentConfigValue, ComposedLayer, CompositeBinding, EnumMarker, ForwardBinding, HtmlTag, LayerInput, PrimitiveLayer, PrimitivePropBinding, PropBinding, RootTag, SingleLayerCompositeBinding, StylePropBinding, StylePropShorthand, VerbosePropBinding } from "./component-config.js";
3
3
  import { Props } from "./Props.js";
4
4
  import { BoundComponent } from "./defineComponent.js";
5
5
  import { ColorFn, ColorKeyword, CssAngle, CssColor, CssLength, CssPercentage, CssRatio, CssTime, CssValue, CssValueTypeName, HexColor, HslColor, RgbColor } from "./types/css-values.js";
@@ -1235,8 +1235,9 @@ const transformOrigin = defineStyleProp({
1235
1235
  classPrefix: "origin"
1236
1236
  }).metadata({ label: "Transform origin" });
1237
1237
  const transition = defineStyleProp({
1238
- cssProperty: "transition-property",
1239
- classPrefix: "transition"
1238
+ cssProperty: "transition",
1239
+ classPrefix: "transition",
1240
+ arbitrary: "string"
1240
1241
  }).metadata({ label: "Transition" });
1241
1242
  const transitionDuration = defineStyleProp({
1242
1243
  cssProperty: "transition-duration",
@@ -0,0 +1,90 @@
1
+ //#region ../loader/dist/loader/lower-new-api-primitive.js
2
+ /**
3
+ * Build the className a binding emits for a given value. Mirrors the
4
+ * codegen convention in `packages/codegen/src/css/prepareCss.ts`:
5
+ *
6
+ * - `classPrefix === ''` / `'no-prefix'` → value IS the class.
7
+ * - Bracketed arbitrary values (`'[#abc]'`) → preserved verbatim
8
+ * (`bg-[#abc]`).
9
+ * - Otherwise → `${classPrefix}-${value}`.
10
+ */
11
+ function buildClassName(classPrefix, noPrefix, value) {
12
+ if (noPrefix) return value;
13
+ return `${classPrefix}-${value}`;
14
+ }
15
+ /**
16
+ * Read a JSX attribute value as a literal string when statically
17
+ * resolvable. Handles `attr="x"`, `attr={"x"}`, and template-literal
18
+ * expressions with no interpolations. Returns `undefined` for any
19
+ * dynamic form so the caller can bail.
20
+ */
21
+ function readStaticString(value) {
22
+ if (!value) return void 0;
23
+ if (value.type === "StringLiteral") return value.value;
24
+ if (value.type === "JSXExpressionContainer") {
25
+ const expr = value.expression;
26
+ if (expr.type === "StringLiteral") return expr.value;
27
+ if (expr.type === "TemplateLiteral" && expr.expressions.length === 0 && expr.quasis.length === 1) return expr.quasis[0].value.cooked ?? expr.quasis[0].value.raw;
28
+ }
29
+ }
30
+ /**
31
+ * Lower a JSX element of a new-API primitive component. Returns `true`
32
+ * when the AST was mutated (lowered); `false` when the call site can't
33
+ * be statically lowered and the runtime path should take over.
34
+ *
35
+ * `t` is the `@babel/types` namespace — passed in so the helper stays
36
+ * free of direct import dependencies on Babel internals (the loader
37
+ * already imports them and threads them through).
38
+ *
39
+ * `openingElement` and (optional) `closingElement` are mutated in
40
+ * place on success.
41
+ */
42
+ function lowerNewApiPrimitiveJsx(openingElement, closingElement, entry, t) {
43
+ let tag = entry.tag;
44
+ const classNames = [...entry.defaultClassNames];
45
+ const passthroughAttrs = [];
46
+ let existingClassName = null;
47
+ for (const attr of openingElement.attributes ?? []) {
48
+ if (attr.type === "JSXSpreadAttribute") return false;
49
+ const attrName = attr.name?.type === "JSXIdentifier" ? attr.name.name : void 0;
50
+ if (!attrName) return false;
51
+ if (attrName === "as") {
52
+ const tagValue = readStaticString(attr.value);
53
+ if (tagValue === void 0) return false;
54
+ tag = tagValue;
55
+ continue;
56
+ }
57
+ if (attrName === "className") {
58
+ existingClassName = attr.value;
59
+ continue;
60
+ }
61
+ const binding = entry.propBindings[attrName];
62
+ if (binding) {
63
+ const value = readStaticString(attr.value);
64
+ if (value === void 0) return false;
65
+ classNames.push(buildClassName(binding.classPrefix, binding.noPrefix, value));
66
+ continue;
67
+ }
68
+ passthroughAttrs.push(attr);
69
+ }
70
+ const boundClassName = classNames.join(" ");
71
+ let classNameAttr = null;
72
+ if (existingClassName === null && boundClassName.length > 0) classNameAttr = t.jsxAttribute(t.jsxIdentifier("className"), t.stringLiteral(boundClassName));
73
+ else if (existingClassName !== null) if (existingClassName.type === "StringLiteral") {
74
+ const merged = boundClassName ? `${existingClassName.value} ${boundClassName}` : existingClassName.value;
75
+ classNameAttr = t.jsxAttribute(t.jsxIdentifier("className"), t.stringLiteral(merged));
76
+ } else if (existingClassName.type === "JSXExpressionContainer" && existingClassName.expression.type === "StringLiteral") {
77
+ const merged = boundClassName ? `${existingClassName.expression.value} ${boundClassName}` : existingClassName.expression.value;
78
+ classNameAttr = t.jsxAttribute(t.jsxIdentifier("className"), t.stringLiteral(merged));
79
+ } else if (existingClassName.type === "JSXExpressionContainer") {
80
+ const expr = existingClassName.expression;
81
+ const finalExpr = boundClassName ? t.binaryExpression("+", t.binaryExpression("+", expr, t.stringLiteral(" ")), t.stringLiteral(boundClassName)) : expr;
82
+ classNameAttr = t.jsxAttribute(t.jsxIdentifier("className"), t.jsxExpressionContainer(finalExpr));
83
+ } else return false;
84
+ openingElement.name = t.jsxIdentifier(tag);
85
+ openingElement.attributes = classNameAttr ? [classNameAttr, ...passthroughAttrs] : passthroughAttrs;
86
+ if (closingElement) closingElement.name = t.jsxIdentifier(tag);
87
+ return true;
88
+ }
89
+ //#endregion
90
+ export { lowerNewApiPrimitiveJsx };
@@ -6,6 +6,7 @@ import { canInlineSimpleLoweredComponent, resolveLoweredCreateComponentData } fr
6
6
  import { applySlotMotionToElement, clearHoistedMotionStates, componentHasExitMotion, getCustomSlotMotion, getHoistedMotionStates, handleMotionOnElement, wrapCustomComponentWithAnimatePresence, wrapParentConditionalWithAnimatePresence } from "./loader/motion-transform.js";
7
7
  import { findClassesParamName, findSlotFromClassNameAttr, findSlotFromPropsSpreadAttr, findSlotPropsParamName, handleCompiledJsxDataAttrs, injectInternalUdsProps } from "./loader/data-attr-transform.js";
8
8
  import { buildInlineSimpleLoweredCreateComponentRenderFn, buildInlineSimplePrimitiveCreateComponentRenderFn, buildLoweredCreateComponentConfigExpression, extractOwnPropKeys, inferCreateComponentNameFromAssignment, isCreateComponentRenderFnNode, remapOnPressToOnClickInJsxAttributes } from "./loader/create-component-lowering.js";
9
+ import { lowerNewApiPrimitiveJsx } from "./loader/lower-new-api-primitive.js";
9
10
  import { createStyleTransformRuntime } from "./loader/style-transform.js";
10
11
  import * as t from "@babel/types";
11
12
  import path from "node:path";
@@ -97,6 +98,18 @@ const transformLoader = function(source) {
97
98
  JSXOpeningElement(nodePath) {
98
99
  const jsxName = nodePath.node.name;
99
100
  const jsxTagName = jsxName?.type === "JSXIdentifier" ? jsxName.name : void 0;
101
+ if (jsxTagName) {
102
+ const componentEntry = manifest?.components?.[jsxTagName];
103
+ if (componentEntry?.propBindings && udsImportedNames.has(jsxTagName)) {
104
+ const closingElement = (nodePath.parentPath?.node)?.closingElement ?? null;
105
+ if (lowerNewApiPrimitiveJsx(nodePath.node, closingElement, {
106
+ tag: componentEntry.element,
107
+ propBindings: componentEntry.propBindings,
108
+ defaultClassNames: componentEntry.defaultClassNames ?? []
109
+ }, t)) transformed = true;
110
+ return;
111
+ }
112
+ }
100
113
  if (jsxTagName && !allUdsComponents.has(jsxTagName) && udsImportedNames.has(jsxTagName)) {
101
114
  allUdsComponents.add(jsxTagName);
102
115
  if (!primitiveUdsComponents.has(jsxTagName)) {