tailwind-styled-v4 5.1.21 → 5.1.23

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 (62) hide show
  1. package/README.md +216 -0
  2. package/dist/atomic.js +34 -4
  3. package/dist/atomic.js.map +1 -1
  4. package/dist/atomic.mjs +31 -2
  5. package/dist/atomic.mjs.map +1 -1
  6. package/dist/cli.d.mts +28 -16
  7. package/dist/cli.d.ts +28 -16
  8. package/dist/cli.js +392 -77
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cli.mjs +388 -75
  11. package/dist/cli.mjs.map +1 -1
  12. package/dist/compiler.d.mts +195 -1
  13. package/dist/compiler.d.ts +195 -1
  14. package/dist/compiler.js +356 -12
  15. package/dist/compiler.js.map +1 -1
  16. package/dist/compiler.mjs +340 -10
  17. package/dist/compiler.mjs.map +1 -1
  18. package/dist/engine.js +194 -164
  19. package/dist/engine.js.map +1 -1
  20. package/dist/engine.mjs +184 -155
  21. package/dist/engine.mjs.map +1 -1
  22. package/dist/index.browser.mjs +144 -14
  23. package/dist/index.browser.mjs.map +1 -1
  24. package/dist/index.d.mts +45 -4
  25. package/dist/index.d.ts +45 -4
  26. package/dist/index.js +174 -9
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +185 -21
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/next.js +489 -158
  31. package/dist/next.js.map +1 -1
  32. package/dist/next.mjs +483 -153
  33. package/dist/next.mjs.map +1 -1
  34. package/dist/runtime-css.js +1 -1
  35. package/dist/runtime-css.js.map +1 -1
  36. package/dist/runtime-css.mjs +1 -1
  37. package/dist/runtime-css.mjs.map +1 -1
  38. package/dist/runtime.js +17 -0
  39. package/dist/runtime.js.map +1 -1
  40. package/dist/runtime.mjs +23 -0
  41. package/dist/runtime.mjs.map +1 -1
  42. package/dist/shared.js +91 -61
  43. package/dist/shared.js.map +1 -1
  44. package/dist/shared.mjs +85 -56
  45. package/dist/shared.mjs.map +1 -1
  46. package/dist/turbopackLoader.js +79 -49
  47. package/dist/turbopackLoader.js.map +1 -1
  48. package/dist/turbopackLoader.mjs +76 -47
  49. package/dist/turbopackLoader.mjs.map +1 -1
  50. package/dist/tw.js +390 -77
  51. package/dist/tw.js.map +1 -1
  52. package/dist/tw.mjs +387 -75
  53. package/dist/tw.mjs.map +1 -1
  54. package/dist/vite.js +157 -127
  55. package/dist/vite.js.map +1 -1
  56. package/dist/vite.mjs +150 -121
  57. package/dist/vite.mjs.map +1 -1
  58. package/dist/webpackLoader.js +39 -9
  59. package/dist/webpackLoader.js.map +1 -1
  60. package/dist/webpackLoader.mjs +36 -7
  61. package/dist/webpackLoader.mjs.map +1 -1
  62. package/package.json +1 -1
package/dist/tw.mjs CHANGED
@@ -998,8 +998,8 @@ var require_command = __commonJS({
998
998
  init_esm_shims();
999
999
  var EventEmitter = __require("events").EventEmitter;
1000
1000
  var childProcess = __require("child_process");
1001
- var path32 = __require("path");
1002
- var fs17 = __require("fs");
1001
+ var path34 = __require("path");
1002
+ var fs19 = __require("fs");
1003
1003
  var process2 = __require("process");
1004
1004
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1005
1005
  var { CommanderError: CommanderError2 } = require_error();
@@ -1931,11 +1931,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1931
1931
  let launchWithNode = false;
1932
1932
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1933
1933
  function findFile(baseDir, baseName) {
1934
- const localBin = path32.resolve(baseDir, baseName);
1935
- if (fs17.existsSync(localBin)) return localBin;
1936
- if (sourceExt.includes(path32.extname(baseName))) return void 0;
1934
+ const localBin = path34.resolve(baseDir, baseName);
1935
+ if (fs19.existsSync(localBin)) return localBin;
1936
+ if (sourceExt.includes(path34.extname(baseName))) return void 0;
1937
1937
  const foundExt = sourceExt.find(
1938
- (ext) => fs17.existsSync(`${localBin}${ext}`)
1938
+ (ext) => fs19.existsSync(`${localBin}${ext}`)
1939
1939
  );
1940
1940
  if (foundExt) return `${localBin}${foundExt}`;
1941
1941
  return void 0;
@@ -1947,21 +1947,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1947
1947
  if (this._scriptPath) {
1948
1948
  let resolvedScriptPath;
1949
1949
  try {
1950
- resolvedScriptPath = fs17.realpathSync(this._scriptPath);
1950
+ resolvedScriptPath = fs19.realpathSync(this._scriptPath);
1951
1951
  } catch (err) {
1952
1952
  resolvedScriptPath = this._scriptPath;
1953
1953
  }
1954
- executableDir = path32.resolve(
1955
- path32.dirname(resolvedScriptPath),
1954
+ executableDir = path34.resolve(
1955
+ path34.dirname(resolvedScriptPath),
1956
1956
  executableDir
1957
1957
  );
1958
1958
  }
1959
1959
  if (executableDir) {
1960
1960
  let localFile = findFile(executableDir, executableFile);
1961
1961
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1962
- const legacyName = path32.basename(
1962
+ const legacyName = path34.basename(
1963
1963
  this._scriptPath,
1964
- path32.extname(this._scriptPath)
1964
+ path34.extname(this._scriptPath)
1965
1965
  );
1966
1966
  if (legacyName !== this._name) {
1967
1967
  localFile = findFile(
@@ -1972,7 +1972,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1972
1972
  }
1973
1973
  executableFile = localFile || executableFile;
1974
1974
  }
1975
- launchWithNode = sourceExt.includes(path32.extname(executableFile));
1975
+ launchWithNode = sourceExt.includes(path34.extname(executableFile));
1976
1976
  let proc;
1977
1977
  if (process2.platform !== "win32") {
1978
1978
  if (launchWithNode) {
@@ -2812,7 +2812,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2812
2812
  * @return {Command}
2813
2813
  */
2814
2814
  nameFromFilename(filename) {
2815
- this._name = path32.basename(filename, path32.extname(filename));
2815
+ this._name = path34.basename(filename, path34.extname(filename));
2816
2816
  return this;
2817
2817
  }
2818
2818
  /**
@@ -2826,9 +2826,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2826
2826
  * @param {string} [path]
2827
2827
  * @return {(string|null|Command)}
2828
2828
  */
2829
- executableDir(path33) {
2830
- if (path33 === void 0) return this._executableDir;
2831
- this._executableDir = path33;
2829
+ executableDir(path35) {
2830
+ if (path35 === void 0) return this._executableDir;
2831
+ this._executableDir = path35;
2832
2832
  return this;
2833
2833
  }
2834
2834
  /**
@@ -3346,9 +3346,9 @@ function createDebugLogger(namespace, label) {
3346
3346
  }
3347
3347
  };
3348
3348
  }
3349
- function formatIssuePath(path32) {
3350
- if (!path32 || path32.length === 0) return "(root)";
3351
- return path32.map(
3349
+ function formatIssuePath(path34) {
3350
+ if (!path34 || path34.length === 0) return "(root)";
3351
+ return path34.map(
3352
3352
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
3353
3353
  ).join(".");
3354
3354
  }
@@ -3464,8 +3464,8 @@ var init_src = __esm({
3464
3464
  /** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
3465
3465
  static fromZod(err) {
3466
3466
  const first = err.issues?.[0] ?? err.errors?.[0];
3467
- const path32 = formatIssuePath(first?.path);
3468
- const message = first ? `${path32}: ${first.message}` : "Schema validation failed";
3467
+ const path34 = formatIssuePath(first?.path);
3468
+ const message = first ? `${path34}: ${first.message}` : "Schema validation failed";
3469
3469
  return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
3470
3470
  }
3471
3471
  static wrap(source, code, err) {
@@ -4021,12 +4021,12 @@ var init_schemas = __esm({
4021
4021
  "use strict";
4022
4022
  init_esm_shims();
4023
4023
  init_src();
4024
- formatIssuePath2 = (path32) => path32.length > 0 ? path32.map(
4024
+ formatIssuePath2 = (path34) => path34.length > 0 ? path34.map(
4025
4025
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
4026
4026
  ).join(".") : "<root>";
4027
4027
  formatIssues = (error) => error.issues.map((issue) => {
4028
- const path32 = formatIssuePath2(issue.path);
4029
- return `${path32}: ${issue.message}`;
4028
+ const path34 = formatIssuePath2(issue.path);
4029
+ return `${path34}: ${issue.message}`;
4030
4030
  }).join("; ");
4031
4031
  parseWithSchema = (schema, data, label) => {
4032
4032
  const parsed = schema.safeParse(data);
@@ -4631,7 +4631,7 @@ var init_schemas2 = __esm({
4631
4631
  "use strict";
4632
4632
  init_esm_shims();
4633
4633
  init_src();
4634
- formatIssuePath3 = (path32) => path32.length > 0 ? path32.map(
4634
+ formatIssuePath3 = (path34) => path34.length > 0 ? path34.map(
4635
4635
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
4636
4636
  ).join(".") : "<root>";
4637
4637
  isPlainObject = (value) => {
@@ -4640,8 +4640,8 @@ var init_schemas2 = __esm({
4640
4640
  return proto === Object.prototype || proto === null;
4641
4641
  };
4642
4642
  formatIssues2 = (error) => error.issues.map((issue) => {
4643
- const path32 = formatIssuePath3(issue.path);
4644
- return `${path32}: ${issue.message}`;
4643
+ const path34 = formatIssuePath3(issue.path);
4644
+ return `${path34}: ${issue.message}`;
4645
4645
  }).join("; ");
4646
4646
  parseWithSchema2 = (schema, data, label) => {
4647
4647
  const parsed = schema.safeParse(data);
@@ -6262,7 +6262,7 @@ var init_nativeBridge = __esm({
6262
6262
  "use strict";
6263
6263
  init_esm_shims();
6264
6264
  init_src();
6265
- _loadNative = (path32) => __require(path32);
6265
+ _loadNative = (path34) => __require(path34);
6266
6266
  log3 = (...args) => {
6267
6267
  if (process.env.DEBUG?.includes("compiler:native")) {
6268
6268
  console.log("[compiler:native]", ...args);
@@ -6405,8 +6405,8 @@ var init_watch = __esm({
6405
6405
  });
6406
6406
 
6407
6407
  // packages/domain/compiler/src/routeGraph.ts
6408
- import fs12 from "fs";
6409
- import path25 from "path";
6408
+ import fs13 from "fs";
6409
+ import path26 from "path";
6410
6410
  var init_routeGraph = __esm({
6411
6411
  "packages/domain/compiler/src/routeGraph.ts"() {
6412
6412
  "use strict";
@@ -6414,9 +6414,35 @@ var init_routeGraph = __esm({
6414
6414
  }
6415
6415
  });
6416
6416
 
6417
+ // packages/domain/compiler/src/semanticComponentAnalyzer.ts
6418
+ var init_semanticComponentAnalyzer = __esm({
6419
+ "packages/domain/compiler/src/semanticComponentAnalyzer.ts"() {
6420
+ "use strict";
6421
+ init_esm_shims();
6422
+ }
6423
+ });
6424
+
6425
+ // packages/domain/compiler/src/typeGeneratorFromMetadata.ts
6426
+ var init_typeGeneratorFromMetadata = __esm({
6427
+ "packages/domain/compiler/src/typeGeneratorFromMetadata.ts"() {
6428
+ "use strict";
6429
+ init_esm_shims();
6430
+ }
6431
+ });
6432
+
6433
+ // packages/domain/compiler/src/typeGenerationPlugin.ts
6434
+ import fs14 from "fs";
6435
+ import path27 from "path";
6436
+ var init_typeGenerationPlugin = __esm({
6437
+ "packages/domain/compiler/src/typeGenerationPlugin.ts"() {
6438
+ "use strict";
6439
+ init_esm_shims();
6440
+ }
6441
+ });
6442
+
6417
6443
  // packages/domain/compiler/src/index.ts
6418
- import fs13 from "fs";
6419
- import path26 from "path";
6444
+ import fs15 from "fs";
6445
+ import path28 from "path";
6420
6446
  import { createRequire as createRequire4 } from "module";
6421
6447
  var _require3, compileCssFromClasses;
6422
6448
  var init_src4 = __esm({
@@ -6431,6 +6457,9 @@ var init_src4 = __esm({
6431
6457
  init_redis();
6432
6458
  init_watch();
6433
6459
  init_routeGraph();
6460
+ init_semanticComponentAnalyzer();
6461
+ init_typeGeneratorFromMetadata();
6462
+ init_typeGenerationPlugin();
6434
6463
  _require3 = createRequire4(
6435
6464
  typeof __require !== "undefined" ? typeof __filename !== "undefined" ? `file://${__filename}` : "file://unknown" : import.meta.url
6436
6465
  );
@@ -8737,12 +8766,289 @@ function printDoctorOutput(result, output) {
8737
8766
  );
8738
8767
  }
8739
8768
 
8769
+ // packages/infrastructure/cli/src/commands/figma.ts
8770
+ init_esm_shims();
8771
+ init_errors();
8772
+ import fs12 from "fs";
8773
+ import path24 from "path";
8774
+
8775
+ // packages/infrastructure/cli/src/utils/figmaApi.ts
8776
+ init_esm_shims();
8777
+ async function figmaRequest(endpoint, options) {
8778
+ const { token, fileKey } = options;
8779
+ if (!token) {
8780
+ throw new Error("FIGMA_TOKEN environment variable not set");
8781
+ }
8782
+ if (!fileKey) {
8783
+ throw new Error("FIGMA_FILE_KEY environment variable not set");
8784
+ }
8785
+ const url = `https://api.figma.com/v1${endpoint.replace(":fileKey", fileKey)}`;
8786
+ const res = await fetch(url, {
8787
+ headers: { "X-Figma-Token": token }
8788
+ });
8789
+ if (!res.ok) {
8790
+ const body = await res.text();
8791
+ throw new Error(`Figma API ${res.status}: ${body.slice(0, 200)}`);
8792
+ }
8793
+ return res.json();
8794
+ }
8795
+ function figmaColorToHex(color) {
8796
+ const { r, g, b, a = 1 } = color;
8797
+ const toHex = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
8798
+ const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
8799
+ return a < 1 ? `${hex}${toHex(a)}` : hex;
8800
+ }
8801
+ function figmaVariablesToTokens(variablesData) {
8802
+ const tokens = {};
8803
+ const { variables = {}, variableCollections = {} } = variablesData;
8804
+ for (const [id, variable] of Object.entries(variables)) {
8805
+ const collection = variableCollections?.[variable.variableCollectionId];
8806
+ if (!collection) continue;
8807
+ const modeId = Object.keys(variable.valuesByMode)[0];
8808
+ const rawValue = variable.valuesByMode[modeId];
8809
+ if (rawValue === void 0) continue;
8810
+ const parts = variable.name.split("/").map(
8811
+ (p) => p.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")
8812
+ );
8813
+ let cursor = tokens;
8814
+ for (let i = 0; i < parts.length - 1; i++) {
8815
+ cursor[parts[i]] ??= {};
8816
+ cursor = cursor[parts[i]];
8817
+ }
8818
+ const leafKey = parts[parts.length - 1];
8819
+ if (variable.resolvedType === "COLOR") {
8820
+ const token = {
8821
+ $value: typeof rawValue === "object" && rawValue !== null && "r" in rawValue ? figmaColorToHex(rawValue) : String(rawValue),
8822
+ $type: "color"
8823
+ };
8824
+ if (variable.description) token.$description = variable.description;
8825
+ token._figmaId = id;
8826
+ cursor[leafKey] = token;
8827
+ } else if (variable.resolvedType === "FLOAT") {
8828
+ cursor[leafKey] = {
8829
+ $value: typeof rawValue === "number" ? `${rawValue}px` : String(rawValue),
8830
+ $type: "dimension",
8831
+ _figmaId: id
8832
+ };
8833
+ } else if (variable.resolvedType === "STRING") {
8834
+ cursor[leafKey] = {
8835
+ $value: String(rawValue),
8836
+ $type: "other",
8837
+ _figmaId: id
8838
+ };
8839
+ }
8840
+ }
8841
+ return tokens;
8842
+ }
8843
+
8844
+ // packages/infrastructure/cli/src/utils/tokenUtils.ts
8845
+ init_esm_shims();
8846
+ function tokensToFigmaUpdates(tokens, existingVariables = {}) {
8847
+ const updates = [];
8848
+ function walk(obj, path34 = []) {
8849
+ for (const [key, val] of Object.entries(obj)) {
8850
+ if (typeof val === "object" && val !== null && "$value" in val) {
8851
+ const tokenVal = val;
8852
+ const name = path34.concat(key).map(
8853
+ (p) => p.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("")
8854
+ ).join("/");
8855
+ const existing = Object.values(existingVariables).find(
8856
+ (v) => v.name === name
8857
+ );
8858
+ if (existing) {
8859
+ updates.push({
8860
+ id: existing.id,
8861
+ name,
8862
+ value: tokenVal.$value,
8863
+ type: tokenVal.$type
8864
+ });
8865
+ }
8866
+ } else if (typeof val === "object" && val !== null && !("$type" in val)) {
8867
+ walk(val, path34.concat(key));
8868
+ }
8869
+ }
8870
+ }
8871
+ walk(tokens);
8872
+ return updates;
8873
+ }
8874
+ function flattenTokens(obj, prefix = "", target = {}) {
8875
+ for (const [k, v] of Object.entries(obj)) {
8876
+ const key = [prefix, k].filter(Boolean).join(".");
8877
+ if (typeof v === "object" && v !== null && "$value" in v) {
8878
+ const tokenVal = v;
8879
+ target[key] = tokenVal.$value;
8880
+ } else if (typeof v === "object" && v !== null && !("$type" in v)) {
8881
+ flattenTokens(v, key, target);
8882
+ }
8883
+ }
8884
+ return target;
8885
+ }
8886
+ function diffTokens(local, figma) {
8887
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(figma)]);
8888
+ const diffs = [];
8889
+ for (const key of allKeys) {
8890
+ if (local[key] !== figma[key]) {
8891
+ diffs.push({
8892
+ key,
8893
+ local: local[key],
8894
+ figma: figma[key]
8895
+ });
8896
+ }
8897
+ }
8898
+ return diffs;
8899
+ }
8900
+
8901
+ // packages/infrastructure/cli/src/commands/figma.ts
8902
+ var figmaCommand = {
8903
+ name: "figma",
8904
+ async run(args, context) {
8905
+ const cmd = args[0];
8906
+ const isDryRun = args.includes("--dry-run");
8907
+ const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
8908
+ const FIGMA_FILE_KEY = process.env.FIGMA_FILE_KEY;
8909
+ const TOKEN_FILE = path24.join(context.cwd, "tokens.sync.json");
8910
+ if (!cmd || cmd === "help") {
8911
+ context.output.writeText(`Usage: tw figma <pull|push|diff> [--dry-run]
8912
+
8913
+ Environment variables:
8914
+ FIGMA_TOKEN \u2014 Figma personal access token (figd_...)
8915
+ FIGMA_FILE_KEY \u2014 Figma file key (from URL: figma.com/file/<KEY>/...)
8916
+
8917
+ Commands:
8918
+ pull Import Figma variables \u2192 tokens.sync.json
8919
+ push Export tokens.sync.json \u2192 Figma variables
8920
+ diff Show differences between local and Figma
8921
+
8922
+ Options:
8923
+ --dry-run Show what would change without writing`);
8924
+ return;
8925
+ }
8926
+ if (cmd === "pull") {
8927
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
8928
+ throw new CliUsageError(
8929
+ "Missing FIGMA_TOKEN or FIGMA_FILE_KEY\nSet environment variables and retry\n\nExample:\n export FIGMA_TOKEN=figd_your_token_here\n export FIGMA_FILE_KEY=abc123XYZ"
8930
+ );
8931
+ }
8932
+ try {
8933
+ const spinner = context.output.spinner();
8934
+ spinner.start("Fetching Figma variables...");
8935
+ const data = await figmaRequest("/files/:fileKey/variables/local", {
8936
+ token: FIGMA_TOKEN,
8937
+ fileKey: FIGMA_FILE_KEY
8938
+ });
8939
+ spinner.stop();
8940
+ const tokens = figmaVariablesToTokens(data);
8941
+ const variableCount = Object.values(data.variables ?? {}).length;
8942
+ if (isDryRun) {
8943
+ context.output.info("DRY RUN \u2014 would write:");
8944
+ context.output.writeText(JSON.stringify({ version: 1, tokens }, null, 2));
8945
+ } else {
8946
+ let existing = { version: 1, tokens: {} };
8947
+ if (fs12.existsSync(TOKEN_FILE)) {
8948
+ try {
8949
+ existing = JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8"));
8950
+ } catch {
8951
+ }
8952
+ }
8953
+ const merged = {
8954
+ ...existing,
8955
+ tokens: { ...existing.tokens, ...tokens },
8956
+ figmaFileKey: FIGMA_FILE_KEY,
8957
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
8958
+ source: "figma"
8959
+ };
8960
+ fs12.writeFileSync(TOKEN_FILE, JSON.stringify(merged, null, 2) + "\n");
8961
+ context.output.success(
8962
+ `Pulled ${variableCount} variables from Figma \u2192 ${TOKEN_FILE}`
8963
+ );
8964
+ }
8965
+ } catch (e) {
8966
+ throw new CliUsageError(
8967
+ `Pull failed: ${e instanceof Error ? e.message : String(e)}`
8968
+ );
8969
+ }
8970
+ } else if (cmd === "push") {
8971
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
8972
+ throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
8973
+ }
8974
+ if (!fs12.existsSync(TOKEN_FILE)) {
8975
+ throw new CliUsageError(
8976
+ `${TOKEN_FILE} not found. Run 'tw sync init' first.`
8977
+ );
8978
+ }
8979
+ try {
8980
+ const local = JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8"));
8981
+ const data = await figmaRequest("/files/:fileKey/variables/local", {
8982
+ token: FIGMA_TOKEN,
8983
+ fileKey: FIGMA_FILE_KEY
8984
+ });
8985
+ const updates = tokensToFigmaUpdates(local.tokens ?? {}, data.variables?.length ? Object.entries(data.variables ?? {}).reduce((acc, [id, v]) => ({ ...acc, [id]: { ...v, id } }), {}) : {});
8986
+ if (isDryRun) {
8987
+ context.output.info(
8988
+ `DRY RUN \u2014 would update ${updates.length} variables in Figma:`
8989
+ );
8990
+ updates.forEach((u) => context.output.writeText(` ${u.name}: ${u.value}`));
8991
+ } else {
8992
+ if (updates.length === 0) {
8993
+ context.output.info("No matching variables to update");
8994
+ } else {
8995
+ context.output.success(`Updated ${updates.length} variables in Figma`);
8996
+ }
8997
+ }
8998
+ } catch (e) {
8999
+ throw new CliUsageError(
9000
+ `Push failed: ${e instanceof Error ? e.message : String(e)}`
9001
+ );
9002
+ }
9003
+ } else if (cmd === "diff") {
9004
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
9005
+ throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
9006
+ }
9007
+ if (!fs12.existsSync(TOKEN_FILE)) {
9008
+ throw new CliUsageError("tokens.sync.json not found");
9009
+ }
9010
+ try {
9011
+ const [local, figmaData] = await Promise.all([
9012
+ JSON.parse(fs12.readFileSync(TOKEN_FILE, "utf8")),
9013
+ figmaRequest("/files/:fileKey/variables/local", {
9014
+ token: FIGMA_TOKEN,
9015
+ fileKey: FIGMA_FILE_KEY
9016
+ })
9017
+ ]);
9018
+ const figmaTokens = figmaVariablesToTokens(figmaData);
9019
+ const figmaFlat = {};
9020
+ const localFlat = {};
9021
+ flattenTokens(local.tokens ?? {}, "", localFlat);
9022
+ flattenTokens(figmaTokens, "", figmaFlat);
9023
+ const diffs = diffTokens(localFlat, figmaFlat);
9024
+ if (diffs.length === 0) {
9025
+ context.output.success("No differences \u2014 local and Figma are in sync");
9026
+ } else {
9027
+ context.output.info(`${diffs.length} differences found:
9028
+ `);
9029
+ diffs.forEach((d) => {
9030
+ context.output.writeText(` ${d.key}`);
9031
+ context.output.writeText(` local: ${d.local ?? "(missing)"}`);
9032
+ context.output.writeText(` figma: ${d.figma ?? "(missing)"}`);
9033
+ });
9034
+ }
9035
+ } catch (e) {
9036
+ throw new CliUsageError(
9037
+ `Diff failed: ${e instanceof Error ? e.message : String(e)}`
9038
+ );
9039
+ }
9040
+ } else {
9041
+ throw new CliUsageError(`Unknown command: ${cmd}`);
9042
+ }
9043
+ }
9044
+ };
9045
+
8740
9046
  // packages/infrastructure/cli/src/commands/misc.ts
8741
9047
  init_esm_shims();
8742
9048
  init_errors();
8743
9049
  init_fs();
8744
9050
  init_json();
8745
- import path24 from "path";
9051
+ import path25 from "path";
8746
9052
  import { parseArgs as parseNodeArgs9 } from "util";
8747
9053
  var testCommand = {
8748
9054
  name: "test",
@@ -8772,7 +9078,7 @@ var shareCommand = {
8772
9078
  name: "share",
8773
9079
  async run(args, context) {
8774
9080
  const name = args.find((arg) => !arg.startsWith("-")) ?? "component-name";
8775
- const manifestPath = path24.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
9081
+ const manifestPath = path25.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
8776
9082
  const defaultManifest = {
8777
9083
  name,
8778
9084
  version: "0.1.0"
@@ -8858,14 +9164,14 @@ var isVersionOutdated = (currentVersion, latestVersion) => {
8858
9164
  };
8859
9165
  var resolveCurrentCliVersion = async (context) => {
8860
9166
  const candidates = [
8861
- path24.resolve(context.runtimeDir, "..", "package.json"),
8862
- path24.resolve(process.cwd(), "packages", "cli", "package.json"),
8863
- path24.resolve(process.cwd(), "package.json")
9167
+ path25.resolve(context.runtimeDir, "..", "package.json"),
9168
+ path25.resolve(process.cwd(), "packages", "cli", "package.json"),
9169
+ path25.resolve(process.cwd(), "package.json")
8864
9170
  ];
8865
9171
  for (const candidate of candidates) {
8866
9172
  if (!await pathExists2(candidate)) continue;
8867
9173
  const pkg = await readJsonSafe(candidate);
8868
- const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${path24.sep}packages${path24.sep}cli${path24.sep}`));
9174
+ const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${path25.sep}packages${path25.sep}cli${path25.sep}`));
8869
9175
  if (isCliPackage) return pkg.version ?? "0.0.0";
8870
9176
  }
8871
9177
  return "0.0.0";
@@ -9113,7 +9419,7 @@ init_errors();
9113
9419
  init_fs();
9114
9420
  init_json();
9115
9421
  init_src4();
9116
- import path27 from "path";
9422
+ import path29 from "path";
9117
9423
  import { pathToFileURL as pathToFileURL2 } from "url";
9118
9424
  var DEFAULT_TAILWIND_CSS2 = '@import "tailwindcss";\n';
9119
9425
  var DEFAULT_TW_CONFIG = `${JSON.stringify(
@@ -9140,8 +9446,8 @@ async function validateThemeConfig(cwd2) {
9140
9446
  const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
9141
9447
  let configPath = null;
9142
9448
  for (const file of twConfigFiles) {
9143
- if (await pathExists2(path27.join(cwd2, file))) {
9144
- configPath = path27.join(cwd2, file);
9449
+ if (await pathExists2(path29.join(cwd2, file))) {
9450
+ configPath = path29.join(cwd2, file);
9145
9451
  break;
9146
9452
  }
9147
9453
  }
@@ -9232,7 +9538,7 @@ function resolveCliEntry(scriptPath) {
9232
9538
  async function hasTailwindCssImport(cwd2) {
9233
9539
  const cssFiles = ["src/app/globals.css", "src/index.css", "src/style.css", "app/globals.css"];
9234
9540
  for (const file of cssFiles) {
9235
- const raw = await readFileSafe(path27.join(cwd2, file));
9541
+ const raw = await readFileSafe(path29.join(cwd2, file));
9236
9542
  if (raw?.includes("tailwindcss")) return true;
9237
9543
  }
9238
9544
  return false;
@@ -9248,7 +9554,7 @@ async function hasSafelistSource(cwd2) {
9248
9554
  "app/globals.css"
9249
9555
  ];
9250
9556
  for (const file of cssFiles) {
9251
- const raw = await readFileSafe(path27.join(cwd2, file));
9557
+ const raw = await readFileSafe(path29.join(cwd2, file));
9252
9558
  if (raw === null) continue;
9253
9559
  if (raw.includes("tw-classes")) return { found: true, cssFile: file };
9254
9560
  if (raw.includes("tailwindcss")) return { found: false, cssFile: file };
@@ -9256,8 +9562,8 @@ async function hasSafelistSource(cwd2) {
9256
9562
  return { found: false, cssFile: null };
9257
9563
  }
9258
9564
  async function applyTailwindInit(cwd2) {
9259
- await ensureFileSafe(path27.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
9260
- await ensureFileSafe(path27.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
9565
+ await ensureFileSafe(path29.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
9566
+ await ensureFileSafe(path29.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
9261
9567
  }
9262
9568
  function check(results, id, label, pass, message, fix) {
9263
9569
  results.push({ id, label, pass, message, fix });
@@ -9279,7 +9585,7 @@ async function runPreflightCli(rawArgs) {
9279
9585
  node.major >= 20 ? `Node ${node.full} OK` : `Node ${node.full} - requires >=20. Download: https://nodejs.org`,
9280
9586
  node.major < 20 ? "Install Node.js 20 LTS or newer from https://nodejs.org" : void 0
9281
9587
  );
9282
- const pkg = await readJsonSafe(path27.join(cwd2, "package.json"));
9588
+ const pkg = await readJsonSafe(path29.join(cwd2, "package.json"));
9283
9589
  check(
9284
9590
  results,
9285
9591
  "package-json",
@@ -9313,7 +9619,7 @@ async function runPreflightCli(rawArgs) {
9313
9619
  }
9314
9620
  const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
9315
9621
  const twConfigChecks = await Promise.all(
9316
- twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(path27.join(cwd2, file)) }))
9622
+ twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(path29.join(cwd2, file)) }))
9317
9623
  );
9318
9624
  const foundTwConfig = twConfigChecks.find((item) => item.exists)?.file ?? null;
9319
9625
  const hasCssConfig = await hasTailwindCssImport(cwd2);
@@ -9325,7 +9631,7 @@ async function runPreflightCli(rawArgs) {
9325
9631
  foundTwConfig ? `${foundTwConfig} found OK` : hasCssConfig ? "@import tailwindcss found in CSS OK" : "No Tailwind config found - run: tw init",
9326
9632
  "tw init"
9327
9633
  );
9328
- const oldConfig = await readJsonSafe(path27.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(path27.join(cwd2, "tailwind.config.ts"));
9634
+ const oldConfig = await readJsonSafe(path29.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(path29.join(cwd2, "tailwind.config.ts"));
9329
9635
  if (oldConfig) {
9330
9636
  const hasOldJit = oldConfig.mode === "jit";
9331
9637
  const hasOldPurge = "purge" in oldConfig;
@@ -9349,7 +9655,7 @@ async function runPreflightCli(rawArgs) {
9349
9655
  validation.message
9350
9656
  );
9351
9657
  }
9352
- const hasTsConfig = await pathExists2(path27.join(cwd2, "tsconfig.json"));
9658
+ const hasTsConfig = await pathExists2(path29.join(cwd2, "tsconfig.json"));
9353
9659
  check(
9354
9660
  results,
9355
9661
  "typescript",
@@ -9711,7 +10017,7 @@ init_esm_shims();
9711
10017
  init_errors();
9712
10018
  init_fs();
9713
10019
  init_json();
9714
- import path28 from "path";
10020
+ import path30 from "path";
9715
10021
  import { parseArgs as parseNodeArgs11 } from "util";
9716
10022
  var storybookCommand = {
9717
10023
  name: "storybook",
@@ -9750,7 +10056,7 @@ var storybookCommand = {
9750
10056
  context.output.writeText(
9751
10057
  `[tw storybook] Tip: use --variants='{"size":["sm","lg"]}' to enumerate variant combinations`
9752
10058
  );
9753
- const localBin = path28.join(
10059
+ const localBin = path30.join(
9754
10060
  process.cwd(),
9755
10061
  "node_modules",
9756
10062
  ".bin",
@@ -10937,10 +11243,10 @@ async function traceClass(className, options) {
10937
11243
  init_esm_shims();
10938
11244
  init_internal();
10939
11245
  init_src2();
10940
- import fs14 from "fs";
10941
- import path29 from "path";
11246
+ import fs16 from "fs";
11247
+ import path31 from "path";
10942
11248
  function toRelativePath(root, value) {
10943
- const relative = path29.relative(root, value);
11249
+ const relative = path31.relative(root, value);
10944
11250
  return relative.length > 0 ? relative : ".";
10945
11251
  }
10946
11252
  function uniqueSorted(values) {
@@ -11009,7 +11315,7 @@ function tryCompileClasses(classes) {
11009
11315
  }
11010
11316
  }
11011
11317
  function traceSingleFile(filePath, root) {
11012
- const source = fs14.readFileSync(filePath, "utf8");
11318
+ const source = fs16.readFileSync(filePath, "utf8");
11013
11319
  const classes = uniqueSorted(scanSource(source));
11014
11320
  const imports = extractImports(source);
11015
11321
  const compiled = tryCompileClasses(classes);
@@ -11040,7 +11346,7 @@ function traceDirectory(targetDir, root) {
11040
11346
  const imports = [];
11041
11347
  const importKeys = /* @__PURE__ */ new Set();
11042
11348
  const files = scanResult.files.filter((entry) => isScannableFile2(entry.file, DEFAULT_EXTENSIONS)).map((entry) => {
11043
- const source = fs14.readFileSync(entry.file, "utf8");
11349
+ const source = fs16.readFileSync(entry.file, "utf8");
11044
11350
  const fileImports = extractImports(source);
11045
11351
  for (const fileImport of fileImports) {
11046
11352
  const key = `${fileImport.kind}:${fileImport.source}`;
@@ -11071,12 +11377,12 @@ function traceDirectory(targetDir, root) {
11071
11377
  };
11072
11378
  }
11073
11379
  async function traceTarget(target, options = {}) {
11074
- const root = path29.resolve(options.root ?? process.cwd());
11075
- const resolvedTarget = path29.resolve(root, target);
11076
- if (!fs14.existsSync(resolvedTarget)) {
11380
+ const root = path31.resolve(options.root ?? process.cwd());
11381
+ const resolvedTarget = path31.resolve(root, target);
11382
+ if (!fs16.existsSync(resolvedTarget)) {
11077
11383
  throw new Error(`Trace target not found: ${resolvedTarget}`);
11078
11384
  }
11079
- const stat = fs14.statSync(resolvedTarget);
11385
+ const stat = fs16.statSync(resolvedTarget);
11080
11386
  if (stat.isDirectory()) {
11081
11387
  return traceDirectory(resolvedTarget, root);
11082
11388
  }
@@ -11241,14 +11547,14 @@ function printClassTraceOutput(result, output) {
11241
11547
  init_esm_shims();
11242
11548
  var import_picocolors6 = __toESM(require_picocolors(), 1);
11243
11549
  init_output();
11244
- import fs15 from "fs";
11245
- import path30 from "path";
11550
+ import fs17 from "fs";
11551
+ import path32 from "path";
11246
11552
  async function runGenerateTypesCli(rawArgs) {
11247
11553
  const output = createCliOutput({ json: rawArgs.includes("--json") });
11248
11554
  const logger = createCliLogger({ output });
11249
11555
  const cwd2 = process.cwd();
11250
11556
  const outFile = rawArgs.find((a) => a.startsWith("--out="))?.slice(6) ?? "src/types/tailwind-styled.d.ts";
11251
- const outPath = path30.resolve(cwd2, outFile);
11557
+ const outPath = path32.resolve(cwd2, outFile);
11252
11558
  output.writeText("");
11253
11559
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.cyan(" \u25C6 tw generate-types")));
11254
11560
  output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
@@ -11284,12 +11590,12 @@ async function runGenerateTypesCli(rawArgs) {
11284
11590
  }
11285
11591
  output.writeText("");
11286
11592
  output.writeText(import_picocolors6.default.bold(" [2/2]") + import_picocolors6.default.cyan(" generate .d.ts"));
11287
- const outDir = path30.dirname(outPath);
11288
- if (!fs15.existsSync(outDir)) {
11289
- fs15.mkdirSync(outDir, { recursive: true });
11593
+ const outDir = path32.dirname(outPath);
11594
+ if (!fs17.existsSync(outDir)) {
11595
+ fs17.mkdirSync(outDir, { recursive: true });
11290
11596
  }
11291
- fs15.writeFileSync(outPath, result.dtsContent, "utf-8");
11292
- logger.ok(path30.relative(cwd2, outPath));
11597
+ fs17.writeFileSync(outPath, result.dtsContent, "utf-8");
11598
+ logger.ok(path32.relative(cwd2, outPath));
11293
11599
  output.writeText("");
11294
11600
  output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11295
11601
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.green(" \u2713 types generated")));
@@ -11300,11 +11606,11 @@ async function runGenerateTypesCli(rawArgs) {
11300
11606
  }
11301
11607
  async function loadNativeBinding2(cwd2) {
11302
11608
  const candidates = [
11303
- path30.join(cwd2, "native", "tailwind-styled-native.node"),
11304
- path30.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
11609
+ path32.join(cwd2, "native", "tailwind-styled-native.node"),
11610
+ path32.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
11305
11611
  ];
11306
11612
  for (const candidate of candidates) {
11307
- if (fs15.existsSync(candidate)) {
11613
+ if (fs17.existsSync(candidate)) {
11308
11614
  try {
11309
11615
  return __require(candidate);
11310
11616
  } catch {
@@ -11322,8 +11628,8 @@ import { parseArgs as parseNodeArgs14 } from "util";
11322
11628
  // packages/infrastructure/cli/src/utils/whyService.ts
11323
11629
  init_esm_shims();
11324
11630
  init_internal();
11325
- import fs16 from "fs";
11326
- import path31 from "path";
11631
+ import fs18 from "fs";
11632
+ import path33 from "path";
11327
11633
  init_src2();
11328
11634
  function extractVariantChain(usage) {
11329
11635
  const segments = normalizeScannedClass(usage).split(":").filter(Boolean);
@@ -11371,7 +11677,7 @@ async function whyClass(className, options) {
11371
11677
  for (const file of scanResult.files) {
11372
11678
  const source = (() => {
11373
11679
  try {
11374
- return fs16.readFileSync(file.file, "utf8");
11680
+ return fs18.readFileSync(file.file, "utf8");
11375
11681
  } catch {
11376
11682
  return "";
11377
11683
  }
@@ -11385,7 +11691,7 @@ async function whyClass(className, options) {
11385
11691
  className
11386
11692
  ]);
11387
11693
  usedIn.push({
11388
- file: path31.relative(root, file.file) || path31.basename(file.file),
11694
+ file: path33.relative(root, file.file) || path33.basename(file.file),
11389
11695
  line: location.line,
11390
11696
  column: location.column,
11391
11697
  usage: normalizeScannedClass(fileClass)
@@ -11692,6 +11998,12 @@ function buildMainProgram(context) {
11692
11998
  );
11693
11999
  });
11694
12000
  });
12001
+ const figmaTopLevel = program2.command("figma").description("Figma design token sync");
12002
+ ["pull", "push", "diff"].forEach((subcommand) => {
12003
+ figmaTopLevel.command(`${subcommand} [args...]`).description(`Figma ${subcommand}`).allowUnknownOption(true).action(async (args) => {
12004
+ await figmaCommand.run(contextArgs([subcommand, ...toVariadic(args)], context), context);
12005
+ });
12006
+ });
11695
12007
  program2.command("test").description("Test shortcut wrapper").option("--watch", "Watch mode").action(async (...actionArgs) => {
11696
12008
  const options = actionCommand(actionArgs).opts();
11697
12009
  const args = [];