@bamboocss/generator 1.38.0 → 1.39.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 (3) hide show
  1. package/dist/index.cjs +141 -12
  2. package/dist/index.mjs +141 -12
  3. package/package.json +7 -7
package/dist/index.cjs CHANGED
@@ -2338,18 +2338,64 @@ const generateTypesEntry = (ctx) => {
2338
2338
  //#region src/artifacts/types/prop-types.ts
2339
2339
  function generatePropTypes(ctx) {
2340
2340
  const { utility } = ctx;
2341
- const result = [outdent.outdent`
2341
+ const result = [
2342
+ outdent.outdent`
2342
2343
  ${ctx.file.importType("ConditionalValue", "./conditions")}
2343
2344
  ${ctx.file.importType("CssProperties", "./system-types")}
2344
2345
  ${ctx.file.importType("Tokens", "../tokens/index")}
2345
-
2346
- export interface UtilityValues {`];
2346
+ `,
2347
+ outdent.outdent`
2348
+ /**
2349
+ * A property's own keywords, without the open \`string\` csstype ends every property with.
2350
+ *
2351
+ * That trailing \`(string & {})\` is what makes \`color: 'mutedd'\` type-check: it is a
2352
+ * string, so it is a colour. Removing it leaves what the property actually enumerates —
2353
+ * \`transparent\`, \`currentColor\`, every named colour — which is what
2354
+ * \`strictTokens: 'unknown-tokens'\` keeps.
2355
+ *
2356
+ * \`string extends T\` is the test, so the wide member goes and the literal ones stay. The
2357
+ * second branch is for the *boxed* \`String\`, which \`Properties<String | Number>\` puts on
2358
+ * every length-taking property and which is not assignable to \`string\` — so it survives the
2359
+ * first test and admits every string on its own. \`Number\` is deliberately kept: a number
2360
+ * cannot be a misspelled token path.
2361
+ */
2362
+ export type KnownKeywords<T> =
2363
+ T extends string ? (string extends T ? never : T)
2364
+ : T extends String ? never
2365
+ : T
2366
+ `,
2367
+ "export interface UtilityValues {"
2368
+ ];
2347
2369
  const types = utility.getTypes();
2348
2370
  for (const [prop, values] of types.entries()) result.push(`\t${prop}: ${values.join(" | ")};`);
2349
2371
  result.push("}", "\n");
2350
2372
  return outdent.outdent`
2351
2373
  ${result.join("\n")}
2352
2374
 
2375
+ /**
2376
+ * Values whose *shape* says they are CSS rather than a token path.
2377
+ *
2378
+ * A token path is a bare identifier, possibly dotted. Anything that starts with a digit, a
2379
+ * dot-digit, \`#\` or \`-\`, or that contains a space, a comma or a call, cannot be one — so
2380
+ * these stay allowed under \`strictTokens: 'unknown-tokens'\` while \`'mutedd'\` does not.
2381
+ *
2382
+ * Constant, and not parameterised by the token union: a template literal distributes over a
2383
+ * union in any placeholder, so a shape built from \`\${Token}\` would multiply the property's
2384
+ * union by the size of the palette. These add seven members whatever the theme contains — see
2385
+ * \`WithModifier\` below for what the other arrangement costs.
2386
+ *
2387
+ * The ambiguity this cannot resolve is a typo that is also a plausible value: \`'2xll'\` starts
2388
+ * with a digit exactly as \`'2rem'\` does, and passes.
2389
+ */
2390
+ export type CssValueShape =
2391
+ | \`\${number}\${string}\`
2392
+ | \`.\${number}\${string}\`
2393
+ | \`#\${string}\`
2394
+ | \`-\${string}\`
2395
+ | \`\${string} \${string}\`
2396
+ | \`\${string},\${string}\`
2397
+ | \`\${string}(\${string})\`
2398
+
2353
2399
  type ImportantMark = "!" | "!important"
2354
2400
  type WhitespaceImportant = \` \${ImportantMark}\`
2355
2401
  type Important = ImportantMark | WhitespaceImportant
@@ -2436,7 +2482,7 @@ function generateStyleProps(ctx) {
2436
2482
  const cssVars = (0, _bamboocss_shared.unionType)(ctx.globalVars.vars);
2437
2483
  return outdent.default`
2438
2484
  ${ctx.file.importType("ConditionalValue", "./conditions")}
2439
- ${ctx.file.importType("OnlyKnown, UtilityValues, WithEscapeHatch", "./prop-type")}
2485
+ ${ctx.file.importType("CssValueShape, KnownKeywords, OnlyKnown, UtilityValues, WithEscapeHatch", "./prop-type")}
2440
2486
  ${ctx.file.importType("CssProperties", "./system-types")}
2441
2487
  ${ctx.file.importType("Token", "../tokens/index")}
2442
2488
 
@@ -2455,25 +2501,93 @@ function generateStyleProps(ctx) {
2455
2501
  const prop = ctx.utility.shorthands.get(key) ?? key;
2456
2502
  const union = [];
2457
2503
  const cssFallback = _bamboocss_is_valid_prop.allCssProperties.includes(prop) ? `CssProperties["${prop}"]` : "";
2504
+ const knownFallback = ctx.config.strictTokens === "unknown-tokens" && !authorIdentProperties.has(prop) && cssFallback ? `KnownKeywords<${cssFallback}>` : "";
2505
+ const gradedFallback = ctx.config.strictTokens === true ? "" : knownFallback || cssFallback;
2506
+ /**
2507
+ * The token side, held out of the union under `'unknown-tokens'` so `restrict` can
2508
+ * put it back inside `WithEscapeHatch`.
2509
+ *
2510
+ * `WithModifier` is `[T] extends [string] ? … : never`, so one non-string member of
2511
+ * `T` — and csstype supplies `undefined` and a boxed `Number` — turns `'blue.300/40'`
2512
+ * and `'blue.300!'` off for the whole property. Wrapping the tokens alone is what
2513
+ * keeps those working, and listing them in both places instead would repeat one of
2514
+ * the largest members a property has.
2515
+ */
2516
+ let heldOutTokens = "";
2517
+ const separateTokens = ctx.config.strictTokens === "unknown-tokens";
2458
2518
  if (propTypes.has(prop)) {
2459
- const utilityValue = `UtilityValues["${prop}"]`;
2460
- if (strictPropertyList.has(key)) union.push([utilityValue, "CssVars"].join(" | "));
2519
+ const tokenValue = `UtilityValues["${prop}"]`;
2520
+ if (separateTokens) heldOutTokens = tokenValue;
2521
+ const own = separateTokens ? "" : tokenValue;
2522
+ if (strictPropertyList.has(key)) union.push([
2523
+ own,
2524
+ "CssVars",
2525
+ knownFallback
2526
+ ].filter(Boolean).join(" | "));
2461
2527
  else union.push([
2462
- utilityValue,
2528
+ own,
2463
2529
  "CssVars",
2464
- ctx.config.strictTokens ? "" : cssFallback
2530
+ gradedFallback
2465
2531
  ].filter(Boolean).join(" | "));
2466
- } else union.push([strictPropertyList.has(key) ? "CssVars" : "", cssFallback].filter(Boolean).join(" | "));
2532
+ } else union.push([strictPropertyList.has(key) ? "CssVars" : "", knownFallback || cssFallback].filter(Boolean).join(" | "));
2467
2533
  const filtered = union.filter(Boolean);
2468
2534
  if (!filtered.length) filtered.push("string | number");
2469
2535
  let comment = comments?.[prop] || "";
2470
2536
  if (ctx.utility.isDeprecated(prop)) comment = comment ? comment.replace("@see", "@deprecated\n@see") : "/** @deprecated */";
2471
- const line = `${key}?: ${restrict(prop, filtered.filter(Boolean).join(" | "), ctx.config)}`;
2537
+ const line = `${key}?: ${restrict(prop, filtered.filter(Boolean).join(" | "), ctx.config, heldOutTokens)}`;
2472
2538
  return " " + [comment, line].filter(Boolean).join("\n");
2473
2539
  }).join("\n")}
2474
2540
  }
2475
2541
  `;
2476
2542
  }
2543
+ /**
2544
+ * Properties whose values are identifiers the author invents, not values anything enumerates.
2545
+ *
2546
+ * `strictTokens: 'unknown-tokens'` rejects a bare identifier that names no token and no keyword,
2547
+ * on the reasoning that nothing else is shaped like one. That reasoning stops at a property
2548
+ * whose values *are* bare identifiers by design: a `@keyframes` name written in CSS rather than
2549
+ * in `theme.keyframes`, a grid area, a counter, a container, a view-transition name, a font
2550
+ * family, a property name in `transitionProperty`. csstype types all of these as open strings
2551
+ * for the same reason, so there is nothing to check against and everything to reject wrongly.
2552
+ *
2553
+ * Left alone rather than narrowed, so they behave under this setting exactly as they do under
2554
+ * the default. The cost is that a typo in one of them is not caught — which is what
2555
+ * `strictTokens: true` is for.
2556
+ *
2557
+ * `content` is here because its values are quoted strings, and `''""''` is neither a keyword nor
2558
+ * a shape this can recognise.
2559
+ */
2560
+ const authorIdentProperties = new Set([
2561
+ "anchorName",
2562
+ "anchorScope",
2563
+ "animationName",
2564
+ "animationTimeline",
2565
+ "containerName",
2566
+ "content",
2567
+ "counterIncrement",
2568
+ "counterReset",
2569
+ "counterSet",
2570
+ "fontFamily",
2571
+ "fontPalette",
2572
+ "gridArea",
2573
+ "gridColumn",
2574
+ "gridColumnEnd",
2575
+ "gridColumnStart",
2576
+ "gridRow",
2577
+ "gridRowEnd",
2578
+ "gridRowStart",
2579
+ "gridTemplateAreas",
2580
+ "listStyleType",
2581
+ "page",
2582
+ "positionAnchor",
2583
+ "positionTryFallbacks",
2584
+ "scrollTimelineName",
2585
+ "timelineScope",
2586
+ "transitionProperty",
2587
+ "viewTimelineName",
2588
+ "viewTransitionName",
2589
+ "willChange"
2590
+ ]);
2477
2591
  const strictPropertyList = new Set([
2478
2592
  "alignContent",
2479
2593
  "alignItems",
@@ -2538,8 +2652,23 @@ const strictPropertyList = new Set([
2538
2652
  "wordBreak",
2539
2653
  "writingMode"
2540
2654
  ]);
2541
- const restrict = (key, value, config) => {
2542
- if (config.strictPropertyValues && strictPropertyList.has(key)) return `ConditionalValue<WithEscapeHatch<OnlyKnown<"${key}", ${value}>>>`;
2655
+ const restrict = (key, value, config, heldOutTokens = "") => {
2656
+ if (config.strictPropertyValues && strictPropertyList.has(key)) return `ConditionalValue<WithEscapeHatch<OnlyKnown<"${key}", ${[heldOutTokens, value].filter(Boolean).join(" | ")}>>>`;
2657
+ /**
2658
+ * The escape hatch wraps the *tokens*, not the whole value.
2659
+ *
2660
+ * `WithModifier` is `[T] extends [string] ? … : never`, so one non-string member of `T`
2661
+ * turns the modifier forms off for the property entirely — and under this setting `T`
2662
+ * carries csstype's keywords, which include `undefined` and boxed `Number`. Wrapping the
2663
+ * whole union that way silently rejected `color: 'blue.300/40'` and `'blue.300!'`, which
2664
+ * decorate a token and have nothing to do with raw values.
2665
+ *
2666
+ * `CssValueShape` is what keeps raw values writable without an escape hatch: the shapes a
2667
+ * token path cannot have — a leading digit, `#` or `-`, or a space, comma or call anywhere.
2668
+ * A bare identifier that names no token and no keyword matches none of them, which is the
2669
+ * mistake this setting exists to catch.
2670
+ */
2671
+ if (config.strictTokens === "unknown-tokens") return `ConditionalValue<WithEscapeHatch<${heldOutTokens || "never"}> | ${value} | CssValueShape>`;
2543
2672
  if (config.strictTokens) return `ConditionalValue<WithEscapeHatch<${value}>>`;
2544
2673
  return `ConditionalValue<${value} | AnyString>`;
2545
2674
  };
package/dist/index.mjs CHANGED
@@ -2312,18 +2312,64 @@ const generateTypesEntry = (ctx) => {
2312
2312
  //#region src/artifacts/types/prop-types.ts
2313
2313
  function generatePropTypes(ctx) {
2314
2314
  const { utility } = ctx;
2315
- const result = [outdent`
2315
+ const result = [
2316
+ outdent`
2316
2317
  ${ctx.file.importType("ConditionalValue", "./conditions")}
2317
2318
  ${ctx.file.importType("CssProperties", "./system-types")}
2318
2319
  ${ctx.file.importType("Tokens", "../tokens/index")}
2319
-
2320
- export interface UtilityValues {`];
2320
+ `,
2321
+ outdent`
2322
+ /**
2323
+ * A property's own keywords, without the open \`string\` csstype ends every property with.
2324
+ *
2325
+ * That trailing \`(string & {})\` is what makes \`color: 'mutedd'\` type-check: it is a
2326
+ * string, so it is a colour. Removing it leaves what the property actually enumerates —
2327
+ * \`transparent\`, \`currentColor\`, every named colour — which is what
2328
+ * \`strictTokens: 'unknown-tokens'\` keeps.
2329
+ *
2330
+ * \`string extends T\` is the test, so the wide member goes and the literal ones stay. The
2331
+ * second branch is for the *boxed* \`String\`, which \`Properties<String | Number>\` puts on
2332
+ * every length-taking property and which is not assignable to \`string\` — so it survives the
2333
+ * first test and admits every string on its own. \`Number\` is deliberately kept: a number
2334
+ * cannot be a misspelled token path.
2335
+ */
2336
+ export type KnownKeywords<T> =
2337
+ T extends string ? (string extends T ? never : T)
2338
+ : T extends String ? never
2339
+ : T
2340
+ `,
2341
+ "export interface UtilityValues {"
2342
+ ];
2321
2343
  const types = utility.getTypes();
2322
2344
  for (const [prop, values] of types.entries()) result.push(`\t${prop}: ${values.join(" | ")};`);
2323
2345
  result.push("}", "\n");
2324
2346
  return outdent`
2325
2347
  ${result.join("\n")}
2326
2348
 
2349
+ /**
2350
+ * Values whose *shape* says they are CSS rather than a token path.
2351
+ *
2352
+ * A token path is a bare identifier, possibly dotted. Anything that starts with a digit, a
2353
+ * dot-digit, \`#\` or \`-\`, or that contains a space, a comma or a call, cannot be one — so
2354
+ * these stay allowed under \`strictTokens: 'unknown-tokens'\` while \`'mutedd'\` does not.
2355
+ *
2356
+ * Constant, and not parameterised by the token union: a template literal distributes over a
2357
+ * union in any placeholder, so a shape built from \`\${Token}\` would multiply the property's
2358
+ * union by the size of the palette. These add seven members whatever the theme contains — see
2359
+ * \`WithModifier\` below for what the other arrangement costs.
2360
+ *
2361
+ * The ambiguity this cannot resolve is a typo that is also a plausible value: \`'2xll'\` starts
2362
+ * with a digit exactly as \`'2rem'\` does, and passes.
2363
+ */
2364
+ export type CssValueShape =
2365
+ | \`\${number}\${string}\`
2366
+ | \`.\${number}\${string}\`
2367
+ | \`#\${string}\`
2368
+ | \`-\${string}\`
2369
+ | \`\${string} \${string}\`
2370
+ | \`\${string},\${string}\`
2371
+ | \`\${string}(\${string})\`
2372
+
2327
2373
  type ImportantMark = "!" | "!important"
2328
2374
  type WhitespaceImportant = \` \${ImportantMark}\`
2329
2375
  type Important = ImportantMark | WhitespaceImportant
@@ -2410,7 +2456,7 @@ function generateStyleProps(ctx) {
2410
2456
  const cssVars = unionType(ctx.globalVars.vars);
2411
2457
  return outdent$1`
2412
2458
  ${ctx.file.importType("ConditionalValue", "./conditions")}
2413
- ${ctx.file.importType("OnlyKnown, UtilityValues, WithEscapeHatch", "./prop-type")}
2459
+ ${ctx.file.importType("CssValueShape, KnownKeywords, OnlyKnown, UtilityValues, WithEscapeHatch", "./prop-type")}
2414
2460
  ${ctx.file.importType("CssProperties", "./system-types")}
2415
2461
  ${ctx.file.importType("Token", "../tokens/index")}
2416
2462
 
@@ -2429,25 +2475,93 @@ function generateStyleProps(ctx) {
2429
2475
  const prop = ctx.utility.shorthands.get(key) ?? key;
2430
2476
  const union = [];
2431
2477
  const cssFallback = allCssProperties.includes(prop) ? `CssProperties["${prop}"]` : "";
2478
+ const knownFallback = ctx.config.strictTokens === "unknown-tokens" && !authorIdentProperties.has(prop) && cssFallback ? `KnownKeywords<${cssFallback}>` : "";
2479
+ const gradedFallback = ctx.config.strictTokens === true ? "" : knownFallback || cssFallback;
2480
+ /**
2481
+ * The token side, held out of the union under `'unknown-tokens'` so `restrict` can
2482
+ * put it back inside `WithEscapeHatch`.
2483
+ *
2484
+ * `WithModifier` is `[T] extends [string] ? … : never`, so one non-string member of
2485
+ * `T` — and csstype supplies `undefined` and a boxed `Number` — turns `'blue.300/40'`
2486
+ * and `'blue.300!'` off for the whole property. Wrapping the tokens alone is what
2487
+ * keeps those working, and listing them in both places instead would repeat one of
2488
+ * the largest members a property has.
2489
+ */
2490
+ let heldOutTokens = "";
2491
+ const separateTokens = ctx.config.strictTokens === "unknown-tokens";
2432
2492
  if (propTypes.has(prop)) {
2433
- const utilityValue = `UtilityValues["${prop}"]`;
2434
- if (strictPropertyList.has(key)) union.push([utilityValue, "CssVars"].join(" | "));
2493
+ const tokenValue = `UtilityValues["${prop}"]`;
2494
+ if (separateTokens) heldOutTokens = tokenValue;
2495
+ const own = separateTokens ? "" : tokenValue;
2496
+ if (strictPropertyList.has(key)) union.push([
2497
+ own,
2498
+ "CssVars",
2499
+ knownFallback
2500
+ ].filter(Boolean).join(" | "));
2435
2501
  else union.push([
2436
- utilityValue,
2502
+ own,
2437
2503
  "CssVars",
2438
- ctx.config.strictTokens ? "" : cssFallback
2504
+ gradedFallback
2439
2505
  ].filter(Boolean).join(" | "));
2440
- } else union.push([strictPropertyList.has(key) ? "CssVars" : "", cssFallback].filter(Boolean).join(" | "));
2506
+ } else union.push([strictPropertyList.has(key) ? "CssVars" : "", knownFallback || cssFallback].filter(Boolean).join(" | "));
2441
2507
  const filtered = union.filter(Boolean);
2442
2508
  if (!filtered.length) filtered.push("string | number");
2443
2509
  let comment = comments?.[prop] || "";
2444
2510
  if (ctx.utility.isDeprecated(prop)) comment = comment ? comment.replace("@see", "@deprecated\n@see") : "/** @deprecated */";
2445
- const line = `${key}?: ${restrict(prop, filtered.filter(Boolean).join(" | "), ctx.config)}`;
2511
+ const line = `${key}?: ${restrict(prop, filtered.filter(Boolean).join(" | "), ctx.config, heldOutTokens)}`;
2446
2512
  return " " + [comment, line].filter(Boolean).join("\n");
2447
2513
  }).join("\n")}
2448
2514
  }
2449
2515
  `;
2450
2516
  }
2517
+ /**
2518
+ * Properties whose values are identifiers the author invents, not values anything enumerates.
2519
+ *
2520
+ * `strictTokens: 'unknown-tokens'` rejects a bare identifier that names no token and no keyword,
2521
+ * on the reasoning that nothing else is shaped like one. That reasoning stops at a property
2522
+ * whose values *are* bare identifiers by design: a `@keyframes` name written in CSS rather than
2523
+ * in `theme.keyframes`, a grid area, a counter, a container, a view-transition name, a font
2524
+ * family, a property name in `transitionProperty`. csstype types all of these as open strings
2525
+ * for the same reason, so there is nothing to check against and everything to reject wrongly.
2526
+ *
2527
+ * Left alone rather than narrowed, so they behave under this setting exactly as they do under
2528
+ * the default. The cost is that a typo in one of them is not caught — which is what
2529
+ * `strictTokens: true` is for.
2530
+ *
2531
+ * `content` is here because its values are quoted strings, and `''""''` is neither a keyword nor
2532
+ * a shape this can recognise.
2533
+ */
2534
+ const authorIdentProperties = new Set([
2535
+ "anchorName",
2536
+ "anchorScope",
2537
+ "animationName",
2538
+ "animationTimeline",
2539
+ "containerName",
2540
+ "content",
2541
+ "counterIncrement",
2542
+ "counterReset",
2543
+ "counterSet",
2544
+ "fontFamily",
2545
+ "fontPalette",
2546
+ "gridArea",
2547
+ "gridColumn",
2548
+ "gridColumnEnd",
2549
+ "gridColumnStart",
2550
+ "gridRow",
2551
+ "gridRowEnd",
2552
+ "gridRowStart",
2553
+ "gridTemplateAreas",
2554
+ "listStyleType",
2555
+ "page",
2556
+ "positionAnchor",
2557
+ "positionTryFallbacks",
2558
+ "scrollTimelineName",
2559
+ "timelineScope",
2560
+ "transitionProperty",
2561
+ "viewTimelineName",
2562
+ "viewTransitionName",
2563
+ "willChange"
2564
+ ]);
2451
2565
  const strictPropertyList = new Set([
2452
2566
  "alignContent",
2453
2567
  "alignItems",
@@ -2512,8 +2626,23 @@ const strictPropertyList = new Set([
2512
2626
  "wordBreak",
2513
2627
  "writingMode"
2514
2628
  ]);
2515
- const restrict = (key, value, config) => {
2516
- if (config.strictPropertyValues && strictPropertyList.has(key)) return `ConditionalValue<WithEscapeHatch<OnlyKnown<"${key}", ${value}>>>`;
2629
+ const restrict = (key, value, config, heldOutTokens = "") => {
2630
+ if (config.strictPropertyValues && strictPropertyList.has(key)) return `ConditionalValue<WithEscapeHatch<OnlyKnown<"${key}", ${[heldOutTokens, value].filter(Boolean).join(" | ")}>>>`;
2631
+ /**
2632
+ * The escape hatch wraps the *tokens*, not the whole value.
2633
+ *
2634
+ * `WithModifier` is `[T] extends [string] ? … : never`, so one non-string member of `T`
2635
+ * turns the modifier forms off for the property entirely — and under this setting `T`
2636
+ * carries csstype's keywords, which include `undefined` and boxed `Number`. Wrapping the
2637
+ * whole union that way silently rejected `color: 'blue.300/40'` and `'blue.300!'`, which
2638
+ * decorate a token and have nothing to do with raw values.
2639
+ *
2640
+ * `CssValueShape` is what keeps raw values writable without an escape hatch: the shapes a
2641
+ * token path cannot have — a leading digit, `#` or `-`, or a space, comma or call anywhere.
2642
+ * A bare identifier that names no token and no keyword matches none of them, which is the
2643
+ * mistake this setting exists to catch.
2644
+ */
2645
+ if (config.strictTokens === "unknown-tokens") return `ConditionalValue<WithEscapeHatch<${heldOutTokens || "never"}> | ${value} | CssValueShape>`;
2517
2646
  if (config.strictTokens) return `ConditionalValue<WithEscapeHatch<${value}>>`;
2518
2647
  return `ConditionalValue<${value} | AnyString>`;
2519
2648
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bamboocss/generator",
3
- "version": "1.38.0",
3
+ "version": "1.39.1",
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.38.0",
42
- "@bamboocss/is-valid-prop": "^1.38.0",
43
- "@bamboocss/logger": "1.38.0",
44
- "@bamboocss/shared": "1.38.0",
45
- "@bamboocss/token-dictionary": "1.38.0",
46
- "@bamboocss/types": "1.38.0"
41
+ "@bamboocss/core": "1.39.1",
42
+ "@bamboocss/is-valid-prop": "^1.39.1",
43
+ "@bamboocss/logger": "1.39.1",
44
+ "@bamboocss/shared": "1.39.1",
45
+ "@bamboocss/token-dictionary": "1.39.1",
46
+ "@bamboocss/types": "1.39.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/pluralize": "0.0.33"