@bamboocss/generator 1.46.3 → 1.47.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.
- package/dist/index.cjs +41 -174
- package/dist/index.d.cts +5 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.mjs +41 -174
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -109,8 +109,6 @@ function generateConditions(ctx) {
|
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/artifacts/js/css-fn.ts
|
|
111
111
|
function generateCssFn(ctx) {
|
|
112
|
-
const { utility, hash, prefix } = ctx;
|
|
113
|
-
const { separator } = utility;
|
|
114
112
|
return {
|
|
115
113
|
dts: outdent.outdent`
|
|
116
114
|
${ctx.file.importType("SystemStyleObject, ViewTransitionFn", "../types/index")}
|
|
@@ -161,39 +159,12 @@ function generateCssFn(ctx) {
|
|
|
161
159
|
|
|
162
160
|
`,
|
|
163
161
|
js: outdent.outdent`
|
|
164
|
-
${ctx.file.import("cloneStyles,
|
|
165
|
-
${ctx.file.import("
|
|
166
|
-
${ctx.file.import("classNameByProp", "./utilities")}
|
|
167
|
-
${ctx.file.import("mergeCss, mergeCssUncached, resolveShorthand", "./merge-css")}
|
|
168
|
-
|
|
169
|
-
const context = {
|
|
170
|
-
${hash.className ? "hash: true," : ""}
|
|
171
|
-
conditions: {
|
|
172
|
-
shift: sortConditions,
|
|
173
|
-
finalize: finalizeConditions,
|
|
174
|
-
},
|
|
175
|
-
utility: {
|
|
176
|
-
${prefix.className ? "prefix: " + JSON.stringify(prefix.className) + "," : ""}
|
|
177
|
-
transform: ${utility.hasShorthand ? `(prop, value) => {
|
|
178
|
-
const key = resolveShorthand(prop)
|
|
179
|
-
const propKey = classNameByProp.get(key) || hypenateProperty(key)
|
|
180
|
-
return { className: \`$\{propKey}${separator}$\{withoutSpace(value)}\` }
|
|
181
|
-
}` : `(key, value) => ({ className: \`$\{classNameByProp.get(key) || hypenateProperty(key)}${separator}$\{withoutSpace(value)}\` })`},
|
|
182
|
-
${utility.hasShorthand ? "hasShorthand: true," : ""}
|
|
183
|
-
toHash: ${utility.toHash},
|
|
184
|
-
resolveShorthand: ${utility.hasShorthand ? "resolveShorthand" : "prop => prop"},
|
|
185
|
-
}
|
|
186
|
-
}
|
|
162
|
+
${ctx.file.import("cloneStyles, uncompiledStyle", "../helpers")}
|
|
163
|
+
${ctx.file.import("mergeCss", "./merge-css")}
|
|
187
164
|
|
|
188
|
-
const
|
|
189
|
-
// \`
|
|
190
|
-
//
|
|
191
|
-
// have not been seen — so a second cache keyed on the same arguments, or on the merge
|
|
192
|
-
// derived from them, can only miss too, after paying for the lookup.
|
|
193
|
-
export const css = /* @__PURE__ */ memo((...styles) => cssFn(mergeCssUncached(...styles)))
|
|
194
|
-
// The cached merge here, since \`raw\` is called straight from user code with no memo
|
|
195
|
-
// above it. The merged result is cached and shared, so a caller mutating a nested
|
|
196
|
-
// condition object would otherwise poison it for everyone after them.
|
|
165
|
+
export const css = (..._styles) => uncompiledStyle('css')
|
|
166
|
+
// \`raw\` is a style object, not a class string. The compiler leaves it; \`css(css.raw(...))\`
|
|
167
|
+
// is what has to fold.
|
|
197
168
|
css.raw = (...styles) => cloneStyles(mergeCss(...styles))
|
|
198
169
|
|
|
199
170
|
// Sugar for the string form, so the feature has an import to discover, a signature to
|
|
@@ -201,10 +172,7 @@ function generateCssFn(ctx) {
|
|
|
201
172
|
// value reaching \`css()\` is the same literal either way.
|
|
202
173
|
export const fallback = (...values) => \`fallback($\{values.join(', ')})\`
|
|
203
174
|
|
|
204
|
-
|
|
205
|
-
// from the same options, hashed by this same function. A call the extractor never saw
|
|
206
|
-
// still returns a class, exactly as \`css()\` does for a value it never saw.
|
|
207
|
-
export const viewTransition = (options) => viewTransitionClassName(options, ${JSON.stringify(prefix.className ?? "")})
|
|
175
|
+
export const viewTransition = (_options) => uncompiledStyle('viewTransition')
|
|
208
176
|
|
|
209
177
|
`
|
|
210
178
|
};
|
|
@@ -310,7 +278,7 @@ function generateCvaFn(ctx) {
|
|
|
310
278
|
const withPrefix = prefix.className ? `(className) => className ? ${JSON.stringify(prefix.className)} + '-' + className : ${JSON.stringify(prefix.className)}` : `(className) => className`;
|
|
311
279
|
return {
|
|
312
280
|
js: outdent.outdent`
|
|
313
|
-
${ctx.file.import("cloneStyles, compact,
|
|
281
|
+
${ctx.file.import("cloneStyles, compact, getRecipeIdentity, mergeProps, memo, splitProps, toHash, uniq, uncompiledStyle", "../helpers")}
|
|
314
282
|
${ctx.file.import("mergeCss", "./merge-css")}
|
|
315
283
|
${ctx.file.import("cx", "./cx")}
|
|
316
284
|
|
|
@@ -380,8 +348,8 @@ function generateCvaFn(ctx) {
|
|
|
380
348
|
// Compound variants are absent on purpose. Their rule selects on the variant classes
|
|
381
349
|
// already in this list — \`.btn--size_sm.btn--tone_a\` — so it applies without anything
|
|
382
350
|
// being added here, and adding a class for it would name a rule that does not exist.
|
|
383
|
-
function cvaFn(
|
|
384
|
-
return
|
|
351
|
+
function cvaFn(_props) {
|
|
352
|
+
return uncompiledStyle('cva')
|
|
385
353
|
}
|
|
386
354
|
|
|
387
355
|
const variantKeys = Object.keys(variants)
|
|
@@ -634,6 +602,18 @@ function generateHelpers() {
|
|
|
634
602
|
export function __objRest(source, exclude) {
|
|
635
603
|
return Object.fromEntries(Object.entries(source).filter(([key]) => !exclude.includes(key)))
|
|
636
604
|
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Style-producing calls compile away. Hitting this means \`@bamboocss/vite\` did not fold
|
|
608
|
+
* the call — missing plugin, a file outside \`include\`, or a shape the compiler rejects.
|
|
609
|
+
*/
|
|
610
|
+
export function uncompiledStyle(name) {
|
|
611
|
+
throw new Error(
|
|
612
|
+
'bamboocss: ' +
|
|
613
|
+
name +
|
|
614
|
+
'() was not compiled. Add \`bamboocss()\` from \`@bamboocss/vite\` and import \`virtual:bamboo.css\`. See https://bamboocss.com/docs/installation/vite',
|
|
615
|
+
)
|
|
616
|
+
}
|
|
637
617
|
` };
|
|
638
618
|
}
|
|
639
619
|
//#endregion
|
|
@@ -752,7 +732,7 @@ function generatePattern(ctx, filters) {
|
|
|
752
732
|
transform,
|
|
753
733
|
defaultValues
|
|
754
734
|
})) ?? "";
|
|
755
|
-
const helperImports = ["getPatternStyles, createPatternFns
|
|
735
|
+
const helperImports = ["getPatternStyles, createPatternFns"];
|
|
756
736
|
if (patternConfigFn.includes("__spreadValues")) helperImports.push("__spreadValues");
|
|
757
737
|
if (patternConfigFn.includes("__objRest")) helperImports.push("__objRest");
|
|
758
738
|
return {
|
|
@@ -785,8 +765,7 @@ function generatePattern(ctx, filters) {
|
|
|
785
765
|
|
|
786
766
|
`,
|
|
787
767
|
js: outdent.outdent`
|
|
788
|
-
${ctx.file.import(helperImports.join(", "), "../helpers")}
|
|
789
|
-
${ctx.file.import("css", "../css/index")}
|
|
768
|
+
${ctx.file.import([...helperImports, "uncompiledStyle"].join(", "), "../helpers")}
|
|
790
769
|
${ctx.file.import("token", "../tokens/index")}
|
|
791
770
|
|
|
792
771
|
/**
|
|
@@ -806,7 +785,7 @@ function generatePattern(ctx, filters) {
|
|
|
806
785
|
return ${baseName}Config.transform(_styles, patternHelpers)
|
|
807
786
|
}
|
|
808
787
|
|
|
809
|
-
export const ${baseName} =
|
|
788
|
+
export const ${baseName} = (styles) => uncompiledStyle(${JSON.stringify(baseName)})
|
|
810
789
|
${baseName}.raw = ${styleFnName}
|
|
811
790
|
`
|
|
812
791
|
};
|
|
@@ -859,55 +838,12 @@ function generateCreateRecipe(ctx) {
|
|
|
859
838
|
name: "create-recipe",
|
|
860
839
|
dts: "",
|
|
861
840
|
js: outdent.outdent`
|
|
862
|
-
${ctx.file.import("
|
|
863
|
-
${ctx.file.import("assertCompoundVariant, getCompoundVariantCss", "../css/cva")}
|
|
864
|
-
${ctx.file.import("cx", "../css/cx")}
|
|
865
|
-
${ctx.file.import("compact, createCssUncached, getRecipeClassNames, splitProps, toHash, uniq, withoutSpace", "../helpers")}
|
|
841
|
+
${ctx.file.import(hash.className ? "compact, splitProps, toHash, uniq, uncompiledStyle" : "compact, splitProps, uniq, uncompiledStyle", "../helpers")}
|
|
866
842
|
|
|
867
|
-
/**
|
|
868
|
-
* What \`createCss\` does to a class name: prefix it, and hash it when \`hash.className\`
|
|
869
|
-
* is set.
|
|
870
|
-
*
|
|
871
|
-
* A slot that takes variants gets this for free, because its classes come from
|
|
872
|
-
* \`createCss\`. A *scoped* slot's class never goes through it — it is a constant — so it
|
|
873
|
-
* has to be formatted here or the runtime hands back a raw name while the stylesheet
|
|
874
|
-
* emits the rule under a hashed one, and the slot renders unstyled.
|
|
875
|
-
*/
|
|
876
843
|
const withPrefix = ${prefix.className ? `(className) => className ? ${JSON.stringify(prefix.className)} + '-' + className : ${JSON.stringify(prefix.className)}` : `(className) => className`}
|
|
877
844
|
export const formatRecipeClass = ${hash.className ? `(className) => withPrefix((${utility.toHash})([className], toHash))` : `withPrefix`}
|
|
878
845
|
|
|
879
|
-
export const createRecipe = (name, defaultVariants,
|
|
880
|
-
/**
|
|
881
|
-
* \`variantMap\` as \`getRecipeClassNames\` wants it — value *keys* rather than a list.
|
|
882
|
-
*
|
|
883
|
-
* Built once per recipe at module init. The lookup needs \`Object.hasOwn\`, and an array
|
|
884
|
-
* answers that for its indices rather than its contents, so a list cannot be passed
|
|
885
|
-
* straight through.
|
|
886
|
-
*/
|
|
887
|
-
const variantValues = variantMap
|
|
888
|
-
? Object.fromEntries(
|
|
889
|
-
Object.entries(variantMap).map(([variant, values]) => [
|
|
890
|
-
variant,
|
|
891
|
-
Object.fromEntries(values.map((value) => [value, true])),
|
|
892
|
-
]),
|
|
893
|
-
)
|
|
894
|
-
: undefined
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
* Whether every selected value is a plain scalar, and so nameable without \`createCss\`.
|
|
898
|
-
*
|
|
899
|
-
* \`typeof value === 'object'\` covers a conditional value like \`{ base: 'sm', md: 'lg' }\`,
|
|
900
|
-
* whose classes carry condition prefixes only \`createCss\` can build. It also catches
|
|
901
|
-
* \`null\`, which \`compact\` keeps — that goes to the path below and comes out as it did
|
|
902
|
-
* before, since \`createCss\` names no class for a null value either.
|
|
903
|
-
*/
|
|
904
|
-
const isScalarSelection = (declared) => {
|
|
905
|
-
for (const key in declared) {
|
|
906
|
-
if (typeof declared[key] === 'object') return false
|
|
907
|
-
}
|
|
908
|
-
return true
|
|
909
|
-
}
|
|
910
|
-
|
|
846
|
+
export const createRecipe = (name, defaultVariants, _compoundVariants, _variantMap) => {
|
|
911
847
|
const getVariantProps = (variants) => {
|
|
912
848
|
return {
|
|
913
849
|
[name]: '__ignore__',
|
|
@@ -916,82 +852,12 @@ function generateCreateRecipe(ctx) {
|
|
|
916
852
|
};
|
|
917
853
|
};
|
|
918
854
|
|
|
919
|
-
const recipeFn = (
|
|
920
|
-
const declaredProps = getVariantProps(variants)
|
|
921
|
-
|
|
922
|
-
// A scalar selection names its classes by lookup: the recipe's own class plus one per
|
|
923
|
-
// selected variant, which is all \`createCss\` was deriving here. Measured at 4.1x the
|
|
924
|
-
// \`createCss\` path on a three-variant recipe. The gain is on a \`memo\` miss — the first
|
|
925
|
-
// call for each variant combination — since a hit never reaches this at all.
|
|
926
|
-
//
|
|
927
|
-
// Compound variants stay absent, as they are on the path below: their rule selects on the
|
|
928
|
-
// variant classes already named, so it applies without one of its own.
|
|
929
|
-
if (variantValues && isScalarSelection(declaredProps)) {
|
|
930
|
-
return getRecipeClassNames(name, variantValues, declaredProps, '${utility.separator}', formatRecipeClass)
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
const transform = (prop, value) => {
|
|
934
|
-
assertCompoundVariant(name, compoundVariants, variants, prop)
|
|
935
|
-
|
|
936
|
-
if (value === '__ignore__') {
|
|
937
|
-
return { className: name }
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
value = withoutSpace(value)
|
|
941
|
-
return { className: \`\${name}--\${prop}${utility.separator}\${value}\` }
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
// Uncached: this runs *inside* \`recipeFn\`, which is itself memoized, so the cache a
|
|
945
|
-
// cached \`createCss\` would build here is constructed fresh per call and used once.
|
|
946
|
-
const recipeCss = createCssUncached({
|
|
947
|
-
${hash.className ? "hash: true," : ""}
|
|
948
|
-
conditions: {
|
|
949
|
-
shift: sortConditions,
|
|
950
|
-
finalize: finalizeConditions,
|
|
951
|
-
},
|
|
952
|
-
utility: {
|
|
953
|
-
${prefix.className ? "prefix: " + JSON.stringify(prefix.className) + "," : ""}
|
|
954
|
-
toHash: ${utility.toHash},
|
|
955
|
-
transform,
|
|
956
|
-
}
|
|
957
|
-
})
|
|
958
|
-
|
|
959
|
-
// Only what the config declares names a class.
|
|
960
|
-
//
|
|
961
|
-
// Without this the transform named one for *any* prop it was handed — the build emits
|
|
962
|
-
// rules only for declared values, so the element carried a class nothing backed. It also
|
|
963
|
-
// disagreed with \`cva\`, which skips an undeclared value, leaving the two recipe kinds
|
|
964
|
-
// with different class strings for the same call.
|
|
965
|
-
//
|
|
966
|
-
// Filtered here rather than in \`getVariantProps\`, which is public and is what compound
|
|
967
|
-
// variants are matched against.
|
|
968
|
-
const declared = declaredProps
|
|
969
|
-
const recipeStyles = variantMap
|
|
970
|
-
? Object.fromEntries(
|
|
971
|
-
Object.entries(declared).filter(([prop, value]) => {
|
|
972
|
-
if (prop === name) return true
|
|
973
|
-
// A conditional or responsive value is an object of leaves, and the leaves are
|
|
974
|
-
// what name classes: createCss walks them and calls transform per condition.
|
|
975
|
-
// Only a scalar can be judged here.
|
|
976
|
-
if (value === null || typeof value === 'object') return true
|
|
977
|
-
return Object.hasOwn(variantMap, prop) && variantMap[prop].includes(String(value))
|
|
978
|
-
}),
|
|
979
|
-
)
|
|
980
|
-
: declared
|
|
981
|
-
|
|
982
|
-
// No class for the compound variants. Their rule selects on the variant classes
|
|
983
|
-
// \`recipeCss\` just named — \`.btn--size_sm.btn--tone_a\` — so it applies on its own,
|
|
984
|
-
// and it is in the same layer as the rest of the recipe rather than atomically in
|
|
985
|
-
// \`utilities\` above it.
|
|
986
|
-
return recipeCss(recipeStyles)
|
|
987
|
-
}
|
|
855
|
+
const recipeFn = (_variants) => uncompiledStyle(name)
|
|
988
856
|
|
|
989
857
|
return {
|
|
990
858
|
recipeFn,
|
|
991
859
|
getVariantProps,
|
|
992
|
-
__getCompoundVariantCss__: (
|
|
993
|
-
return getCompoundVariantCss(compoundVariants, getVariantProps(variants));
|
|
994
|
-
},
|
|
860
|
+
__getCompoundVariantCss__: (_variants) => uncompiledStyle(name),
|
|
995
861
|
}
|
|
996
862
|
}
|
|
997
863
|
|
|
@@ -999,7 +865,7 @@ function generateCreateRecipe(ctx) {
|
|
|
999
865
|
if (recipeA && !recipeB) return recipeA
|
|
1000
866
|
if (!recipeA && recipeB) return recipeB
|
|
1001
867
|
|
|
1002
|
-
const recipeFn = (...
|
|
868
|
+
const recipeFn = (..._args) => uncompiledStyle(recipeA.__name__ || 'recipe')
|
|
1003
869
|
const variantKeys = uniq(Object.keys(recipeA.variantMap), Object.keys(recipeB.variantMap))
|
|
1004
870
|
const variantMap = variantKeys.reduce((acc, key) => {
|
|
1005
871
|
acc[key] = uniq(recipeA.variantMap[key], recipeB.variantMap[key])
|
|
@@ -1195,7 +1061,7 @@ function generateRecipes(ctx, filters) {
|
|
|
1195
1061
|
function generateSvaFn(ctx) {
|
|
1196
1062
|
return {
|
|
1197
1063
|
js: outdent.outdent`
|
|
1198
|
-
${ctx.file.import("compact, getRecipeIdentity, getSlotRecipes, memo, splitProps", "../helpers")}
|
|
1064
|
+
${ctx.file.import("compact, getRecipeIdentity, getSlotRecipes, memo, splitProps, uncompiledStyle", "../helpers")}
|
|
1199
1065
|
${ctx.file.import("cva, formatRecipeClass", "./cva")}
|
|
1200
1066
|
${ctx.file.import("cx", "./cx")}
|
|
1201
1067
|
|
|
@@ -1237,12 +1103,8 @@ function generateSvaFn(ctx) {
|
|
|
1237
1103
|
// atomic and nothing else carried the name to target it in the DOM. The slot's cva is
|
|
1238
1104
|
// now named \`name__slot\` and returns that as its base class, so joining it again
|
|
1239
1105
|
// would just repeat it.
|
|
1240
|
-
function svaFn(
|
|
1241
|
-
|
|
1242
|
-
slot,
|
|
1243
|
-
anchors.length && !anchors.includes(slot) ? formatRecipeClass(cvaFn.config.className) : cvaFn(props),
|
|
1244
|
-
])
|
|
1245
|
-
return Object.fromEntries(result)
|
|
1106
|
+
function svaFn(_props) {
|
|
1107
|
+
return uncompiledStyle('sva')
|
|
1246
1108
|
}
|
|
1247
1109
|
|
|
1248
1110
|
function raw(props) {
|
|
@@ -4279,7 +4141,7 @@ var Generator = class extends _bamboocss_core.Context {
|
|
|
4279
4141
|
* Get all split CSS artifacts for the stylesheet
|
|
4280
4142
|
* Used when --splitting flag is enabled
|
|
4281
4143
|
*/
|
|
4282
|
-
getSplitCssArtifacts = (sheet) => {
|
|
4144
|
+
getSplitCssArtifacts = (sheet, { includeRecipes = false } = {}) => {
|
|
4283
4145
|
const layerNames = this.config.layers;
|
|
4284
4146
|
const decoder = this.decoder.collect(this.encoder);
|
|
4285
4147
|
const layers = [
|
|
@@ -4310,7 +4172,7 @@ var Generator = class extends _bamboocss_core.Context {
|
|
|
4310
4172
|
code: l.css
|
|
4311
4173
|
}));
|
|
4312
4174
|
const recipes = [];
|
|
4313
|
-
for (const recipeName of this.recipes.keys) {
|
|
4175
|
+
if (includeRecipes) for (const recipeName of this.recipes.keys) {
|
|
4314
4176
|
const recipeSheet = this.createSheet();
|
|
4315
4177
|
recipeSheet.processDecoderForRecipe(decoder, recipeName);
|
|
4316
4178
|
const code = recipeSheet.getLayerCss("recipes");
|
|
@@ -4334,13 +4196,18 @@ var Generator = class extends _bamboocss_core.Context {
|
|
|
4334
4196
|
});
|
|
4335
4197
|
}
|
|
4336
4198
|
const recipesIndex = recipes.map((r) => `@import './recipes/${r.file}';`).join("\n");
|
|
4337
|
-
const imports = [`@layer ${[
|
|
4199
|
+
const imports = [`@layer ${(includeRecipes ? [
|
|
4338
4200
|
layerNames.reset,
|
|
4339
4201
|
layerNames.base,
|
|
4340
4202
|
layerNames.tokens,
|
|
4341
4203
|
layerNames.recipes,
|
|
4342
4204
|
layerNames.utilities
|
|
4343
|
-
]
|
|
4205
|
+
] : [
|
|
4206
|
+
layerNames.reset,
|
|
4207
|
+
layerNames.base,
|
|
4208
|
+
layerNames.tokens,
|
|
4209
|
+
layerNames.utilities
|
|
4210
|
+
]).join(", ")};`, ""];
|
|
4344
4211
|
for (const layer of layers) imports.push(`@import './styles/${layer.file}';`);
|
|
4345
4212
|
if (recipes.length) imports.push(`@import './styles/recipes.css';`);
|
|
4346
4213
|
return {
|
package/dist/index.d.cts
CHANGED
|
@@ -208,7 +208,11 @@ declare class Generator extends Context {
|
|
|
208
208
|
* Get all split CSS artifacts for the stylesheet
|
|
209
209
|
* Used when --splitting flag is enabled
|
|
210
210
|
*/
|
|
211
|
-
getSplitCssArtifacts: (sheet: Stylesheet
|
|
211
|
+
getSplitCssArtifacts: (sheet: Stylesheet, {
|
|
212
|
+
includeRecipes
|
|
213
|
+
}?: {
|
|
214
|
+
includeRecipes?: boolean;
|
|
215
|
+
}) => SplitCssResult;
|
|
212
216
|
getSpec: () => SpecFile[];
|
|
213
217
|
getSpecOfType: <T extends SpecType>(type: T) => T extends "color-palette" | "themes" ? SpecTypeMap[T] | undefined : SpecTypeMap[T];
|
|
214
218
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -208,7 +208,11 @@ declare class Generator extends Context {
|
|
|
208
208
|
* Get all split CSS artifacts for the stylesheet
|
|
209
209
|
* Used when --splitting flag is enabled
|
|
210
210
|
*/
|
|
211
|
-
getSplitCssArtifacts: (sheet: Stylesheet
|
|
211
|
+
getSplitCssArtifacts: (sheet: Stylesheet, {
|
|
212
|
+
includeRecipes
|
|
213
|
+
}?: {
|
|
214
|
+
includeRecipes?: boolean;
|
|
215
|
+
}) => SplitCssResult;
|
|
212
216
|
getSpec: () => SpecFile[];
|
|
213
217
|
getSpecOfType: <T extends SpecType>(type: T) => T extends "color-palette" | "themes" ? SpecTypeMap[T] | undefined : SpecTypeMap[T];
|
|
214
218
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -83,8 +83,6 @@ function generateConditions(ctx) {
|
|
|
83
83
|
//#endregion
|
|
84
84
|
//#region src/artifacts/js/css-fn.ts
|
|
85
85
|
function generateCssFn(ctx) {
|
|
86
|
-
const { utility, hash, prefix } = ctx;
|
|
87
|
-
const { separator } = utility;
|
|
88
86
|
return {
|
|
89
87
|
dts: outdent`
|
|
90
88
|
${ctx.file.importType("SystemStyleObject, ViewTransitionFn", "../types/index")}
|
|
@@ -135,39 +133,12 @@ function generateCssFn(ctx) {
|
|
|
135
133
|
|
|
136
134
|
`,
|
|
137
135
|
js: outdent`
|
|
138
|
-
${ctx.file.import("cloneStyles,
|
|
139
|
-
${ctx.file.import("
|
|
140
|
-
${ctx.file.import("classNameByProp", "./utilities")}
|
|
141
|
-
${ctx.file.import("mergeCss, mergeCssUncached, resolveShorthand", "./merge-css")}
|
|
142
|
-
|
|
143
|
-
const context = {
|
|
144
|
-
${hash.className ? "hash: true," : ""}
|
|
145
|
-
conditions: {
|
|
146
|
-
shift: sortConditions,
|
|
147
|
-
finalize: finalizeConditions,
|
|
148
|
-
},
|
|
149
|
-
utility: {
|
|
150
|
-
${prefix.className ? "prefix: " + JSON.stringify(prefix.className) + "," : ""}
|
|
151
|
-
transform: ${utility.hasShorthand ? `(prop, value) => {
|
|
152
|
-
const key = resolveShorthand(prop)
|
|
153
|
-
const propKey = classNameByProp.get(key) || hypenateProperty(key)
|
|
154
|
-
return { className: \`$\{propKey}${separator}$\{withoutSpace(value)}\` }
|
|
155
|
-
}` : `(key, value) => ({ className: \`$\{classNameByProp.get(key) || hypenateProperty(key)}${separator}$\{withoutSpace(value)}\` })`},
|
|
156
|
-
${utility.hasShorthand ? "hasShorthand: true," : ""}
|
|
157
|
-
toHash: ${utility.toHash},
|
|
158
|
-
resolveShorthand: ${utility.hasShorthand ? "resolveShorthand" : "prop => prop"},
|
|
159
|
-
}
|
|
160
|
-
}
|
|
136
|
+
${ctx.file.import("cloneStyles, uncompiledStyle", "../helpers")}
|
|
137
|
+
${ctx.file.import("mergeCss", "./merge-css")}
|
|
161
138
|
|
|
162
|
-
const
|
|
163
|
-
// \`
|
|
164
|
-
//
|
|
165
|
-
// have not been seen — so a second cache keyed on the same arguments, or on the merge
|
|
166
|
-
// derived from them, can only miss too, after paying for the lookup.
|
|
167
|
-
export const css = /* @__PURE__ */ memo((...styles) => cssFn(mergeCssUncached(...styles)))
|
|
168
|
-
// The cached merge here, since \`raw\` is called straight from user code with no memo
|
|
169
|
-
// above it. The merged result is cached and shared, so a caller mutating a nested
|
|
170
|
-
// condition object would otherwise poison it for everyone after them.
|
|
139
|
+
export const css = (..._styles) => uncompiledStyle('css')
|
|
140
|
+
// \`raw\` is a style object, not a class string. The compiler leaves it; \`css(css.raw(...))\`
|
|
141
|
+
// is what has to fold.
|
|
171
142
|
css.raw = (...styles) => cloneStyles(mergeCss(...styles))
|
|
172
143
|
|
|
173
144
|
// Sugar for the string form, so the feature has an import to discover, a signature to
|
|
@@ -175,10 +146,7 @@ function generateCssFn(ctx) {
|
|
|
175
146
|
// value reaching \`css()\` is the same literal either way.
|
|
176
147
|
export const fallback = (...values) => \`fallback($\{values.join(', ')})\`
|
|
177
148
|
|
|
178
|
-
|
|
179
|
-
// from the same options, hashed by this same function. A call the extractor never saw
|
|
180
|
-
// still returns a class, exactly as \`css()\` does for a value it never saw.
|
|
181
|
-
export const viewTransition = (options) => viewTransitionClassName(options, ${JSON.stringify(prefix.className ?? "")})
|
|
149
|
+
export const viewTransition = (_options) => uncompiledStyle('viewTransition')
|
|
182
150
|
|
|
183
151
|
`
|
|
184
152
|
};
|
|
@@ -284,7 +252,7 @@ function generateCvaFn(ctx) {
|
|
|
284
252
|
const withPrefix = prefix.className ? `(className) => className ? ${JSON.stringify(prefix.className)} + '-' + className : ${JSON.stringify(prefix.className)}` : `(className) => className`;
|
|
285
253
|
return {
|
|
286
254
|
js: outdent`
|
|
287
|
-
${ctx.file.import("cloneStyles, compact,
|
|
255
|
+
${ctx.file.import("cloneStyles, compact, getRecipeIdentity, mergeProps, memo, splitProps, toHash, uniq, uncompiledStyle", "../helpers")}
|
|
288
256
|
${ctx.file.import("mergeCss", "./merge-css")}
|
|
289
257
|
${ctx.file.import("cx", "./cx")}
|
|
290
258
|
|
|
@@ -354,8 +322,8 @@ function generateCvaFn(ctx) {
|
|
|
354
322
|
// Compound variants are absent on purpose. Their rule selects on the variant classes
|
|
355
323
|
// already in this list — \`.btn--size_sm.btn--tone_a\` — so it applies without anything
|
|
356
324
|
// being added here, and adding a class for it would name a rule that does not exist.
|
|
357
|
-
function cvaFn(
|
|
358
|
-
return
|
|
325
|
+
function cvaFn(_props) {
|
|
326
|
+
return uncompiledStyle('cva')
|
|
359
327
|
}
|
|
360
328
|
|
|
361
329
|
const variantKeys = Object.keys(variants)
|
|
@@ -608,6 +576,18 @@ function generateHelpers() {
|
|
|
608
576
|
export function __objRest(source, exclude) {
|
|
609
577
|
return Object.fromEntries(Object.entries(source).filter(([key]) => !exclude.includes(key)))
|
|
610
578
|
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Style-producing calls compile away. Hitting this means \`@bamboocss/vite\` did not fold
|
|
582
|
+
* the call — missing plugin, a file outside \`include\`, or a shape the compiler rejects.
|
|
583
|
+
*/
|
|
584
|
+
export function uncompiledStyle(name) {
|
|
585
|
+
throw new Error(
|
|
586
|
+
'bamboocss: ' +
|
|
587
|
+
name +
|
|
588
|
+
'() was not compiled. Add \`bamboocss()\` from \`@bamboocss/vite\` and import \`virtual:bamboo.css\`. See https://bamboocss.com/docs/installation/vite',
|
|
589
|
+
)
|
|
590
|
+
}
|
|
611
591
|
` };
|
|
612
592
|
}
|
|
613
593
|
//#endregion
|
|
@@ -726,7 +706,7 @@ function generatePattern(ctx, filters) {
|
|
|
726
706
|
transform,
|
|
727
707
|
defaultValues
|
|
728
708
|
})) ?? "";
|
|
729
|
-
const helperImports = ["getPatternStyles, createPatternFns
|
|
709
|
+
const helperImports = ["getPatternStyles, createPatternFns"];
|
|
730
710
|
if (patternConfigFn.includes("__spreadValues")) helperImports.push("__spreadValues");
|
|
731
711
|
if (patternConfigFn.includes("__objRest")) helperImports.push("__objRest");
|
|
732
712
|
return {
|
|
@@ -759,8 +739,7 @@ function generatePattern(ctx, filters) {
|
|
|
759
739
|
|
|
760
740
|
`,
|
|
761
741
|
js: outdent`
|
|
762
|
-
${ctx.file.import(helperImports.join(", "), "../helpers")}
|
|
763
|
-
${ctx.file.import("css", "../css/index")}
|
|
742
|
+
${ctx.file.import([...helperImports, "uncompiledStyle"].join(", "), "../helpers")}
|
|
764
743
|
${ctx.file.import("token", "../tokens/index")}
|
|
765
744
|
|
|
766
745
|
/**
|
|
@@ -780,7 +759,7 @@ function generatePattern(ctx, filters) {
|
|
|
780
759
|
return ${baseName}Config.transform(_styles, patternHelpers)
|
|
781
760
|
}
|
|
782
761
|
|
|
783
|
-
export const ${baseName} =
|
|
762
|
+
export const ${baseName} = (styles) => uncompiledStyle(${JSON.stringify(baseName)})
|
|
784
763
|
${baseName}.raw = ${styleFnName}
|
|
785
764
|
`
|
|
786
765
|
};
|
|
@@ -833,55 +812,12 @@ function generateCreateRecipe(ctx) {
|
|
|
833
812
|
name: "create-recipe",
|
|
834
813
|
dts: "",
|
|
835
814
|
js: outdent`
|
|
836
|
-
${ctx.file.import("
|
|
837
|
-
${ctx.file.import("assertCompoundVariant, getCompoundVariantCss", "../css/cva")}
|
|
838
|
-
${ctx.file.import("cx", "../css/cx")}
|
|
839
|
-
${ctx.file.import("compact, createCssUncached, getRecipeClassNames, splitProps, toHash, uniq, withoutSpace", "../helpers")}
|
|
815
|
+
${ctx.file.import(hash.className ? "compact, splitProps, toHash, uniq, uncompiledStyle" : "compact, splitProps, uniq, uncompiledStyle", "../helpers")}
|
|
840
816
|
|
|
841
|
-
/**
|
|
842
|
-
* What \`createCss\` does to a class name: prefix it, and hash it when \`hash.className\`
|
|
843
|
-
* is set.
|
|
844
|
-
*
|
|
845
|
-
* A slot that takes variants gets this for free, because its classes come from
|
|
846
|
-
* \`createCss\`. A *scoped* slot's class never goes through it — it is a constant — so it
|
|
847
|
-
* has to be formatted here or the runtime hands back a raw name while the stylesheet
|
|
848
|
-
* emits the rule under a hashed one, and the slot renders unstyled.
|
|
849
|
-
*/
|
|
850
817
|
const withPrefix = ${prefix.className ? `(className) => className ? ${JSON.stringify(prefix.className)} + '-' + className : ${JSON.stringify(prefix.className)}` : `(className) => className`}
|
|
851
818
|
export const formatRecipeClass = ${hash.className ? `(className) => withPrefix((${utility.toHash})([className], toHash))` : `withPrefix`}
|
|
852
819
|
|
|
853
|
-
export const createRecipe = (name, defaultVariants,
|
|
854
|
-
/**
|
|
855
|
-
* \`variantMap\` as \`getRecipeClassNames\` wants it — value *keys* rather than a list.
|
|
856
|
-
*
|
|
857
|
-
* Built once per recipe at module init. The lookup needs \`Object.hasOwn\`, and an array
|
|
858
|
-
* answers that for its indices rather than its contents, so a list cannot be passed
|
|
859
|
-
* straight through.
|
|
860
|
-
*/
|
|
861
|
-
const variantValues = variantMap
|
|
862
|
-
? Object.fromEntries(
|
|
863
|
-
Object.entries(variantMap).map(([variant, values]) => [
|
|
864
|
-
variant,
|
|
865
|
-
Object.fromEntries(values.map((value) => [value, true])),
|
|
866
|
-
]),
|
|
867
|
-
)
|
|
868
|
-
: undefined
|
|
869
|
-
|
|
870
|
-
/**
|
|
871
|
-
* Whether every selected value is a plain scalar, and so nameable without \`createCss\`.
|
|
872
|
-
*
|
|
873
|
-
* \`typeof value === 'object'\` covers a conditional value like \`{ base: 'sm', md: 'lg' }\`,
|
|
874
|
-
* whose classes carry condition prefixes only \`createCss\` can build. It also catches
|
|
875
|
-
* \`null\`, which \`compact\` keeps — that goes to the path below and comes out as it did
|
|
876
|
-
* before, since \`createCss\` names no class for a null value either.
|
|
877
|
-
*/
|
|
878
|
-
const isScalarSelection = (declared) => {
|
|
879
|
-
for (const key in declared) {
|
|
880
|
-
if (typeof declared[key] === 'object') return false
|
|
881
|
-
}
|
|
882
|
-
return true
|
|
883
|
-
}
|
|
884
|
-
|
|
820
|
+
export const createRecipe = (name, defaultVariants, _compoundVariants, _variantMap) => {
|
|
885
821
|
const getVariantProps = (variants) => {
|
|
886
822
|
return {
|
|
887
823
|
[name]: '__ignore__',
|
|
@@ -890,82 +826,12 @@ function generateCreateRecipe(ctx) {
|
|
|
890
826
|
};
|
|
891
827
|
};
|
|
892
828
|
|
|
893
|
-
const recipeFn = (
|
|
894
|
-
const declaredProps = getVariantProps(variants)
|
|
895
|
-
|
|
896
|
-
// A scalar selection names its classes by lookup: the recipe's own class plus one per
|
|
897
|
-
// selected variant, which is all \`createCss\` was deriving here. Measured at 4.1x the
|
|
898
|
-
// \`createCss\` path on a three-variant recipe. The gain is on a \`memo\` miss — the first
|
|
899
|
-
// call for each variant combination — since a hit never reaches this at all.
|
|
900
|
-
//
|
|
901
|
-
// Compound variants stay absent, as they are on the path below: their rule selects on the
|
|
902
|
-
// variant classes already named, so it applies without one of its own.
|
|
903
|
-
if (variantValues && isScalarSelection(declaredProps)) {
|
|
904
|
-
return getRecipeClassNames(name, variantValues, declaredProps, '${utility.separator}', formatRecipeClass)
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
const transform = (prop, value) => {
|
|
908
|
-
assertCompoundVariant(name, compoundVariants, variants, prop)
|
|
909
|
-
|
|
910
|
-
if (value === '__ignore__') {
|
|
911
|
-
return { className: name }
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
value = withoutSpace(value)
|
|
915
|
-
return { className: \`\${name}--\${prop}${utility.separator}\${value}\` }
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
// Uncached: this runs *inside* \`recipeFn\`, which is itself memoized, so the cache a
|
|
919
|
-
// cached \`createCss\` would build here is constructed fresh per call and used once.
|
|
920
|
-
const recipeCss = createCssUncached({
|
|
921
|
-
${hash.className ? "hash: true," : ""}
|
|
922
|
-
conditions: {
|
|
923
|
-
shift: sortConditions,
|
|
924
|
-
finalize: finalizeConditions,
|
|
925
|
-
},
|
|
926
|
-
utility: {
|
|
927
|
-
${prefix.className ? "prefix: " + JSON.stringify(prefix.className) + "," : ""}
|
|
928
|
-
toHash: ${utility.toHash},
|
|
929
|
-
transform,
|
|
930
|
-
}
|
|
931
|
-
})
|
|
932
|
-
|
|
933
|
-
// Only what the config declares names a class.
|
|
934
|
-
//
|
|
935
|
-
// Without this the transform named one for *any* prop it was handed — the build emits
|
|
936
|
-
// rules only for declared values, so the element carried a class nothing backed. It also
|
|
937
|
-
// disagreed with \`cva\`, which skips an undeclared value, leaving the two recipe kinds
|
|
938
|
-
// with different class strings for the same call.
|
|
939
|
-
//
|
|
940
|
-
// Filtered here rather than in \`getVariantProps\`, which is public and is what compound
|
|
941
|
-
// variants are matched against.
|
|
942
|
-
const declared = declaredProps
|
|
943
|
-
const recipeStyles = variantMap
|
|
944
|
-
? Object.fromEntries(
|
|
945
|
-
Object.entries(declared).filter(([prop, value]) => {
|
|
946
|
-
if (prop === name) return true
|
|
947
|
-
// A conditional or responsive value is an object of leaves, and the leaves are
|
|
948
|
-
// what name classes: createCss walks them and calls transform per condition.
|
|
949
|
-
// Only a scalar can be judged here.
|
|
950
|
-
if (value === null || typeof value === 'object') return true
|
|
951
|
-
return Object.hasOwn(variantMap, prop) && variantMap[prop].includes(String(value))
|
|
952
|
-
}),
|
|
953
|
-
)
|
|
954
|
-
: declared
|
|
955
|
-
|
|
956
|
-
// No class for the compound variants. Their rule selects on the variant classes
|
|
957
|
-
// \`recipeCss\` just named — \`.btn--size_sm.btn--tone_a\` — so it applies on its own,
|
|
958
|
-
// and it is in the same layer as the rest of the recipe rather than atomically in
|
|
959
|
-
// \`utilities\` above it.
|
|
960
|
-
return recipeCss(recipeStyles)
|
|
961
|
-
}
|
|
829
|
+
const recipeFn = (_variants) => uncompiledStyle(name)
|
|
962
830
|
|
|
963
831
|
return {
|
|
964
832
|
recipeFn,
|
|
965
833
|
getVariantProps,
|
|
966
|
-
__getCompoundVariantCss__: (
|
|
967
|
-
return getCompoundVariantCss(compoundVariants, getVariantProps(variants));
|
|
968
|
-
},
|
|
834
|
+
__getCompoundVariantCss__: (_variants) => uncompiledStyle(name),
|
|
969
835
|
}
|
|
970
836
|
}
|
|
971
837
|
|
|
@@ -973,7 +839,7 @@ function generateCreateRecipe(ctx) {
|
|
|
973
839
|
if (recipeA && !recipeB) return recipeA
|
|
974
840
|
if (!recipeA && recipeB) return recipeB
|
|
975
841
|
|
|
976
|
-
const recipeFn = (...
|
|
842
|
+
const recipeFn = (..._args) => uncompiledStyle(recipeA.__name__ || 'recipe')
|
|
977
843
|
const variantKeys = uniq(Object.keys(recipeA.variantMap), Object.keys(recipeB.variantMap))
|
|
978
844
|
const variantMap = variantKeys.reduce((acc, key) => {
|
|
979
845
|
acc[key] = uniq(recipeA.variantMap[key], recipeB.variantMap[key])
|
|
@@ -1169,7 +1035,7 @@ function generateRecipes(ctx, filters) {
|
|
|
1169
1035
|
function generateSvaFn(ctx) {
|
|
1170
1036
|
return {
|
|
1171
1037
|
js: outdent`
|
|
1172
|
-
${ctx.file.import("compact, getRecipeIdentity, getSlotRecipes, memo, splitProps", "../helpers")}
|
|
1038
|
+
${ctx.file.import("compact, getRecipeIdentity, getSlotRecipes, memo, splitProps, uncompiledStyle", "../helpers")}
|
|
1173
1039
|
${ctx.file.import("cva, formatRecipeClass", "./cva")}
|
|
1174
1040
|
${ctx.file.import("cx", "./cx")}
|
|
1175
1041
|
|
|
@@ -1211,12 +1077,8 @@ function generateSvaFn(ctx) {
|
|
|
1211
1077
|
// atomic and nothing else carried the name to target it in the DOM. The slot's cva is
|
|
1212
1078
|
// now named \`name__slot\` and returns that as its base class, so joining it again
|
|
1213
1079
|
// would just repeat it.
|
|
1214
|
-
function svaFn(
|
|
1215
|
-
|
|
1216
|
-
slot,
|
|
1217
|
-
anchors.length && !anchors.includes(slot) ? formatRecipeClass(cvaFn.config.className) : cvaFn(props),
|
|
1218
|
-
])
|
|
1219
|
-
return Object.fromEntries(result)
|
|
1080
|
+
function svaFn(_props) {
|
|
1081
|
+
return uncompiledStyle('sva')
|
|
1220
1082
|
}
|
|
1221
1083
|
|
|
1222
1084
|
function raw(props) {
|
|
@@ -4253,7 +4115,7 @@ var Generator = class extends Context {
|
|
|
4253
4115
|
* Get all split CSS artifacts for the stylesheet
|
|
4254
4116
|
* Used when --splitting flag is enabled
|
|
4255
4117
|
*/
|
|
4256
|
-
getSplitCssArtifacts = (sheet) => {
|
|
4118
|
+
getSplitCssArtifacts = (sheet, { includeRecipes = false } = {}) => {
|
|
4257
4119
|
const layerNames = this.config.layers;
|
|
4258
4120
|
const decoder = this.decoder.collect(this.encoder);
|
|
4259
4121
|
const layers = [
|
|
@@ -4284,7 +4146,7 @@ var Generator = class extends Context {
|
|
|
4284
4146
|
code: l.css
|
|
4285
4147
|
}));
|
|
4286
4148
|
const recipes = [];
|
|
4287
|
-
for (const recipeName of this.recipes.keys) {
|
|
4149
|
+
if (includeRecipes) for (const recipeName of this.recipes.keys) {
|
|
4288
4150
|
const recipeSheet = this.createSheet();
|
|
4289
4151
|
recipeSheet.processDecoderForRecipe(decoder, recipeName);
|
|
4290
4152
|
const code = recipeSheet.getLayerCss("recipes");
|
|
@@ -4308,13 +4170,18 @@ var Generator = class extends Context {
|
|
|
4308
4170
|
});
|
|
4309
4171
|
}
|
|
4310
4172
|
const recipesIndex = recipes.map((r) => `@import './recipes/${r.file}';`).join("\n");
|
|
4311
|
-
const imports = [`@layer ${[
|
|
4173
|
+
const imports = [`@layer ${(includeRecipes ? [
|
|
4312
4174
|
layerNames.reset,
|
|
4313
4175
|
layerNames.base,
|
|
4314
4176
|
layerNames.tokens,
|
|
4315
4177
|
layerNames.recipes,
|
|
4316
4178
|
layerNames.utilities
|
|
4317
|
-
]
|
|
4179
|
+
] : [
|
|
4180
|
+
layerNames.reset,
|
|
4181
|
+
layerNames.base,
|
|
4182
|
+
layerNames.tokens,
|
|
4183
|
+
layerNames.utilities
|
|
4184
|
+
]).join(", ")};`, ""];
|
|
4318
4185
|
for (const layer of layers) imports.push(`@import './styles/${layer.file}';`);
|
|
4319
4186
|
if (recipes.length) imports.push(`@import './styles/recipes.css';`);
|
|
4320
4187
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/generator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"description": "The css generator for css bamboo",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"pluralize": "8.0.0",
|
|
39
39
|
"postcss": "8.5.26",
|
|
40
40
|
"ts-pattern": "5.9.0",
|
|
41
|
-
"@bamboocss/core": "1.
|
|
42
|
-
"@bamboocss/is-valid-prop": "^1.
|
|
43
|
-
"@bamboocss/logger": "1.
|
|
44
|
-
"@bamboocss/shared": "1.
|
|
45
|
-
"@bamboocss/token-dictionary": "1.
|
|
46
|
-
"@bamboocss/types": "1.
|
|
41
|
+
"@bamboocss/core": "1.47.0",
|
|
42
|
+
"@bamboocss/is-valid-prop": "^1.47.0",
|
|
43
|
+
"@bamboocss/logger": "1.47.0",
|
|
44
|
+
"@bamboocss/shared": "1.47.0",
|
|
45
|
+
"@bamboocss/token-dictionary": "1.47.0",
|
|
46
|
+
"@bamboocss/types": "1.47.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/pluralize": "0.0.33"
|