@yahoo/uds-create-utils 1.1.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.
Files changed (60) hide show
  1. package/dist/array-utils/closestItem.d.ts +4 -0
  2. package/dist/array-utils/closestItem.js +9 -0
  3. package/dist/array-utils/removeItem.d.ts +4 -0
  4. package/dist/array-utils/removeItem.js +8 -0
  5. package/dist/arrayUtils.d.ts +4 -0
  6. package/dist/arrayUtils.js +9 -0
  7. package/dist/component-style-defaults.d.ts +5 -0
  8. package/dist/component-style-defaults.js +68 -0
  9. package/dist/config-snippet.d.ts +15 -0
  10. package/dist/config-snippet.js +261 -0
  11. package/dist/index.d.ts +25 -0
  12. package/dist/index.js +25 -0
  13. package/dist/logger.d.ts +20 -0
  14. package/dist/logger.js +79 -0
  15. package/dist/math-utils/clamp.d.ts +12 -0
  16. package/dist/math-utils/clamp.js +14 -0
  17. package/dist/motion-utils/interpolate.d.ts +10 -0
  18. package/dist/motion-utils/interpolate.js +25 -0
  19. package/dist/motion-utils/resolveMotionState.d.ts +34 -0
  20. package/dist/motion-utils/resolveMotionState.js +33 -0
  21. package/dist/object-utils/entries.d.ts +4 -0
  22. package/dist/object-utils/entries.js +6 -0
  23. package/dist/object-utils/flattenObj.d.ts +12 -0
  24. package/dist/object-utils/flattenObj.js +21 -0
  25. package/dist/object-utils/fromEntries.d.ts +4 -0
  26. package/dist/object-utils/fromEntries.js +6 -0
  27. package/dist/object-utils/keys.d.ts +4 -0
  28. package/dist/object-utils/keys.js +6 -0
  29. package/dist/object-utils/mapKeys.d.ts +5 -0
  30. package/dist/object-utils/mapKeys.js +10 -0
  31. package/dist/object-utils/mapValues.d.ts +5 -0
  32. package/dist/object-utils/mapValues.js +9 -0
  33. package/dist/string-utils/arrayToUnion.d.ts +4 -0
  34. package/dist/string-utils/arrayToUnion.js +6 -0
  35. package/dist/string-utils/capitalize.d.ts +4 -0
  36. package/dist/string-utils/capitalize.js +6 -0
  37. package/dist/string-utils/componentClassName.d.ts +58 -0
  38. package/dist/string-utils/componentClassName.js +70 -0
  39. package/dist/string-utils/createTemplate.d.ts +16 -0
  40. package/dist/string-utils/createTemplate.js +142 -0
  41. package/dist/string-utils/cssVar.d.ts +55 -0
  42. package/dist/string-utils/cssVar.js +63 -0
  43. package/dist/string-utils/cssVars.d.ts +81 -0
  44. package/dist/string-utils/cssVars.js +108 -0
  45. package/dist/string-utils/dedent.d.ts +47 -0
  46. package/dist/string-utils/dedent.js +68 -0
  47. package/dist/string-utils/indent.d.ts +4 -0
  48. package/dist/string-utils/indent.js +6 -0
  49. package/dist/string-utils/join.d.ts +5 -0
  50. package/dist/string-utils/join.js +6 -0
  51. package/dist/string-utils/kebabCase.d.ts +13 -0
  52. package/dist/string-utils/kebabCase.js +14 -0
  53. package/dist/string-utils/objectToInterface.d.ts +1 -0
  54. package/dist/string-utils/objectToInterface.js +6 -0
  55. package/dist/string-utils/split.d.ts +10 -0
  56. package/dist/string-utils/split.js +12 -0
  57. package/dist/string-utils/tsProperties.d.ts +29 -0
  58. package/dist/string-utils/tsProperties.js +60 -0
  59. package/dist/tsconfig.tsbuildinfo +1 -0
  60. package/package.json +40 -0
@@ -0,0 +1,4 @@
1
+ //#region src/array-utils/closestItem.d.ts
2
+ declare function closestItem<T>(arr: T[], item: T): T;
3
+ //#endregion
4
+ export { closestItem };
@@ -0,0 +1,9 @@
1
+ //#region src/array-utils/closestItem.ts
2
+ function closestItem(arr, item) {
3
+ const index = arr.indexOf(item);
4
+ if (index === -1) return arr[0];
5
+ if (index === arr.length - 1) return arr[arr.length - 2];
6
+ return arr[index + 1];
7
+ }
8
+ //#endregion
9
+ export { closestItem };
@@ -0,0 +1,4 @@
1
+ //#region src/array-utils/removeItem.d.ts
2
+ declare function removeItem<T>([...arr]: T[], item: T): T[];
3
+ //#endregion
4
+ export { removeItem };
@@ -0,0 +1,8 @@
1
+ //#region src/array-utils/removeItem.ts
2
+ function removeItem([ ...arr], item) {
3
+ const index = arr.indexOf(item);
4
+ index > -1 && arr.splice(index, 1);
5
+ return arr;
6
+ }
7
+ //#endregion
8
+ export { removeItem };
@@ -0,0 +1,4 @@
1
+ //#region src/arrayUtils.d.ts
2
+ declare function closestItem<T>(arr: T[], item: T): T;
3
+ //#endregion
4
+ export { closestItem };
@@ -0,0 +1,9 @@
1
+ //#region src/arrayUtils.ts
2
+ function closestItem(arr, item) {
3
+ const index = arr.indexOf(item);
4
+ if (index === -1) return arr[0];
5
+ if (index === arr.length - 1) return arr[arr.length - 2];
6
+ return arr[index + 1];
7
+ }
8
+ //#endregion
9
+ export { closestItem };
@@ -0,0 +1,5 @@
1
+ //#region src/component-style-defaults.d.ts
2
+ type ComponentStyleDefaultsInput = Record<string, unknown>;
3
+ declare function applyComponentStyleDefaults(componentName: string, styleProps: ComponentStyleDefaultsInput): ComponentStyleDefaultsInput;
4
+ //#endregion
5
+ export { ComponentStyleDefaultsInput, applyComponentStyleDefaults };
@@ -0,0 +1,68 @@
1
+ //#region src/component-style-defaults.ts
2
+ function toStringValue(value) {
3
+ return typeof value === "string" ? value : String(value);
4
+ }
5
+ function applyComponentStyleDefaults(componentName, styleProps) {
6
+ if (componentName === "HStack") {
7
+ const { gap, display = "flex", flexDirection = display === "flex" ? "row" : void 0, alignItems = display === "flex" ? "center" : void 0, ...rest } = styleProps;
8
+ return {
9
+ flexDirection,
10
+ display,
11
+ alignItems,
12
+ gapX: gap,
13
+ ...rest
14
+ };
15
+ }
16
+ if (componentName === "VStack") {
17
+ const { gap, display = "flex", flexDirection = display === "flex" ? "col" : void 0, ...rest } = styleProps;
18
+ return {
19
+ flexDirection,
20
+ display,
21
+ gapY: gap,
22
+ ...rest
23
+ };
24
+ }
25
+ if (componentName === "Grid") {
26
+ const { columns, rows, autoFit, autoFill, inline, display, gridTemplateColumns, gridTemplateRows, ...rest } = styleProps;
27
+ return {
28
+ display: display ?? (inline ? "inline-grid" : "grid"),
29
+ gridTemplateColumns: gridTemplateColumns ?? (autoFit ? `[repeat(auto-fit,minmax(${toStringValue(autoFit)},1fr))]` : autoFill ? `[repeat(auto-fill,minmax(${toStringValue(autoFill)},1fr))]` : columns),
30
+ gridTemplateRows: gridTemplateRows ?? rows,
31
+ ...rest
32
+ };
33
+ }
34
+ if (componentName === "GridItem") {
35
+ const { colSpan, rowSpan, colStart, colEnd, rowStart, rowEnd, gridColumnSpan, gridRowSpan, gridColumnStart, gridColumnEnd, gridRowStart, gridRowEnd, ...rest } = styleProps;
36
+ return {
37
+ gridColumnSpan: gridColumnSpan ?? colSpan,
38
+ gridRowSpan: gridRowSpan ?? rowSpan,
39
+ gridColumnStart: gridColumnStart ?? colStart,
40
+ gridColumnEnd: gridColumnEnd ?? colEnd,
41
+ gridRowStart: gridRowStart ?? rowStart,
42
+ gridRowEnd: gridRowEnd ?? rowEnd,
43
+ ...rest
44
+ };
45
+ }
46
+ if (componentName === "Button") return {
47
+ cursor: "pointer",
48
+ ...styleProps
49
+ };
50
+ if (componentName === "Avatar") {
51
+ const { shape, ...rest } = styleProps;
52
+ return {
53
+ borderRadius: shape,
54
+ ...rest
55
+ };
56
+ }
57
+ if (componentName === "Svg") {
58
+ const { viewBox, width, height, strokeWidth, ...rest } = styleProps;
59
+ return {
60
+ minWidth: viewBox && width && height ? "fit" : void 0,
61
+ ...rest,
62
+ strokeWidth
63
+ };
64
+ }
65
+ return styleProps;
66
+ }
67
+ //#endregion
68
+ export { applyComponentStyleDefaults };
@@ -0,0 +1,15 @@
1
+ //#region src/config-snippet.d.ts
2
+ /**
3
+ * Shared utilities for extracting and formatting UDS component config snippets.
4
+ * Used by both the docs app and codegen to display component configuration.
5
+ */
6
+ /**
7
+ * Build a formatted component config snippet from raw config source code.
8
+ *
9
+ * @param componentName - PascalCase component name (e.g. "Button")
10
+ * @param componentConfigSource - Raw source code of the config file
11
+ * @param modifierMappings - Map of modifier names to Tailwind prefixes (e.g. { _hover: "hover:" })
12
+ */
13
+ declare function buildComponentConfigSnippet(componentName: string, componentConfigSource: string, modifierMappings?: Record<string, string>): string;
14
+ //#endregion
15
+ export { buildComponentConfigSnippet };
@@ -0,0 +1,261 @@
1
+ //#region src/config-snippet.ts
2
+ /**
3
+ * Shared utilities for extracting and formatting UDS component config snippets.
4
+ * Used by both the docs app and codegen to display component configuration.
5
+ */
6
+ function findMatchingBrace(source, openBraceIndex) {
7
+ let depth = 0;
8
+ let inSingle = false;
9
+ let inDouble = false;
10
+ let inTemplate = false;
11
+ let inLineComment = false;
12
+ let inBlockComment = false;
13
+ for (let i = openBraceIndex; i < source.length; i += 1) {
14
+ const ch = source[i];
15
+ const next = source[i + 1];
16
+ const prev = source[i - 1];
17
+ if (inLineComment) {
18
+ if (ch === "\n") inLineComment = false;
19
+ continue;
20
+ }
21
+ if (inBlockComment) {
22
+ if (prev === "*" && ch === "/") inBlockComment = false;
23
+ continue;
24
+ }
25
+ if (!inSingle && !inDouble && !inTemplate) {
26
+ if (ch === "/" && next === "/") {
27
+ inLineComment = true;
28
+ i += 1;
29
+ continue;
30
+ }
31
+ if (ch === "/" && next === "*") {
32
+ inBlockComment = true;
33
+ i += 1;
34
+ continue;
35
+ }
36
+ }
37
+ if (!inDouble && !inTemplate && ch === "'" && prev !== "\\") {
38
+ inSingle = !inSingle;
39
+ continue;
40
+ }
41
+ if (!inSingle && !inTemplate && ch === "\"" && prev !== "\\") {
42
+ inDouble = !inDouble;
43
+ continue;
44
+ }
45
+ if (!inSingle && !inDouble && ch === "`" && prev !== "\\") {
46
+ inTemplate = !inTemplate;
47
+ continue;
48
+ }
49
+ if (inSingle || inDouble || inTemplate) continue;
50
+ if (ch === "{") depth += 1;
51
+ if (ch === "}") {
52
+ depth -= 1;
53
+ if (depth === 0) return i;
54
+ }
55
+ }
56
+ return -1;
57
+ }
58
+ /**
59
+ * Match a new-API single-call form:
60
+ *
61
+ * export const Box = defineComponent('div').config(({ styleProp }) => ({...}));
62
+ * export const VStack = defineComponent(Box).config(() => ({ defaultProps: {...} }));
63
+ *
64
+ * Returns the full `defineComponent(...)` call expression as a snippet
65
+ * (suitable for direct display in a source-config tab) or `null` when
66
+ * the pattern isn't present.
67
+ */
68
+ function extractNewApiComponentBlock(source, componentName) {
69
+ const match = new RegExp(`(?:^|[\\s;])(?:export\\s+)?const\\s+${componentName}\\s*=\\s*defineComponent\\s*\\(`, "m").exec(source);
70
+ if (!match) return null;
71
+ const openParenIndex = match.index + match[0].length - 1;
72
+ let depth = 0;
73
+ let inSingle = false;
74
+ let inDouble = false;
75
+ let inTemplate = false;
76
+ for (let i = openParenIndex; i < source.length; i += 1) {
77
+ const ch = source[i];
78
+ const prev = source[i - 1];
79
+ if (!inDouble && !inTemplate && ch === "'" && prev !== "\\") {
80
+ inSingle = !inSingle;
81
+ continue;
82
+ }
83
+ if (!inSingle && !inTemplate && ch === "\"" && prev !== "\\") {
84
+ inDouble = !inDouble;
85
+ continue;
86
+ }
87
+ if (!inSingle && !inDouble && ch === "`" && prev !== "\\") {
88
+ inTemplate = !inTemplate;
89
+ continue;
90
+ }
91
+ if (inSingle || inDouble || inTemplate) continue;
92
+ if (ch === "(") depth += 1;
93
+ if (ch === ")") {
94
+ depth -= 1;
95
+ if (depth === 0) {
96
+ const callStart = match.index + match[0].indexOf("defineComponent");
97
+ let end = i + 1;
98
+ while (end < source.length) {
99
+ const chainMatch = /^\s*\.(config|render|metadata)\s*\(/.exec(source.slice(end));
100
+ if (!chainMatch) break;
101
+ let chainDepth = 0;
102
+ let chainInSingle = false;
103
+ let chainInDouble = false;
104
+ let chainInTemplate = false;
105
+ let j = end + chainMatch[0].length - 1;
106
+ for (; j < source.length; j += 1) {
107
+ const cch = source[j];
108
+ const cprev = source[j - 1];
109
+ if (!chainInDouble && !chainInTemplate && cch === "'" && cprev !== "\\") {
110
+ chainInSingle = !chainInSingle;
111
+ continue;
112
+ }
113
+ if (!chainInSingle && !chainInTemplate && cch === "\"" && cprev !== "\\") {
114
+ chainInDouble = !chainInDouble;
115
+ continue;
116
+ }
117
+ if (!chainInSingle && !chainInDouble && cch === "`" && cprev !== "\\") {
118
+ chainInTemplate = !chainInTemplate;
119
+ continue;
120
+ }
121
+ if (chainInSingle || chainInDouble || chainInTemplate) continue;
122
+ if (cch === "(") chainDepth += 1;
123
+ if (cch === ")") {
124
+ chainDepth -= 1;
125
+ if (chainDepth === 0) {
126
+ end = j + 1;
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ if (chainDepth !== 0) break;
132
+ }
133
+ return source.slice(callStart, end);
134
+ }
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+ function extractDefinitionComponentBlock(source, componentName) {
140
+ const newApi = extractNewApiComponentBlock(source, componentName);
141
+ if (newApi) return newApi;
142
+ const defineComponentIndex = source.indexOf("defineComponent");
143
+ if (defineComponentIndex < 0) return null;
144
+ const quotedNameIndex = [`'${componentName}'`, `"${componentName}"`].map((pattern) => source.indexOf(pattern, defineComponentIndex)).find((index) => index >= 0);
145
+ if (quotedNameIndex != null && quotedNameIndex >= 0) {
146
+ const arrowIndex = source.indexOf("=>", quotedNameIndex);
147
+ if (arrowIndex < 0) return null;
148
+ const openParenIndex = source.indexOf("(", arrowIndex);
149
+ if (openParenIndex < 0) return null;
150
+ const openBraceIndex = source.indexOf("{", openParenIndex);
151
+ if (openBraceIndex < 0) return null;
152
+ const closeBraceIndex = findMatchingBrace(source, openBraceIndex);
153
+ if (closeBraceIndex < 0) return null;
154
+ return ` ${componentName}: ${source.slice(openBraceIndex, closeBraceIndex + 1)},`;
155
+ }
156
+ const keyMatch = new RegExp(`(?:^|[\\s,({])${componentName}\\s*:\\s*\\{`, "m").exec(source.slice(defineComponentIndex));
157
+ if (!keyMatch) return null;
158
+ const matchStart = defineComponentIndex + keyMatch.index;
159
+ const braceOffset = source.indexOf("{", matchStart + keyMatch[0].indexOf(componentName));
160
+ if (braceOffset < 0) return null;
161
+ const closeBraceIndex = findMatchingBrace(source, braceOffset);
162
+ if (closeBraceIndex < 0) return null;
163
+ return ` ${componentName}: ${source.slice(braceOffset, closeBraceIndex + 1)},`;
164
+ }
165
+ function extractAtomicTokenAliases(source) {
166
+ const aliasesByGroup = /* @__PURE__ */ new Map();
167
+ const addAlias = (group, alias) => {
168
+ if (!group || !alias) return;
169
+ const aliases = aliasesByGroup.get(group) ?? /* @__PURE__ */ new Set();
170
+ aliases.add(alias);
171
+ aliasesByGroup.set(group, aliases);
172
+ };
173
+ for (const match of source.matchAll(/tokens\.([a-zA-Z_$][a-zA-Z0-9_$]*)\.([a-zA-Z_$][a-zA-Z0-9_$]*)/g)) addAlias(match[1], match[2]);
174
+ for (const match of source.matchAll(/tokens\.([a-zA-Z_$][a-zA-Z0-9_$]*)\[['"]([^'"\\]+)['"]\]/g)) addAlias(match[1], match[2]);
175
+ return aliasesByGroup;
176
+ }
177
+ function buildTokenHeaderComment(componentName, block) {
178
+ const groups = [...extractAtomicTokenAliases(block).entries()].sort(([a], [b]) => a.localeCompare(b));
179
+ if (groups.length === 0) return "";
180
+ return `// Required token aliases for this ${componentName} config:\n${groups.map(([group, aliases]) => {
181
+ return `// - ${group}: ${[...aliases].sort((a, b) => a.localeCompare(b)).join(", ")}`;
182
+ }).join("\n")}`;
183
+ }
184
+ /**
185
+ * Replace `textVariants.<variant>.root` with `components.Text.variant.<variant>`
186
+ * so the snippet is self-contained without the internal textVariants import.
187
+ */
188
+ function expandTextVariantRefs(block) {
189
+ return block.replace(/textVariants\.([a-zA-Z0-9_]+)\.root/g, "components.Text.variant.$1");
190
+ }
191
+ /**
192
+ * Extract modifier prop names (`_foo`) used as object keys in the config block.
193
+ */
194
+ function extractModifierNames(block) {
195
+ const pattern = /\b(_[a-zA-Z][a-zA-Z0-9]*)\s*:/g;
196
+ const names = /* @__PURE__ */ new Set();
197
+ for (const match of block.matchAll(pattern)) names.add(match[1]);
198
+ return [...names].sort((a, b) => a.localeCompare(b));
199
+ }
200
+ /**
201
+ * Convert a Tailwind modifier prefix to a CSS selector.
202
+ * e.g. "hover:" -> "&:hover"
203
+ * "data-[state=open]:" -> "&[data-state=open]"
204
+ * "aria-expanded:" -> "&[aria-expanded=true]"
205
+ */
206
+ function tailwindPrefixToSelector(prefix) {
207
+ const raw = prefix.replace(/:$/, "");
208
+ if (raw.startsWith("data-[") && raw.endsWith("]")) return `&[data-${raw.slice(6, -1)}]`;
209
+ if (raw.startsWith("aria-")) return `&[${raw}=true]`;
210
+ if (raw.startsWith("*::")) return `& ${raw.slice(1)}`;
211
+ if (raw === "starting-style") return "@starting-style";
212
+ return `&:${raw}`;
213
+ }
214
+ /**
215
+ * Build a modifier comment + `.defineModifiers([...])` snippet
216
+ * for modifiers used in the config block.
217
+ */
218
+ function buildModifierSnippet(block, modifierMappings) {
219
+ const names = extractModifierNames(block);
220
+ if (names.length === 0) return "";
221
+ const matched = names.filter((name) => name in modifierMappings);
222
+ if (matched.length === 0) return "";
223
+ return `${`// Modifiers used:\n${matched.map((name) => `// ${name} → ${modifierMappings[name]}`).join("\n")}\n`}${`.defineModifiers([\n${matched.map((name) => {
224
+ return ` { modifier: '${name}', selector: '${tailwindPrefixToSelector(modifierMappings[name])}' },`;
225
+ }).join("\n")}\n ])\n `}`;
226
+ }
227
+ /**
228
+ * Build a formatted component config snippet from raw config source code.
229
+ *
230
+ * @param componentName - PascalCase component name (e.g. "Button")
231
+ * @param componentConfigSource - Raw source code of the config file
232
+ * @param modifierMappings - Map of modifier names to Tailwind prefixes (e.g. { _hover: "hover:" })
233
+ */
234
+ function buildComponentConfigSnippet(componentName, componentConfigSource, modifierMappings = {}) {
235
+ const newApi = extractNewApiComponentBlock(componentConfigSource, componentName);
236
+ if (newApi) return `import { defineComponent } from '@yahoo/uds-create-config';
237
+
238
+ export const ${componentName} = ${newApi};`;
239
+ let block = extractDefinitionComponentBlock(componentConfigSource, componentName);
240
+ if (block) {
241
+ block = expandTextVariantRefs(block);
242
+ const params = block.includes("components.") ? "{ tokens, components }" : "{ tokens }";
243
+ const modifierSnippet = buildModifierSnippet(block, modifierMappings);
244
+ return `${buildTokenHeaderComment(componentName, block)}
245
+ ${modifierSnippet}.defineComponents((${params}) => ({
246
+ ${block}
247
+ }))`;
248
+ }
249
+ return `// ${componentName} config file was not found or could not be parsed.
250
+ // Add this builder snippet to override it:
251
+ // ${componentName} required token aliases: none detected
252
+ .defineComponents(({ tokens }) => ({
253
+ ${componentName}: {
254
+ base: {
255
+ root: {},
256
+ },
257
+ },
258
+ }))`;
259
+ }
260
+ //#endregion
261
+ export { buildComponentConfigSnippet };
@@ -0,0 +1,25 @@
1
+ import { ComponentStyleDefaultsInput, applyComponentStyleDefaults } from "./component-style-defaults.js";
2
+ import { closestItem } from "./array-utils/closestItem.js";
3
+ import { removeItem } from "./array-utils/removeItem.js";
4
+ import { clamp } from "./math-utils/clamp.js";
5
+ import { interpolate } from "./motion-utils/interpolate.js";
6
+ import { resolveInterpolate, resolveMotionState } from "./motion-utils/resolveMotionState.js";
7
+ import { entries } from "./object-utils/entries.js";
8
+ import { flattenObj } from "./object-utils/flattenObj.js";
9
+ import { fromEntries } from "./object-utils/fromEntries.js";
10
+ import { keys } from "./object-utils/keys.js";
11
+ import { mapKeys } from "./object-utils/mapKeys.js";
12
+ import { mapValues } from "./object-utils/mapValues.js";
13
+ import { arrayToUnion } from "./string-utils/arrayToUnion.js";
14
+ import { capitalize } from "./string-utils/capitalize.js";
15
+ import { ComponentClassNames, componentClassNames, componentCompoundClass, componentDefaultClass, componentLayerClass, componentVariantClass } from "./string-utils/componentClassName.js";
16
+ import { createTemplate, interfaceTemplate, template, typeTemplate } from "./string-utils/createTemplate.js";
17
+ import { KebabCase, kebabCase } from "./string-utils/kebabCase.js";
18
+ import { CssVar, CssVarName, cssVar, cssVarDeclarations, cssVarName, safeTokenName } from "./string-utils/cssVar.js";
19
+ import { cssVars } from "./string-utils/cssVars.js";
20
+ import { dedent, dedentTS } from "./string-utils/dedent.js";
21
+ import { indent } from "./string-utils/indent.js";
22
+ import { join } from "./string-utils/join.js";
23
+ import { split } from "./string-utils/split.js";
24
+ import { tsProperties, tsTypes } from "./string-utils/tsProperties.js";
25
+ export { type ComponentClassNames, type ComponentStyleDefaultsInput, type CssVar, type CssVarName, type KebabCase, applyComponentStyleDefaults, arrayToUnion, capitalize, clamp, closestItem, componentClassNames, componentCompoundClass, componentDefaultClass, componentLayerClass, componentVariantClass, createTemplate, cssVar, cssVarDeclarations, cssVarName, cssVars, dedent, dedentTS, entries, flattenObj, fromEntries, indent, interfaceTemplate, interpolate, join, kebabCase, keys, mapKeys, mapValues, removeItem, resolveInterpolate, resolveMotionState, safeTokenName, split, template, tsProperties, tsTypes, typeTemplate };
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ import { applyComponentStyleDefaults } from "./component-style-defaults.js";
2
+ import { closestItem } from "./array-utils/closestItem.js";
3
+ import { removeItem } from "./array-utils/removeItem.js";
4
+ import { clamp } from "./math-utils/clamp.js";
5
+ import { interpolate } from "./motion-utils/interpolate.js";
6
+ import { resolveInterpolate, resolveMotionState } from "./motion-utils/resolveMotionState.js";
7
+ import { entries } from "./object-utils/entries.js";
8
+ import { flattenObj } from "./object-utils/flattenObj.js";
9
+ import { fromEntries } from "./object-utils/fromEntries.js";
10
+ import { keys } from "./object-utils/keys.js";
11
+ import { mapKeys } from "./object-utils/mapKeys.js";
12
+ import { mapValues } from "./object-utils/mapValues.js";
13
+ import { arrayToUnion } from "./string-utils/arrayToUnion.js";
14
+ import { capitalize } from "./string-utils/capitalize.js";
15
+ import { kebabCase } from "./string-utils/kebabCase.js";
16
+ import { componentClassNames, componentCompoundClass, componentDefaultClass, componentLayerClass, componentVariantClass } from "./string-utils/componentClassName.js";
17
+ import { createTemplate, interfaceTemplate, template, typeTemplate } from "./string-utils/createTemplate.js";
18
+ import { cssVar, cssVarDeclarations, cssVarName, safeTokenName } from "./string-utils/cssVar.js";
19
+ import { cssVars } from "./string-utils/cssVars.js";
20
+ import { dedent, dedentTS } from "./string-utils/dedent.js";
21
+ import { indent } from "./string-utils/indent.js";
22
+ import { join } from "./string-utils/join.js";
23
+ import { split } from "./string-utils/split.js";
24
+ import { tsProperties, tsTypes } from "./string-utils/tsProperties.js";
25
+ export { applyComponentStyleDefaults, arrayToUnion, capitalize, clamp, closestItem, componentClassNames, componentCompoundClass, componentDefaultClass, componentLayerClass, componentVariantClass, createTemplate, cssVar, cssVarDeclarations, cssVarName, cssVars, dedent, dedentTS, entries, flattenObj, fromEntries, indent, interfaceTemplate, interpolate, join, kebabCase, keys, mapKeys, mapValues, removeItem, resolveInterpolate, resolveMotionState, safeTokenName, split, template, tsProperties, tsTypes, typeTemplate };
@@ -0,0 +1,20 @@
1
+ //#region src/logger.d.ts
2
+ declare const logger: {
3
+ /** Enable `logger.debug()` output (set via `--verbose` flag). */setVerbose(value: boolean): void; /** Suppress everything except errors (set via `--quiet` flag). */
4
+ setQuiet(value: boolean): void;
5
+ /**
6
+ * Route stdout-bound logs to stderr. Enable when stdout carries a protocol
7
+ * stream that must stay free of log noise — e.g. the MCP stdio transport,
8
+ * where a stray banner line corrupts the JSON-RPC framing.
9
+ */
10
+ setStderr(value: boolean): void; /** Green check — a step completed successfully. */
11
+ success(message: string): void; /** Neutral informational message. */
12
+ info(message: string): void; /** Yellow warning — something is off but not fatal. */
13
+ warn(message: string): void; /** Red error — always printed, even in quiet mode. */
14
+ error(message: string, cause?: unknown): void; /** Indented sub-line for detail beneath a success/info message. */
15
+ detail(message: string): void; /** Only printed when `--verbose` is active. */
16
+ debug(message: string): void; /** Highlight a file path or URL inside a message. */
17
+ path(value: string): string;
18
+ };
19
+ //#endregion
20
+ export { logger };
package/dist/logger.js ADDED
@@ -0,0 +1,79 @@
1
+ //#region src/logger.ts
2
+ const PREFIX = "[uds]";
3
+ const isColorSupported = !process.env.NO_COLOR && process.stderr.isTTY !== false && process.stdout.isTTY !== false;
4
+ function green(text) {
5
+ return isColorSupported ? `\x1b[32m${text}\x1b[39m` : text;
6
+ }
7
+ function yellow(text) {
8
+ return isColorSupported ? `\x1b[33m${text}\x1b[39m` : text;
9
+ }
10
+ function red(text) {
11
+ return isColorSupported ? `\x1b[31m${text}\x1b[39m` : text;
12
+ }
13
+ function dim(text) {
14
+ return isColorSupported ? `\x1b[2m${text}\x1b[22m` : text;
15
+ }
16
+ function cyan(text) {
17
+ return isColorSupported ? `\x1b[36m${text}\x1b[39m` : text;
18
+ }
19
+ let verboseEnabled = false;
20
+ let quietEnabled = false;
21
+ let stderrEnabled = false;
22
+ function out(message) {
23
+ if (stderrEnabled) console.error(message);
24
+ else console.log(message);
25
+ }
26
+ const logger = {
27
+ /** Enable `logger.debug()` output (set via `--verbose` flag). */
28
+ setVerbose(value) {
29
+ verboseEnabled = value;
30
+ },
31
+ /** Suppress everything except errors (set via `--quiet` flag). */
32
+ setQuiet(value) {
33
+ quietEnabled = value;
34
+ },
35
+ /**
36
+ * Route stdout-bound logs to stderr. Enable when stdout carries a protocol
37
+ * stream that must stay free of log noise — e.g. the MCP stdio transport,
38
+ * where a stray banner line corrupts the JSON-RPC framing.
39
+ */
40
+ setStderr(value) {
41
+ stderrEnabled = value;
42
+ },
43
+ /** Green check — a step completed successfully. */
44
+ success(message) {
45
+ if (quietEnabled) return;
46
+ out(`${PREFIX} ${green("✓")} ${message}`);
47
+ },
48
+ /** Neutral informational message. */
49
+ info(message) {
50
+ if (quietEnabled) return;
51
+ out(`${PREFIX} ${message}`);
52
+ },
53
+ /** Yellow warning — something is off but not fatal. */
54
+ warn(message) {
55
+ if (quietEnabled) return;
56
+ console.warn(`${PREFIX} ${yellow("⚠")} ${message}`);
57
+ },
58
+ /** Red error — always printed, even in quiet mode. */
59
+ error(message, cause) {
60
+ if (cause !== void 0) console.error("%s %s %s", PREFIX, red("✗"), message, cause);
61
+ else console.error("%s %s %s", PREFIX, red("✗"), message);
62
+ },
63
+ /** Indented sub-line for detail beneath a success/info message. */
64
+ detail(message) {
65
+ if (quietEnabled) return;
66
+ out(`${PREFIX} ${dim(message)}`);
67
+ },
68
+ /** Only printed when `--verbose` is active. */
69
+ debug(message) {
70
+ if (!verboseEnabled) return;
71
+ out(dim(`${PREFIX} ${message}`));
72
+ },
73
+ /** Highlight a file path or URL inside a message. */
74
+ path(value) {
75
+ return cyan(value);
76
+ }
77
+ };
78
+ //#endregion
79
+ export { logger };
@@ -0,0 +1,12 @@
1
+ //#region src/math-utils/clamp.d.ts
2
+ /**
3
+ * Clamps a value between a lower and upper bound.
4
+ *
5
+ * @param value - The value to clamp.
6
+ * @param lower - The lower bound.
7
+ * @param upper - The upper bound.
8
+ * @returns The clamped value.
9
+ */
10
+ declare function clamp(value: number, lower: number, upper: number): number;
11
+ //#endregion
12
+ export { clamp };
@@ -0,0 +1,14 @@
1
+ //#region src/math-utils/clamp.ts
2
+ /**
3
+ * Clamps a value between a lower and upper bound.
4
+ *
5
+ * @param value - The value to clamp.
6
+ * @param lower - The lower bound.
7
+ * @param upper - The upper bound.
8
+ * @returns The clamped value.
9
+ */
10
+ function clamp(value, lower, upper) {
11
+ return Math.max(lower, Math.min(value, upper));
12
+ }
13
+ //#endregion
14
+ export { clamp };
@@ -0,0 +1,10 @@
1
+ //#region src/motion-utils/interpolate.d.ts
2
+ type ExtrapolateType = 'extend' | 'identity' | 'clamp';
3
+ declare function interpolate(input: number, inputRange: number[], outputRange: number[], options?: {
4
+ easing?: (input: number) => number;
5
+ extrapolate?: ExtrapolateType;
6
+ extrapolateLeft?: ExtrapolateType;
7
+ extrapolateRight?: ExtrapolateType;
8
+ }): number;
9
+ //#endregion
10
+ export { interpolate };
@@ -0,0 +1,25 @@
1
+ import { clamp } from "../math-utils/clamp.js";
2
+ //#region src/motion-utils/interpolate.ts
3
+ function interpolate(input, inputRange, outputRange, options = {}) {
4
+ const { easing, extrapolate = "extend", extrapolateLeft = extrapolate, extrapolateRight = extrapolate } = options;
5
+ if (inputRange.length !== outputRange.length) throw new Error("inputRange and outputRange must have the same length");
6
+ let segmentIndex = inputRange.findIndex((value, i) => input < value && i > 0) - 1;
7
+ if (segmentIndex === -2) segmentIndex = inputRange.length - 2;
8
+ let extrapolationType = extrapolate;
9
+ if (segmentIndex < 0) extrapolationType = extrapolateLeft;
10
+ else if (segmentIndex >= inputRange.length - 2) extrapolationType = extrapolateRight;
11
+ if (extrapolationType === "clamp") {
12
+ if (segmentIndex < 0) return outputRange[0];
13
+ if (segmentIndex >= inputRange.length - 2) return outputRange[outputRange.length - 1];
14
+ } else if (extrapolationType === "identity") return input;
15
+ const inputStart = inputRange[segmentIndex];
16
+ const inputEnd = inputRange[segmentIndex + 1];
17
+ const outputStart = outputRange[segmentIndex];
18
+ const outputEnd = outputRange[segmentIndex + 1];
19
+ let ratio = (input - inputStart) / (inputEnd - inputStart);
20
+ ratio = clamp(ratio, 0, 1);
21
+ if (easing) ratio = easing(ratio);
22
+ return outputStart + ratio * (outputEnd - outputStart);
23
+ }
24
+ //#endregion
25
+ export { interpolate };
@@ -0,0 +1,34 @@
1
+ //#region src/motion-utils/resolveMotionState.d.ts
2
+ /**
3
+ * Runtime helper for codegen's `__rms(stateKeyframe, index)` calls in
4
+ * multi-layer authoring sources that use `interpolate(...)` markers
5
+ * inside per-state motion keyframes. Given a state keyframe object
6
+ * whose values are either scalars or `interpolate({ output, extrapolate })`
7
+ * markers, resolves each marker against `index` and returns a plain
8
+ * keyframe object ready to spread onto `motion.<x>` props.
9
+ *
10
+ * Inlined `InterpolateMarker` shape rather than imported from
11
+ * `@yahoo/uds-create-config` so this stays a small leaf runtime helper.
12
+ */
13
+ interface InterpolateMarker {
14
+ __type: 'interpolate';
15
+ output: number[];
16
+ extrapolate: 'clamp' | 'extend' | 'identity';
17
+ }
18
+ /**
19
+ * Resolve a single `interpolate({ output, extrapolate })` marker against
20
+ * an integer-ish `index`. Output is a discrete lookup by index for
21
+ * `index < output.length`; beyond that, `extrapolate` chooses the
22
+ * extension rule (clamp / linear-extend / identity).
23
+ */
24
+ declare function resolveInterpolate(marker: InterpolateMarker, index: number): number;
25
+ /**
26
+ * Resolve every InterpolateMarker in a state keyframe object against
27
+ * `index`, leaving non-marker values unchanged. Used by codegen-emitted
28
+ * `__rms(...)` call sites — see
29
+ * `packages/codegen/src/build/get-styles/motion-transform.ts` for the
30
+ * call-site generation.
31
+ */
32
+ declare function resolveMotionState(stateKeyframe: Record<string, unknown>, index: number): Record<string, unknown>;
33
+ //#endregion
34
+ export { resolveInterpolate, resolveMotionState };