clava 0.2.1 → 0.2.3
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/CHANGELOG.md +20 -0
- package/dist/index.js +303 -232
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +506 -397
- package/src/utils.ts +47 -3
- package/tests/{component-api-test.ts → component-api.test.ts} +39 -0
- package/tests/{computed-test.ts → computed.test.ts} +57 -0
- package/tests/{extend-test.ts → extend.test.ts} +81 -0
- package/tests/prototype-pollution.test.ts +47 -0
- package/perfs/component.bench.ts +0 -233
- /package/tests/{class-style-test.ts → class-style.test.ts} +0 -0
- /package/tests/{computed-variants-test.ts → computed-variants.test.ts} +0 -0
- /package/tests/{language-service-test.ts → language-service.test.ts} +0 -0
- /package/tests/{react-test.ts → react.test.ts} +0 -0
- /package/tests/{solid-test.ts → solid.test.ts} +0 -0
- /package/tests/{split-props-test.ts → split-props.test.ts} +0 -0
- /package/tests/{variants-test.ts → variants.test.ts} +0 -0
package/src/utils.ts
CHANGED
|
@@ -11,6 +11,11 @@ export type Mode = (typeof MODES)[number];
|
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
12
12
|
const hasOwn = Object.prototype.hasOwnProperty;
|
|
13
13
|
|
|
14
|
+
function isAsciiLetter(code: number) {
|
|
15
|
+
if (code >= 65 && code <= 90) return true;
|
|
16
|
+
return code >= 97 && code <= 122;
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* Returns the appropriate class property name based on the mode.
|
|
16
21
|
* @example
|
|
@@ -33,8 +38,34 @@ export function hyphenToCamel(str: string) {
|
|
|
33
38
|
return str;
|
|
34
39
|
}
|
|
35
40
|
// Fast path: no hyphen -> return as-is
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
let hyphenIndex = str.indexOf("-");
|
|
42
|
+
if (hyphenIndex === -1) return str;
|
|
43
|
+
|
|
44
|
+
let result = "";
|
|
45
|
+
let lastIndex = 0;
|
|
46
|
+
while (hyphenIndex !== -1) {
|
|
47
|
+
result += str.slice(lastIndex, hyphenIndex);
|
|
48
|
+
|
|
49
|
+
const nextIndex = hyphenIndex + 1;
|
|
50
|
+
if (nextIndex >= str.length) {
|
|
51
|
+
result += "-";
|
|
52
|
+
lastIndex = nextIndex;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const code = str.charCodeAt(nextIndex);
|
|
57
|
+
if (isAsciiLetter(code)) {
|
|
58
|
+
result += str[nextIndex].toUpperCase();
|
|
59
|
+
lastIndex = nextIndex + 1;
|
|
60
|
+
} else {
|
|
61
|
+
result += "-";
|
|
62
|
+
lastIndex = nextIndex;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
hyphenIndex = str.indexOf("-", lastIndex);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result + str.slice(lastIndex);
|
|
38
69
|
}
|
|
39
70
|
|
|
40
71
|
/**
|
|
@@ -48,7 +79,20 @@ export function camelToHyphen(str: string) {
|
|
|
48
79
|
if (str.length >= 2 && str.charCodeAt(0) === 45 && str.charCodeAt(1) === 45) {
|
|
49
80
|
return str;
|
|
50
81
|
}
|
|
51
|
-
|
|
82
|
+
|
|
83
|
+
let result = "";
|
|
84
|
+
let lastIndex = 0;
|
|
85
|
+
for (let i = 0; i < str.length; i++) {
|
|
86
|
+
const code = str.charCodeAt(i);
|
|
87
|
+
if (code < 65 || code > 90) continue;
|
|
88
|
+
result += str.slice(lastIndex, i);
|
|
89
|
+
result += "-";
|
|
90
|
+
result += str[i].toLowerCase();
|
|
91
|
+
lastIndex = i + 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (lastIndex === 0) return str;
|
|
95
|
+
return result + str.slice(lastIndex);
|
|
52
96
|
}
|
|
53
97
|
|
|
54
98
|
/**
|
|
@@ -131,6 +131,45 @@ for (const config of Object.values(CONFIGS)) {
|
|
|
131
131
|
expect(variants).toEqual({ color: "blue" });
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
+
test("getVariants picks up setDefaultVariants from extended component", () => {
|
|
135
|
+
const base = cv({
|
|
136
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
137
|
+
computed: ({ setDefaultVariants }) => {
|
|
138
|
+
setDefaultVariants({ size: "lg" });
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
const component = getModeComponent(
|
|
142
|
+
mode,
|
|
143
|
+
cv({
|
|
144
|
+
extend: [base],
|
|
145
|
+
variants: { color: { red: "red", blue: "blue" } },
|
|
146
|
+
defaultVariants: { color: "red" },
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
const variants = component.getVariants();
|
|
150
|
+
expect(variants).toEqual({ size: "lg", color: "red" });
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("getVariants picks up setDefaultVariants from grandparent component", () => {
|
|
154
|
+
const grandparent = cv({
|
|
155
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
156
|
+
computed: ({ setDefaultVariants }) => {
|
|
157
|
+
setDefaultVariants({ size: "lg" });
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
const parent = cv({ extend: [grandparent] });
|
|
161
|
+
const component = getModeComponent(
|
|
162
|
+
mode,
|
|
163
|
+
cv({
|
|
164
|
+
extend: [parent],
|
|
165
|
+
variants: { color: { red: "red", blue: "blue" } },
|
|
166
|
+
defaultVariants: { color: "red" },
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
const variants = component.getVariants();
|
|
170
|
+
expect(variants).toEqual({ size: "lg", color: "red" });
|
|
171
|
+
});
|
|
172
|
+
|
|
134
173
|
test("keys returns props keys", () => {
|
|
135
174
|
const component = getModeComponent(
|
|
136
175
|
mode,
|
|
@@ -267,6 +267,63 @@ for (const config of Object.values(CONFIGS)) {
|
|
|
267
267
|
expect(getStyleClass(props)).toEqual({ class: cls("sm red") });
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
+
test("computed in extended component does not see foreign variant keys", () => {
|
|
271
|
+
const base = cv({
|
|
272
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
273
|
+
defaultVariants: { size: "sm" },
|
|
274
|
+
computed: ({ variants, addClass }) => {
|
|
275
|
+
// `color` is added by the parent component below — it must not
|
|
276
|
+
// leak into base's `ctx.variants`, whose shape is declared as
|
|
277
|
+
// `{ size }` only.
|
|
278
|
+
if ("color" in (variants as Record<string, unknown>)) {
|
|
279
|
+
addClass("base-saw-foreign");
|
|
280
|
+
} else {
|
|
281
|
+
addClass("base-no-foreign");
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
const component = getModeComponent(
|
|
286
|
+
mode,
|
|
287
|
+
cv({
|
|
288
|
+
extend: [base],
|
|
289
|
+
variants: { color: { red: "red", blue: "blue" } },
|
|
290
|
+
}),
|
|
291
|
+
);
|
|
292
|
+
const props = component({ color: "red" });
|
|
293
|
+
expect(getStyleClass(props)).toEqual({
|
|
294
|
+
class: cls("sm base-no-foreign red"),
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("setDefaultVariants in extended component does not branch on foreign variant keys", () => {
|
|
299
|
+
// Same shape as the test above, but the base's `computed` reaches
|
|
300
|
+
// `setDefaultVariants` — covers the resolveDefaults pass (driving
|
|
301
|
+
// both class output and `getVariants`) rather than the render-time
|
|
302
|
+
// compute path.
|
|
303
|
+
const base = cv({
|
|
304
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
305
|
+
defaultVariants: { size: "sm" },
|
|
306
|
+
computed: ({ variants, setDefaultVariants }) => {
|
|
307
|
+
if ("color" in (variants as Record<string, unknown>)) {
|
|
308
|
+
setDefaultVariants({ size: "lg" });
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
const component = getModeComponent(
|
|
313
|
+
mode,
|
|
314
|
+
cv({
|
|
315
|
+
extend: [base],
|
|
316
|
+
variants: { color: { red: "red", blue: "blue" } },
|
|
317
|
+
}),
|
|
318
|
+
);
|
|
319
|
+
const props = component({ color: "red" });
|
|
320
|
+
expect(getStyleClass(props)).toEqual({ class: cls("sm red") });
|
|
321
|
+
expect(component.getVariants({ color: "red" })).toEqual({
|
|
322
|
+
size: "sm",
|
|
323
|
+
color: "red",
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
270
327
|
test("child setDefaultVariants receives computed variants from parent", () => {
|
|
271
328
|
const base = cv({
|
|
272
329
|
variants: { size: { sm: "sm", lg: "lg" }, small: "" },
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { create } from "../src/index.ts";
|
|
2
3
|
import {
|
|
3
4
|
CONFIGS,
|
|
4
5
|
createCVFromConfig,
|
|
@@ -299,3 +300,83 @@ for (const config of Object.values(CONFIGS)) {
|
|
|
299
300
|
});
|
|
300
301
|
});
|
|
301
302
|
}
|
|
303
|
+
|
|
304
|
+
describe("non-idempotent transformClass", () => {
|
|
305
|
+
// A non-idempotent transform: prefixing each word with `tw-`. Applying it
|
|
306
|
+
// twice yields `tw-tw-foo`, so the engine must invoke it exactly once per
|
|
307
|
+
// class word — even when extend chains pipe extended base classes back into
|
|
308
|
+
// a parent's `clsx` and through the same transform at render time.
|
|
309
|
+
const { cv } = create({
|
|
310
|
+
transformClass: (className) =>
|
|
311
|
+
className
|
|
312
|
+
.split(" ")
|
|
313
|
+
.filter(Boolean)
|
|
314
|
+
.map((word) => `tw-${word}`)
|
|
315
|
+
.join(" "),
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("base class is transformed exactly once across single extend", () => {
|
|
319
|
+
const base = cv({ class: "base" });
|
|
320
|
+
const component = cv({ extend: [base], class: "extended" });
|
|
321
|
+
expect(component().class).toBe("tw-base tw-extended");
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test("base class is transformed exactly once across multi-level extend", () => {
|
|
325
|
+
const base = cv({ class: "base" });
|
|
326
|
+
const middle = cv({ extend: [base], class: "middle" });
|
|
327
|
+
const top = cv({
|
|
328
|
+
extend: [middle],
|
|
329
|
+
class: "top",
|
|
330
|
+
variants: { size: { sm: "sm" } },
|
|
331
|
+
});
|
|
332
|
+
expect(top({ size: "sm" }).class).toBe("tw-base tw-middle tw-top tw-sm");
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const toUpperCase = (className: string) => className.toUpperCase();
|
|
337
|
+
const toLowerCase = (className: string) => className.toLowerCase();
|
|
338
|
+
|
|
339
|
+
describe("extend across `create()` factories", () => {
|
|
340
|
+
// The extend's own `transformClass` must apply to its own classes even when
|
|
341
|
+
// the extending component comes from a different `create()` call. The
|
|
342
|
+
// optimized compute path bypasses the public-component round-trip, so it
|
|
343
|
+
// detects mixed-factory extends by reference identity and runs the extend's
|
|
344
|
+
// transform on its contribution before joining.
|
|
345
|
+
const { cv: cvUpper } = create({ transformClass: toUpperCase });
|
|
346
|
+
const { cv: cvDefault } = create();
|
|
347
|
+
|
|
348
|
+
test("extend's transformClass applies to its base class", () => {
|
|
349
|
+
const base = cvUpper({ class: "base" });
|
|
350
|
+
const component = cvDefault({ extend: [base], class: "extended" });
|
|
351
|
+
expect(component().class).toBe("BASE extended");
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("extend's transformClass applies to its variant classes", () => {
|
|
355
|
+
const base = cvUpper({
|
|
356
|
+
class: "base",
|
|
357
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
358
|
+
});
|
|
359
|
+
const component = cvDefault({ extend: [base], class: "extended" });
|
|
360
|
+
expect(component({ size: "sm" }).class).toBe("BASE extended SM");
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test("extend's transformClass cascades through grandparent chain", () => {
|
|
364
|
+
const grandparent = cvUpper({ class: "grandparent" });
|
|
365
|
+
const parent = cvUpper({ extend: [grandparent], class: "parent" });
|
|
366
|
+
const component = cvDefault({ extend: [parent], class: "child" });
|
|
367
|
+
expect(component().class).toBe("GRANDPARENT PARENT child");
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
test("parent's transformClass applies on top of extend's transformed output", () => {
|
|
371
|
+
const { cv: cvLower } = create({ transformClass: toLowerCase });
|
|
372
|
+
const base = cvUpper({
|
|
373
|
+
class: "base",
|
|
374
|
+
variants: { size: { sm: "sm" } },
|
|
375
|
+
});
|
|
376
|
+
const component = cvLower({ extend: [base], class: "child" });
|
|
377
|
+
// The extend uppercases its own contribution, then the parent's
|
|
378
|
+
// transformClass runs on the joined string and lowercases everything —
|
|
379
|
+
// mirrors main's `parentTransform(clsx(extTransform(extOutput), …))`.
|
|
380
|
+
expect(component({ size: "sm" }).class).toBe("base child sm");
|
|
381
|
+
});
|
|
382
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { afterEach, expect, test } from "vitest";
|
|
2
|
+
import { cv } from "../src/index.ts";
|
|
3
|
+
|
|
4
|
+
const proto = Object.prototype as Record<string, unknown>;
|
|
5
|
+
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
for (const key of Object.keys(proto)) {
|
|
8
|
+
delete proto[key];
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("getVariants ignores keys inherited from Object.prototype", () => {
|
|
13
|
+
proto.size = "lg";
|
|
14
|
+
const component = cv({
|
|
15
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
16
|
+
defaultVariants: { size: "sm" },
|
|
17
|
+
});
|
|
18
|
+
expect(component.getVariants({})).toEqual({ size: "sm" });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("render ignores keys inherited from Object.prototype", () => {
|
|
22
|
+
proto.size = "lg";
|
|
23
|
+
const component = cv({
|
|
24
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
25
|
+
defaultVariants: { size: "sm" },
|
|
26
|
+
});
|
|
27
|
+
expect(component({}).class).toBe("sm");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("extend's resolveDefaults ignores polluted prototype on parent's computed", () => {
|
|
31
|
+
// Base's computed branches on its own variants.size — if the polluted
|
|
32
|
+
// "size" key leaks into resolveDefaultsFn's resolvedVariants, the computed
|
|
33
|
+
// callback would see size = "lg" instead of the staticDefault "sm" and
|
|
34
|
+
// emit the lg-specific class.
|
|
35
|
+
proto.size = "lg";
|
|
36
|
+
const base = cv({
|
|
37
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
38
|
+
defaultVariants: { size: "sm" },
|
|
39
|
+
computed: ({ variants, addClass }) => {
|
|
40
|
+
if (variants.size === "lg") {
|
|
41
|
+
addClass("base-lg-detected");
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
const child = cv({ extend: [base], class: "child" });
|
|
46
|
+
expect(child({}).class).not.toContain("base-lg-detected");
|
|
47
|
+
});
|
package/perfs/component.bench.ts
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { bench, describe } from "vitest";
|
|
2
|
-
import { cv, splitProps } from "../src/index.ts";
|
|
3
|
-
|
|
4
|
-
const options = {
|
|
5
|
-
time: 2000,
|
|
6
|
-
warmupTime: 500,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
let sink: unknown;
|
|
10
|
-
|
|
11
|
-
function consume(value: unknown) {
|
|
12
|
-
sink = value;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const buttonConfig = {
|
|
16
|
-
class: "button inline-flex items-center justify-center",
|
|
17
|
-
style: {
|
|
18
|
-
borderRadius: "6px",
|
|
19
|
-
fontWeight: "600",
|
|
20
|
-
},
|
|
21
|
-
variants: {
|
|
22
|
-
size: {
|
|
23
|
-
sm: {
|
|
24
|
-
class: "button-sm",
|
|
25
|
-
style: { fontSize: "12px", paddingBlock: "4px", paddingInline: "8px" },
|
|
26
|
-
},
|
|
27
|
-
md: {
|
|
28
|
-
class: "button-md",
|
|
29
|
-
style: {
|
|
30
|
-
fontSize: "14px",
|
|
31
|
-
paddingBlock: "6px",
|
|
32
|
-
paddingInline: "12px",
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
lg: {
|
|
36
|
-
class: "button-lg",
|
|
37
|
-
style: {
|
|
38
|
-
fontSize: "16px",
|
|
39
|
-
paddingBlock: "8px",
|
|
40
|
-
paddingInline: "16px",
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
intent: {
|
|
45
|
-
primary: {
|
|
46
|
-
class: "button-primary",
|
|
47
|
-
style: { color: "white", backgroundColor: "blue" },
|
|
48
|
-
},
|
|
49
|
-
danger: {
|
|
50
|
-
class: "button-danger",
|
|
51
|
-
style: { color: "white", backgroundColor: "red" },
|
|
52
|
-
},
|
|
53
|
-
neutral: {
|
|
54
|
-
class: "button-neutral",
|
|
55
|
-
style: { color: "black", backgroundColor: "gray" },
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
disabled: {
|
|
59
|
-
true: {
|
|
60
|
-
class: "button-disabled",
|
|
61
|
-
style: { opacity: "0.5", pointerEvents: "none" },
|
|
62
|
-
},
|
|
63
|
-
false: "button-enabled",
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
defaultVariants: {
|
|
67
|
-
size: "md",
|
|
68
|
-
intent: "primary",
|
|
69
|
-
},
|
|
70
|
-
} as const;
|
|
71
|
-
|
|
72
|
-
const fieldConfig = {
|
|
73
|
-
class: "field",
|
|
74
|
-
variants: {
|
|
75
|
-
tone: {
|
|
76
|
-
plain: "field-plain",
|
|
77
|
-
invalid: {
|
|
78
|
-
class: "field-invalid",
|
|
79
|
-
style: { borderColor: "red", color: "red" },
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
compact: "field-compact",
|
|
83
|
-
},
|
|
84
|
-
defaultVariants: {
|
|
85
|
-
tone: "plain",
|
|
86
|
-
},
|
|
87
|
-
} as const;
|
|
88
|
-
|
|
89
|
-
const button = cv(buttonConfig);
|
|
90
|
-
const field = cv(fieldConfig);
|
|
91
|
-
const toolbarButton = cv({
|
|
92
|
-
extend: [button],
|
|
93
|
-
class: "toolbar-button",
|
|
94
|
-
variants: {
|
|
95
|
-
active: {
|
|
96
|
-
true: "toolbar-button-active",
|
|
97
|
-
false: "toolbar-button-idle",
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
computedVariants: {
|
|
101
|
-
intent: (value: unknown) => {
|
|
102
|
-
if (value === "danger") {
|
|
103
|
-
return {
|
|
104
|
-
class: "toolbar-button-danger",
|
|
105
|
-
style: { boxShadow: "0 0 0 1px red" },
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return null;
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
defaultVariants: {
|
|
112
|
-
active: false,
|
|
113
|
-
},
|
|
114
|
-
computed: ({ variants, addClass, addStyle, setDefaultVariants }) => {
|
|
115
|
-
if (variants.active) {
|
|
116
|
-
addClass("toolbar-button-pressed");
|
|
117
|
-
addStyle({ transform: "translateY(1px)" });
|
|
118
|
-
}
|
|
119
|
-
if (variants.size === "lg") {
|
|
120
|
-
setDefaultVariants({ intent: "neutral" });
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const splitPropsInput = {
|
|
126
|
-
id: "save",
|
|
127
|
-
type: "button",
|
|
128
|
-
size: "lg",
|
|
129
|
-
intent: "danger",
|
|
130
|
-
disabled: true,
|
|
131
|
-
tone: "invalid",
|
|
132
|
-
compact: true,
|
|
133
|
-
active: true,
|
|
134
|
-
className: "custom",
|
|
135
|
-
style: "margin-top: 4px; --accent-color: red;",
|
|
136
|
-
"data-testid": "save",
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
describe("cv", () => {
|
|
140
|
-
bench(
|
|
141
|
-
"create component with variants",
|
|
142
|
-
() => {
|
|
143
|
-
consume(cv(buttonConfig));
|
|
144
|
-
},
|
|
145
|
-
options,
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
bench(
|
|
149
|
-
"resolve component props",
|
|
150
|
-
() => {
|
|
151
|
-
consume(
|
|
152
|
-
button({
|
|
153
|
-
size: "lg",
|
|
154
|
-
intent: "danger",
|
|
155
|
-
disabled: true,
|
|
156
|
-
className: "custom",
|
|
157
|
-
style: { marginTop: 4 },
|
|
158
|
-
}),
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
options,
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
bench(
|
|
165
|
-
"resolve html props from string style",
|
|
166
|
-
() => {
|
|
167
|
-
consume(
|
|
168
|
-
button.html({
|
|
169
|
-
size: "sm",
|
|
170
|
-
intent: "neutral",
|
|
171
|
-
style: "margin-top: 4px; --accent-color: blue;",
|
|
172
|
-
}),
|
|
173
|
-
);
|
|
174
|
-
},
|
|
175
|
-
options,
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
bench(
|
|
179
|
-
"resolve extended computed props",
|
|
180
|
-
() => {
|
|
181
|
-
consume(
|
|
182
|
-
toolbarButton({
|
|
183
|
-
size: "lg",
|
|
184
|
-
intent: "danger",
|
|
185
|
-
active: true,
|
|
186
|
-
class: "custom",
|
|
187
|
-
style: { marginInlineStart: 4 },
|
|
188
|
-
}),
|
|
189
|
-
);
|
|
190
|
-
},
|
|
191
|
-
options,
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
bench(
|
|
195
|
-
"get variant values",
|
|
196
|
-
() => {
|
|
197
|
-
consume(
|
|
198
|
-
toolbarButton.getVariants({
|
|
199
|
-
size: "lg",
|
|
200
|
-
active: true,
|
|
201
|
-
}),
|
|
202
|
-
);
|
|
203
|
-
},
|
|
204
|
-
options,
|
|
205
|
-
);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe("splitProps", () => {
|
|
209
|
-
bench(
|
|
210
|
-
"split props across components",
|
|
211
|
-
() => {
|
|
212
|
-
consume(splitProps(splitPropsInput, toolbarButton, field));
|
|
213
|
-
},
|
|
214
|
-
options,
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
bench(
|
|
218
|
-
"split props across arrays and components",
|
|
219
|
-
() => {
|
|
220
|
-
consume(
|
|
221
|
-
splitProps(
|
|
222
|
-
splitPropsInput,
|
|
223
|
-
["id", "type", "data-testid"],
|
|
224
|
-
toolbarButton,
|
|
225
|
-
field,
|
|
226
|
-
),
|
|
227
|
-
);
|
|
228
|
-
},
|
|
229
|
-
options,
|
|
230
|
-
);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
export { sink };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|