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/cli.js CHANGED
@@ -988,8 +988,8 @@ var require_command = __commonJS({
988
988
  init_cjs_shims();
989
989
  var EventEmitter = require("events").EventEmitter;
990
990
  var childProcess = require("child_process");
991
- var path31 = require("path");
992
- var fs17 = require("fs");
991
+ var path33 = require("path");
992
+ var fs19 = require("fs");
993
993
  var process2 = require("process");
994
994
  var { Argument: Argument2, humanReadableArgName } = require_argument();
995
995
  var { CommanderError: CommanderError2 } = require_error();
@@ -1921,11 +1921,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1921
1921
  let launchWithNode = false;
1922
1922
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1923
1923
  function findFile(baseDir, baseName) {
1924
- const localBin = path31.resolve(baseDir, baseName);
1925
- if (fs17.existsSync(localBin)) return localBin;
1926
- if (sourceExt.includes(path31.extname(baseName))) return void 0;
1924
+ const localBin = path33.resolve(baseDir, baseName);
1925
+ if (fs19.existsSync(localBin)) return localBin;
1926
+ if (sourceExt.includes(path33.extname(baseName))) return void 0;
1927
1927
  const foundExt = sourceExt.find(
1928
- (ext) => fs17.existsSync(`${localBin}${ext}`)
1928
+ (ext) => fs19.existsSync(`${localBin}${ext}`)
1929
1929
  );
1930
1930
  if (foundExt) return `${localBin}${foundExt}`;
1931
1931
  return void 0;
@@ -1937,21 +1937,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1937
1937
  if (this._scriptPath) {
1938
1938
  let resolvedScriptPath;
1939
1939
  try {
1940
- resolvedScriptPath = fs17.realpathSync(this._scriptPath);
1940
+ resolvedScriptPath = fs19.realpathSync(this._scriptPath);
1941
1941
  } catch (err) {
1942
1942
  resolvedScriptPath = this._scriptPath;
1943
1943
  }
1944
- executableDir = path31.resolve(
1945
- path31.dirname(resolvedScriptPath),
1944
+ executableDir = path33.resolve(
1945
+ path33.dirname(resolvedScriptPath),
1946
1946
  executableDir
1947
1947
  );
1948
1948
  }
1949
1949
  if (executableDir) {
1950
1950
  let localFile = findFile(executableDir, executableFile);
1951
1951
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1952
- const legacyName = path31.basename(
1952
+ const legacyName = path33.basename(
1953
1953
  this._scriptPath,
1954
- path31.extname(this._scriptPath)
1954
+ path33.extname(this._scriptPath)
1955
1955
  );
1956
1956
  if (legacyName !== this._name) {
1957
1957
  localFile = findFile(
@@ -1962,7 +1962,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1962
1962
  }
1963
1963
  executableFile = localFile || executableFile;
1964
1964
  }
1965
- launchWithNode = sourceExt.includes(path31.extname(executableFile));
1965
+ launchWithNode = sourceExt.includes(path33.extname(executableFile));
1966
1966
  let proc;
1967
1967
  if (process2.platform !== "win32") {
1968
1968
  if (launchWithNode) {
@@ -2802,7 +2802,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2802
2802
  * @return {Command}
2803
2803
  */
2804
2804
  nameFromFilename(filename) {
2805
- this._name = path31.basename(filename, path31.extname(filename));
2805
+ this._name = path33.basename(filename, path33.extname(filename));
2806
2806
  return this;
2807
2807
  }
2808
2808
  /**
@@ -2816,9 +2816,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2816
2816
  * @param {string} [path]
2817
2817
  * @return {(string|null|Command)}
2818
2818
  */
2819
- executableDir(path32) {
2820
- if (path32 === void 0) return this._executableDir;
2821
- this._executableDir = path32;
2819
+ executableDir(path34) {
2820
+ if (path34 === void 0) return this._executableDir;
2821
+ this._executableDir = path34;
2822
2822
  return this;
2823
2823
  }
2824
2824
  /**
@@ -3332,9 +3332,9 @@ function createDebugLogger(namespace, label) {
3332
3332
  }
3333
3333
  };
3334
3334
  }
3335
- function formatIssuePath(path31) {
3336
- if (!path31 || path31.length === 0) return "(root)";
3337
- return path31.map(
3335
+ function formatIssuePath(path33) {
3336
+ if (!path33 || path33.length === 0) return "(root)";
3337
+ return path33.map(
3338
3338
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
3339
3339
  ).join(".");
3340
3340
  }
@@ -3455,8 +3455,8 @@ var init_src = __esm({
3455
3455
  /** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
3456
3456
  static fromZod(err) {
3457
3457
  const first = err.issues?.[0] ?? err.errors?.[0];
3458
- const path31 = formatIssuePath(first?.path);
3459
- const message = first ? `${path31}: ${first.message}` : "Schema validation failed";
3458
+ const path33 = formatIssuePath(first?.path);
3459
+ const message = first ? `${path33}: ${first.message}` : "Schema validation failed";
3460
3460
  return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
3461
3461
  }
3462
3462
  static wrap(source, code, err) {
@@ -4013,12 +4013,12 @@ var init_schemas = __esm({
4013
4013
  init_cjs_shims();
4014
4014
  import_zod = require("zod");
4015
4015
  init_src();
4016
- formatIssuePath2 = (path31) => path31.length > 0 ? path31.map(
4016
+ formatIssuePath2 = (path33) => path33.length > 0 ? path33.map(
4017
4017
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
4018
4018
  ).join(".") : "<root>";
4019
4019
  formatIssues = (error) => error.issues.map((issue) => {
4020
- const path31 = formatIssuePath2(issue.path);
4021
- return `${path31}: ${issue.message}`;
4020
+ const path33 = formatIssuePath2(issue.path);
4021
+ return `${path33}: ${issue.message}`;
4022
4022
  }).join("; ");
4023
4023
  parseWithSchema = (schema, data, label) => {
4024
4024
  const parsed = schema.safeParse(data);
@@ -4624,7 +4624,7 @@ var init_schemas2 = __esm({
4624
4624
  init_cjs_shims();
4625
4625
  init_src();
4626
4626
  import_zod2 = require("zod");
4627
- formatIssuePath3 = (path31) => path31.length > 0 ? path31.map(
4627
+ formatIssuePath3 = (path33) => path33.length > 0 ? path33.map(
4628
4628
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
4629
4629
  ).join(".") : "<root>";
4630
4630
  isPlainObject = (value) => {
@@ -4633,8 +4633,8 @@ var init_schemas2 = __esm({
4633
4633
  return proto === Object.prototype || proto === null;
4634
4634
  };
4635
4635
  formatIssues2 = (error) => error.issues.map((issue) => {
4636
- const path31 = formatIssuePath3(issue.path);
4637
- return `${path31}: ${issue.message}`;
4636
+ const path33 = formatIssuePath3(issue.path);
4637
+ return `${path33}: ${issue.message}`;
4638
4638
  }).join("; ");
4639
4639
  parseWithSchema2 = (schema, data, label) => {
4640
4640
  const parsed = schema.safeParse(data);
@@ -6254,7 +6254,7 @@ var init_nativeBridge = __esm({
6254
6254
  "use strict";
6255
6255
  init_cjs_shims();
6256
6256
  init_src();
6257
- _loadNative = (path31) => require(path31);
6257
+ _loadNative = (path33) => require(path33);
6258
6258
  log3 = (...args) => {
6259
6259
  if (process.env.DEBUG?.includes("compiler:native")) {
6260
6260
  console.log("[compiler:native]", ...args);
@@ -6397,24 +6397,51 @@ var init_watch = __esm({
6397
6397
  });
6398
6398
 
6399
6399
  // packages/domain/compiler/src/routeGraph.ts
6400
- var import_node_fs9, import_node_path24;
6400
+ var import_node_fs10, import_node_path25;
6401
6401
  var init_routeGraph = __esm({
6402
6402
  "packages/domain/compiler/src/routeGraph.ts"() {
6403
6403
  "use strict";
6404
6404
  init_cjs_shims();
6405
- import_node_fs9 = __toESM(require("fs"), 1);
6406
- import_node_path24 = __toESM(require("path"), 1);
6405
+ import_node_fs10 = __toESM(require("fs"), 1);
6406
+ import_node_path25 = __toESM(require("path"), 1);
6407
+ }
6408
+ });
6409
+
6410
+ // packages/domain/compiler/src/semanticComponentAnalyzer.ts
6411
+ var init_semanticComponentAnalyzer = __esm({
6412
+ "packages/domain/compiler/src/semanticComponentAnalyzer.ts"() {
6413
+ "use strict";
6414
+ init_cjs_shims();
6415
+ }
6416
+ });
6417
+
6418
+ // packages/domain/compiler/src/typeGeneratorFromMetadata.ts
6419
+ var init_typeGeneratorFromMetadata = __esm({
6420
+ "packages/domain/compiler/src/typeGeneratorFromMetadata.ts"() {
6421
+ "use strict";
6422
+ init_cjs_shims();
6423
+ }
6424
+ });
6425
+
6426
+ // packages/domain/compiler/src/typeGenerationPlugin.ts
6427
+ var import_node_fs11, import_node_path26;
6428
+ var init_typeGenerationPlugin = __esm({
6429
+ "packages/domain/compiler/src/typeGenerationPlugin.ts"() {
6430
+ "use strict";
6431
+ init_cjs_shims();
6432
+ import_node_fs11 = __toESM(require("fs"), 1);
6433
+ import_node_path26 = __toESM(require("path"), 1);
6407
6434
  }
6408
6435
  });
6409
6436
 
6410
6437
  // packages/domain/compiler/src/index.ts
6411
- var import_node_fs10, import_node_path25, import_node_module4, _require3, compileCssFromClasses;
6438
+ var import_node_fs12, import_node_path27, import_node_module4, _require3, compileCssFromClasses;
6412
6439
  var init_src4 = __esm({
6413
6440
  "packages/domain/compiler/src/index.ts"() {
6414
6441
  "use strict";
6415
6442
  init_cjs_shims();
6416
- import_node_fs10 = __toESM(require("fs"), 1);
6417
- import_node_path25 = __toESM(require("path"), 1);
6443
+ import_node_fs12 = __toESM(require("fs"), 1);
6444
+ import_node_path27 = __toESM(require("path"), 1);
6418
6445
  import_node_module4 = require("module");
6419
6446
  init_nativeBridge();
6420
6447
  init_compiler();
@@ -6424,6 +6451,9 @@ var init_src4 = __esm({
6424
6451
  init_redis();
6425
6452
  init_watch();
6426
6453
  init_routeGraph();
6454
+ init_semanticComponentAnalyzer();
6455
+ init_typeGeneratorFromMetadata();
6456
+ init_typeGenerationPlugin();
6427
6457
  _require3 = (0, import_node_module4.createRequire)(
6428
6458
  typeof require !== "undefined" ? typeof __filename !== "undefined" ? `file://${__filename}` : "file://unknown" : importMetaUrl
6429
6459
  );
@@ -6459,6 +6489,7 @@ var init_internal = __esm({
6459
6489
  // src/umbrella/cli.ts
6460
6490
  var cli_exports = {};
6461
6491
  __export(cli_exports, {
6492
+ buildMainProgram: () => buildMainProgram,
6462
6493
  createCliOutput: () => createCliOutput,
6463
6494
  ensureFlag: () => ensureFlag,
6464
6495
  parseCliArgs: () => parseCliInput,
@@ -8738,9 +8769,286 @@ function printDoctorOutput(result, output) {
8738
8769
  );
8739
8770
  }
8740
8771
 
8741
- // packages/infrastructure/cli/src/commands/misc.ts
8772
+ // packages/infrastructure/cli/src/commands/figma.ts
8742
8773
  init_cjs_shims();
8774
+ var import_node_fs9 = __toESM(require("fs"), 1);
8743
8775
  var import_node_path23 = __toESM(require("path"), 1);
8776
+ init_errors();
8777
+
8778
+ // packages/infrastructure/cli/src/utils/figmaApi.ts
8779
+ init_cjs_shims();
8780
+ async function figmaRequest(endpoint, options) {
8781
+ const { token, fileKey } = options;
8782
+ if (!token) {
8783
+ throw new Error("FIGMA_TOKEN environment variable not set");
8784
+ }
8785
+ if (!fileKey) {
8786
+ throw new Error("FIGMA_FILE_KEY environment variable not set");
8787
+ }
8788
+ const url = `https://api.figma.com/v1${endpoint.replace(":fileKey", fileKey)}`;
8789
+ const res = await fetch(url, {
8790
+ headers: { "X-Figma-Token": token }
8791
+ });
8792
+ if (!res.ok) {
8793
+ const body = await res.text();
8794
+ throw new Error(`Figma API ${res.status}: ${body.slice(0, 200)}`);
8795
+ }
8796
+ return res.json();
8797
+ }
8798
+ function figmaColorToHex(color) {
8799
+ const { r, g, b, a = 1 } = color;
8800
+ const toHex = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
8801
+ const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
8802
+ return a < 1 ? `${hex}${toHex(a)}` : hex;
8803
+ }
8804
+ function figmaVariablesToTokens(variablesData) {
8805
+ const tokens = {};
8806
+ const { variables = {}, variableCollections = {} } = variablesData;
8807
+ for (const [id, variable] of Object.entries(variables)) {
8808
+ const collection = variableCollections?.[variable.variableCollectionId];
8809
+ if (!collection) continue;
8810
+ const modeId = Object.keys(variable.valuesByMode)[0];
8811
+ const rawValue = variable.valuesByMode[modeId];
8812
+ if (rawValue === void 0) continue;
8813
+ const parts = variable.name.split("/").map(
8814
+ (p) => p.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")
8815
+ );
8816
+ let cursor = tokens;
8817
+ for (let i = 0; i < parts.length - 1; i++) {
8818
+ cursor[parts[i]] ??= {};
8819
+ cursor = cursor[parts[i]];
8820
+ }
8821
+ const leafKey = parts[parts.length - 1];
8822
+ if (variable.resolvedType === "COLOR") {
8823
+ const token = {
8824
+ $value: typeof rawValue === "object" && rawValue !== null && "r" in rawValue ? figmaColorToHex(rawValue) : String(rawValue),
8825
+ $type: "color"
8826
+ };
8827
+ if (variable.description) token.$description = variable.description;
8828
+ token._figmaId = id;
8829
+ cursor[leafKey] = token;
8830
+ } else if (variable.resolvedType === "FLOAT") {
8831
+ cursor[leafKey] = {
8832
+ $value: typeof rawValue === "number" ? `${rawValue}px` : String(rawValue),
8833
+ $type: "dimension",
8834
+ _figmaId: id
8835
+ };
8836
+ } else if (variable.resolvedType === "STRING") {
8837
+ cursor[leafKey] = {
8838
+ $value: String(rawValue),
8839
+ $type: "other",
8840
+ _figmaId: id
8841
+ };
8842
+ }
8843
+ }
8844
+ return tokens;
8845
+ }
8846
+
8847
+ // packages/infrastructure/cli/src/utils/tokenUtils.ts
8848
+ init_cjs_shims();
8849
+ function tokensToFigmaUpdates(tokens, existingVariables = {}) {
8850
+ const updates = [];
8851
+ function walk(obj, path33 = []) {
8852
+ for (const [key, val] of Object.entries(obj)) {
8853
+ if (typeof val === "object" && val !== null && "$value" in val) {
8854
+ const tokenVal = val;
8855
+ const name = path33.concat(key).map(
8856
+ (p) => p.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("")
8857
+ ).join("/");
8858
+ const existing = Object.values(existingVariables).find(
8859
+ (v) => v.name === name
8860
+ );
8861
+ if (existing) {
8862
+ updates.push({
8863
+ id: existing.id,
8864
+ name,
8865
+ value: tokenVal.$value,
8866
+ type: tokenVal.$type
8867
+ });
8868
+ }
8869
+ } else if (typeof val === "object" && val !== null && !("$type" in val)) {
8870
+ walk(val, path33.concat(key));
8871
+ }
8872
+ }
8873
+ }
8874
+ walk(tokens);
8875
+ return updates;
8876
+ }
8877
+ function flattenTokens(obj, prefix = "", target = {}) {
8878
+ for (const [k, v] of Object.entries(obj)) {
8879
+ const key = [prefix, k].filter(Boolean).join(".");
8880
+ if (typeof v === "object" && v !== null && "$value" in v) {
8881
+ const tokenVal = v;
8882
+ target[key] = tokenVal.$value;
8883
+ } else if (typeof v === "object" && v !== null && !("$type" in v)) {
8884
+ flattenTokens(v, key, target);
8885
+ }
8886
+ }
8887
+ return target;
8888
+ }
8889
+ function diffTokens(local, figma) {
8890
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(figma)]);
8891
+ const diffs = [];
8892
+ for (const key of allKeys) {
8893
+ if (local[key] !== figma[key]) {
8894
+ diffs.push({
8895
+ key,
8896
+ local: local[key],
8897
+ figma: figma[key]
8898
+ });
8899
+ }
8900
+ }
8901
+ return diffs;
8902
+ }
8903
+
8904
+ // packages/infrastructure/cli/src/commands/figma.ts
8905
+ var figmaCommand = {
8906
+ name: "figma",
8907
+ async run(args, context) {
8908
+ const cmd = args[0];
8909
+ const isDryRun = args.includes("--dry-run");
8910
+ const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
8911
+ const FIGMA_FILE_KEY = process.env.FIGMA_FILE_KEY;
8912
+ const TOKEN_FILE = import_node_path23.default.join(context.cwd, "tokens.sync.json");
8913
+ if (!cmd || cmd === "help") {
8914
+ context.output.writeText(`Usage: tw figma <pull|push|diff> [--dry-run]
8915
+
8916
+ Environment variables:
8917
+ FIGMA_TOKEN \u2014 Figma personal access token (figd_...)
8918
+ FIGMA_FILE_KEY \u2014 Figma file key (from URL: figma.com/file/<KEY>/...)
8919
+
8920
+ Commands:
8921
+ pull Import Figma variables \u2192 tokens.sync.json
8922
+ push Export tokens.sync.json \u2192 Figma variables
8923
+ diff Show differences between local and Figma
8924
+
8925
+ Options:
8926
+ --dry-run Show what would change without writing`);
8927
+ return;
8928
+ }
8929
+ if (cmd === "pull") {
8930
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
8931
+ throw new CliUsageError(
8932
+ "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"
8933
+ );
8934
+ }
8935
+ try {
8936
+ const spinner = context.output.spinner();
8937
+ spinner.start("Fetching Figma variables...");
8938
+ const data = await figmaRequest("/files/:fileKey/variables/local", {
8939
+ token: FIGMA_TOKEN,
8940
+ fileKey: FIGMA_FILE_KEY
8941
+ });
8942
+ spinner.stop();
8943
+ const tokens = figmaVariablesToTokens(data);
8944
+ const variableCount = Object.values(data.variables ?? {}).length;
8945
+ if (isDryRun) {
8946
+ context.output.info("DRY RUN \u2014 would write:");
8947
+ context.output.writeText(JSON.stringify({ version: 1, tokens }, null, 2));
8948
+ } else {
8949
+ let existing = { version: 1, tokens: {} };
8950
+ if (import_node_fs9.default.existsSync(TOKEN_FILE)) {
8951
+ try {
8952
+ existing = JSON.parse(import_node_fs9.default.readFileSync(TOKEN_FILE, "utf8"));
8953
+ } catch {
8954
+ }
8955
+ }
8956
+ const merged = {
8957
+ ...existing,
8958
+ tokens: { ...existing.tokens, ...tokens },
8959
+ figmaFileKey: FIGMA_FILE_KEY,
8960
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
8961
+ source: "figma"
8962
+ };
8963
+ import_node_fs9.default.writeFileSync(TOKEN_FILE, JSON.stringify(merged, null, 2) + "\n");
8964
+ context.output.success(
8965
+ `Pulled ${variableCount} variables from Figma \u2192 ${TOKEN_FILE}`
8966
+ );
8967
+ }
8968
+ } catch (e) {
8969
+ throw new CliUsageError(
8970
+ `Pull failed: ${e instanceof Error ? e.message : String(e)}`
8971
+ );
8972
+ }
8973
+ } else if (cmd === "push") {
8974
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
8975
+ throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
8976
+ }
8977
+ if (!import_node_fs9.default.existsSync(TOKEN_FILE)) {
8978
+ throw new CliUsageError(
8979
+ `${TOKEN_FILE} not found. Run 'tw sync init' first.`
8980
+ );
8981
+ }
8982
+ try {
8983
+ const local = JSON.parse(import_node_fs9.default.readFileSync(TOKEN_FILE, "utf8"));
8984
+ const data = await figmaRequest("/files/:fileKey/variables/local", {
8985
+ token: FIGMA_TOKEN,
8986
+ fileKey: FIGMA_FILE_KEY
8987
+ });
8988
+ const updates = tokensToFigmaUpdates(local.tokens ?? {}, data.variables?.length ? Object.entries(data.variables ?? {}).reduce((acc, [id, v]) => ({ ...acc, [id]: { ...v, id } }), {}) : {});
8989
+ if (isDryRun) {
8990
+ context.output.info(
8991
+ `DRY RUN \u2014 would update ${updates.length} variables in Figma:`
8992
+ );
8993
+ updates.forEach((u) => context.output.writeText(` ${u.name}: ${u.value}`));
8994
+ } else {
8995
+ if (updates.length === 0) {
8996
+ context.output.info("No matching variables to update");
8997
+ } else {
8998
+ context.output.success(`Updated ${updates.length} variables in Figma`);
8999
+ }
9000
+ }
9001
+ } catch (e) {
9002
+ throw new CliUsageError(
9003
+ `Push failed: ${e instanceof Error ? e.message : String(e)}`
9004
+ );
9005
+ }
9006
+ } else if (cmd === "diff") {
9007
+ if (!FIGMA_TOKEN || !FIGMA_FILE_KEY) {
9008
+ throw new CliUsageError("Missing FIGMA_TOKEN or FIGMA_FILE_KEY");
9009
+ }
9010
+ if (!import_node_fs9.default.existsSync(TOKEN_FILE)) {
9011
+ throw new CliUsageError("tokens.sync.json not found");
9012
+ }
9013
+ try {
9014
+ const [local, figmaData] = await Promise.all([
9015
+ JSON.parse(import_node_fs9.default.readFileSync(TOKEN_FILE, "utf8")),
9016
+ figmaRequest("/files/:fileKey/variables/local", {
9017
+ token: FIGMA_TOKEN,
9018
+ fileKey: FIGMA_FILE_KEY
9019
+ })
9020
+ ]);
9021
+ const figmaTokens = figmaVariablesToTokens(figmaData);
9022
+ const figmaFlat = {};
9023
+ const localFlat = {};
9024
+ flattenTokens(local.tokens ?? {}, "", localFlat);
9025
+ flattenTokens(figmaTokens, "", figmaFlat);
9026
+ const diffs = diffTokens(localFlat, figmaFlat);
9027
+ if (diffs.length === 0) {
9028
+ context.output.success("No differences \u2014 local and Figma are in sync");
9029
+ } else {
9030
+ context.output.info(`${diffs.length} differences found:
9031
+ `);
9032
+ diffs.forEach((d) => {
9033
+ context.output.writeText(` ${d.key}`);
9034
+ context.output.writeText(` local: ${d.local ?? "(missing)"}`);
9035
+ context.output.writeText(` figma: ${d.figma ?? "(missing)"}`);
9036
+ });
9037
+ }
9038
+ } catch (e) {
9039
+ throw new CliUsageError(
9040
+ `Diff failed: ${e instanceof Error ? e.message : String(e)}`
9041
+ );
9042
+ }
9043
+ } else {
9044
+ throw new CliUsageError(`Unknown command: ${cmd}`);
9045
+ }
9046
+ }
9047
+ };
9048
+
9049
+ // packages/infrastructure/cli/src/commands/misc.ts
9050
+ init_cjs_shims();
9051
+ var import_node_path24 = __toESM(require("path"), 1);
8744
9052
  var import_node_util9 = require("util");
8745
9053
  init_errors();
8746
9054
  init_fs();
@@ -8773,7 +9081,7 @@ var shareCommand = {
8773
9081
  name: "share",
8774
9082
  async run(args, context) {
8775
9083
  const name = args.find((arg) => !arg.startsWith("-")) ?? "component-name";
8776
- const manifestPath = import_node_path23.default.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
9084
+ const manifestPath = import_node_path24.default.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
8777
9085
  const defaultManifest = {
8778
9086
  name,
8779
9087
  version: "0.1.0"
@@ -8859,14 +9167,14 @@ var isVersionOutdated = (currentVersion, latestVersion) => {
8859
9167
  };
8860
9168
  var resolveCurrentCliVersion = async (context) => {
8861
9169
  const candidates = [
8862
- import_node_path23.default.resolve(context.runtimeDir, "..", "package.json"),
8863
- import_node_path23.default.resolve(process.cwd(), "packages", "cli", "package.json"),
8864
- import_node_path23.default.resolve(process.cwd(), "package.json")
9170
+ import_node_path24.default.resolve(context.runtimeDir, "..", "package.json"),
9171
+ import_node_path24.default.resolve(process.cwd(), "packages", "cli", "package.json"),
9172
+ import_node_path24.default.resolve(process.cwd(), "package.json")
8865
9173
  ];
8866
9174
  for (const candidate of candidates) {
8867
9175
  if (!await pathExists2(candidate)) continue;
8868
9176
  const pkg = await readJsonSafe(candidate);
8869
- const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${import_node_path23.default.sep}packages${import_node_path23.default.sep}cli${import_node_path23.default.sep}`));
9177
+ const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${import_node_path24.default.sep}packages${import_node_path24.default.sep}cli${import_node_path24.default.sep}`));
8870
9178
  if (isCliPackage) return pkg.version ?? "0.0.0";
8871
9179
  }
8872
9180
  return "0.0.0";
@@ -9109,7 +9417,7 @@ init_cjs_shims();
9109
9417
 
9110
9418
  // packages/infrastructure/cli/src/preflight.ts
9111
9419
  init_cjs_shims();
9112
- var import_node_path26 = __toESM(require("path"), 1);
9420
+ var import_node_path28 = __toESM(require("path"), 1);
9113
9421
  var import_node_url7 = require("url");
9114
9422
  init_args();
9115
9423
  init_errors();
@@ -9142,8 +9450,8 @@ async function validateThemeConfig(cwd2) {
9142
9450
  const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
9143
9451
  let configPath = null;
9144
9452
  for (const file of twConfigFiles) {
9145
- if (await pathExists2(import_node_path26.default.join(cwd2, file))) {
9146
- configPath = import_node_path26.default.join(cwd2, file);
9453
+ if (await pathExists2(import_node_path28.default.join(cwd2, file))) {
9454
+ configPath = import_node_path28.default.join(cwd2, file);
9147
9455
  break;
9148
9456
  }
9149
9457
  }
@@ -9234,7 +9542,7 @@ function resolveCliEntry(scriptPath) {
9234
9542
  async function hasTailwindCssImport(cwd2) {
9235
9543
  const cssFiles = ["src/app/globals.css", "src/index.css", "src/style.css", "app/globals.css"];
9236
9544
  for (const file of cssFiles) {
9237
- const raw = await readFileSafe(import_node_path26.default.join(cwd2, file));
9545
+ const raw = await readFileSafe(import_node_path28.default.join(cwd2, file));
9238
9546
  if (raw?.includes("tailwindcss")) return true;
9239
9547
  }
9240
9548
  return false;
@@ -9250,7 +9558,7 @@ async function hasSafelistSource(cwd2) {
9250
9558
  "app/globals.css"
9251
9559
  ];
9252
9560
  for (const file of cssFiles) {
9253
- const raw = await readFileSafe(import_node_path26.default.join(cwd2, file));
9561
+ const raw = await readFileSafe(import_node_path28.default.join(cwd2, file));
9254
9562
  if (raw === null) continue;
9255
9563
  if (raw.includes("tw-classes")) return { found: true, cssFile: file };
9256
9564
  if (raw.includes("tailwindcss")) return { found: false, cssFile: file };
@@ -9258,8 +9566,8 @@ async function hasSafelistSource(cwd2) {
9258
9566
  return { found: false, cssFile: null };
9259
9567
  }
9260
9568
  async function applyTailwindInit(cwd2) {
9261
- await ensureFileSafe(import_node_path26.default.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
9262
- await ensureFileSafe(import_node_path26.default.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
9569
+ await ensureFileSafe(import_node_path28.default.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
9570
+ await ensureFileSafe(import_node_path28.default.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
9263
9571
  }
9264
9572
  function check(results, id, label, pass, message, fix) {
9265
9573
  results.push({ id, label, pass, message, fix });
@@ -9281,7 +9589,7 @@ async function runPreflightCli(rawArgs) {
9281
9589
  node.major >= 20 ? `Node ${node.full} OK` : `Node ${node.full} - requires >=20. Download: https://nodejs.org`,
9282
9590
  node.major < 20 ? "Install Node.js 20 LTS or newer from https://nodejs.org" : void 0
9283
9591
  );
9284
- const pkg = await readJsonSafe(import_node_path26.default.join(cwd2, "package.json"));
9592
+ const pkg = await readJsonSafe(import_node_path28.default.join(cwd2, "package.json"));
9285
9593
  check(
9286
9594
  results,
9287
9595
  "package-json",
@@ -9315,7 +9623,7 @@ async function runPreflightCli(rawArgs) {
9315
9623
  }
9316
9624
  const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
9317
9625
  const twConfigChecks = await Promise.all(
9318
- twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(import_node_path26.default.join(cwd2, file)) }))
9626
+ twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(import_node_path28.default.join(cwd2, file)) }))
9319
9627
  );
9320
9628
  const foundTwConfig = twConfigChecks.find((item) => item.exists)?.file ?? null;
9321
9629
  const hasCssConfig = await hasTailwindCssImport(cwd2);
@@ -9327,7 +9635,7 @@ async function runPreflightCli(rawArgs) {
9327
9635
  foundTwConfig ? `${foundTwConfig} found OK` : hasCssConfig ? "@import tailwindcss found in CSS OK" : "No Tailwind config found - run: tw init",
9328
9636
  "tw init"
9329
9637
  );
9330
- const oldConfig = await readJsonSafe(import_node_path26.default.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(import_node_path26.default.join(cwd2, "tailwind.config.ts"));
9638
+ const oldConfig = await readJsonSafe(import_node_path28.default.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(import_node_path28.default.join(cwd2, "tailwind.config.ts"));
9331
9639
  if (oldConfig) {
9332
9640
  const hasOldJit = oldConfig.mode === "jit";
9333
9641
  const hasOldPurge = "purge" in oldConfig;
@@ -9351,7 +9659,7 @@ async function runPreflightCli(rawArgs) {
9351
9659
  validation.message
9352
9660
  );
9353
9661
  }
9354
- const hasTsConfig = await pathExists2(import_node_path26.default.join(cwd2, "tsconfig.json"));
9662
+ const hasTsConfig = await pathExists2(import_node_path28.default.join(cwd2, "tsconfig.json"));
9355
9663
  check(
9356
9664
  results,
9357
9665
  "typescript",
@@ -9710,7 +10018,7 @@ var scriptCommands = [
9710
10018
 
9711
10019
  // packages/infrastructure/cli/src/commands/storybook.ts
9712
10020
  init_cjs_shims();
9713
- var import_node_path27 = __toESM(require("path"), 1);
10021
+ var import_node_path29 = __toESM(require("path"), 1);
9714
10022
  var import_node_util11 = require("util");
9715
10023
  init_errors();
9716
10024
  init_fs();
@@ -9752,7 +10060,7 @@ var storybookCommand = {
9752
10060
  context.output.writeText(
9753
10061
  `[tw storybook] Tip: use --variants='{"size":["sm","lg"]}' to enumerate variant combinations`
9754
10062
  );
9755
- const localBin = import_node_path27.default.join(
10063
+ const localBin = import_node_path29.default.join(
9756
10064
  process.cwd(),
9757
10065
  "node_modules",
9758
10066
  ".bin",
@@ -10938,12 +11246,12 @@ async function traceClass(className, options) {
10938
11246
 
10939
11247
  // packages/infrastructure/cli/src/utils/traceTargetService.ts
10940
11248
  init_cjs_shims();
10941
- var import_node_fs11 = __toESM(require("fs"), 1);
10942
- var import_node_path28 = __toESM(require("path"), 1);
11249
+ var import_node_fs13 = __toESM(require("fs"), 1);
11250
+ var import_node_path30 = __toESM(require("path"), 1);
10943
11251
  init_internal();
10944
11252
  init_src2();
10945
11253
  function toRelativePath(root, value) {
10946
- const relative = import_node_path28.default.relative(root, value);
11254
+ const relative = import_node_path30.default.relative(root, value);
10947
11255
  return relative.length > 0 ? relative : ".";
10948
11256
  }
10949
11257
  function uniqueSorted(values) {
@@ -11012,7 +11320,7 @@ function tryCompileClasses(classes) {
11012
11320
  }
11013
11321
  }
11014
11322
  function traceSingleFile(filePath, root) {
11015
- const source = import_node_fs11.default.readFileSync(filePath, "utf8");
11323
+ const source = import_node_fs13.default.readFileSync(filePath, "utf8");
11016
11324
  const classes = uniqueSorted(scanSource(source));
11017
11325
  const imports = extractImports(source);
11018
11326
  const compiled = tryCompileClasses(classes);
@@ -11043,7 +11351,7 @@ function traceDirectory(targetDir, root) {
11043
11351
  const imports = [];
11044
11352
  const importKeys = /* @__PURE__ */ new Set();
11045
11353
  const files = scanResult.files.filter((entry) => isScannableFile2(entry.file, DEFAULT_EXTENSIONS)).map((entry) => {
11046
- const source = import_node_fs11.default.readFileSync(entry.file, "utf8");
11354
+ const source = import_node_fs13.default.readFileSync(entry.file, "utf8");
11047
11355
  const fileImports = extractImports(source);
11048
11356
  for (const fileImport of fileImports) {
11049
11357
  const key = `${fileImport.kind}:${fileImport.source}`;
@@ -11074,12 +11382,12 @@ function traceDirectory(targetDir, root) {
11074
11382
  };
11075
11383
  }
11076
11384
  async function traceTarget(target, options = {}) {
11077
- const root = import_node_path28.default.resolve(options.root ?? process.cwd());
11078
- const resolvedTarget = import_node_path28.default.resolve(root, target);
11079
- if (!import_node_fs11.default.existsSync(resolvedTarget)) {
11385
+ const root = import_node_path30.default.resolve(options.root ?? process.cwd());
11386
+ const resolvedTarget = import_node_path30.default.resolve(root, target);
11387
+ if (!import_node_fs13.default.existsSync(resolvedTarget)) {
11080
11388
  throw new Error(`Trace target not found: ${resolvedTarget}`);
11081
11389
  }
11082
- const stat = import_node_fs11.default.statSync(resolvedTarget);
11390
+ const stat = import_node_fs13.default.statSync(resolvedTarget);
11083
11391
  if (stat.isDirectory()) {
11084
11392
  return traceDirectory(resolvedTarget, root);
11085
11393
  }
@@ -11242,8 +11550,8 @@ function printClassTraceOutput(result, output) {
11242
11550
 
11243
11551
  // packages/infrastructure/cli/src/generateTypes.ts
11244
11552
  init_cjs_shims();
11245
- var import_node_fs12 = __toESM(require("fs"), 1);
11246
- var import_node_path29 = __toESM(require("path"), 1);
11553
+ var import_node_fs14 = __toESM(require("fs"), 1);
11554
+ var import_node_path31 = __toESM(require("path"), 1);
11247
11555
  var import_picocolors6 = __toESM(require_picocolors(), 1);
11248
11556
  init_output();
11249
11557
  async function runGenerateTypesCli(rawArgs) {
@@ -11251,7 +11559,7 @@ async function runGenerateTypesCli(rawArgs) {
11251
11559
  const logger = createCliLogger({ output });
11252
11560
  const cwd2 = process.cwd();
11253
11561
  const outFile = rawArgs.find((a) => a.startsWith("--out="))?.slice(6) ?? "src/types/tailwind-styled.d.ts";
11254
- const outPath = import_node_path29.default.resolve(cwd2, outFile);
11562
+ const outPath = import_node_path31.default.resolve(cwd2, outFile);
11255
11563
  output.writeText("");
11256
11564
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.cyan(" \u25C6 tw generate-types")));
11257
11565
  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"));
@@ -11287,12 +11595,12 @@ async function runGenerateTypesCli(rawArgs) {
11287
11595
  }
11288
11596
  output.writeText("");
11289
11597
  output.writeText(import_picocolors6.default.bold(" [2/2]") + import_picocolors6.default.cyan(" generate .d.ts"));
11290
- const outDir = import_node_path29.default.dirname(outPath);
11291
- if (!import_node_fs12.default.existsSync(outDir)) {
11292
- import_node_fs12.default.mkdirSync(outDir, { recursive: true });
11598
+ const outDir = import_node_path31.default.dirname(outPath);
11599
+ if (!import_node_fs14.default.existsSync(outDir)) {
11600
+ import_node_fs14.default.mkdirSync(outDir, { recursive: true });
11293
11601
  }
11294
- import_node_fs12.default.writeFileSync(outPath, result.dtsContent, "utf-8");
11295
- logger.ok(import_node_path29.default.relative(cwd2, outPath));
11602
+ import_node_fs14.default.writeFileSync(outPath, result.dtsContent, "utf-8");
11603
+ logger.ok(import_node_path31.default.relative(cwd2, outPath));
11296
11604
  output.writeText("");
11297
11605
  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"));
11298
11606
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.green(" \u2713 types generated")));
@@ -11303,11 +11611,11 @@ async function runGenerateTypesCli(rawArgs) {
11303
11611
  }
11304
11612
  async function loadNativeBinding2(cwd2) {
11305
11613
  const candidates = [
11306
- import_node_path29.default.join(cwd2, "native", "tailwind-styled-native.node"),
11307
- import_node_path29.default.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
11614
+ import_node_path31.default.join(cwd2, "native", "tailwind-styled-native.node"),
11615
+ import_node_path31.default.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
11308
11616
  ];
11309
11617
  for (const candidate of candidates) {
11310
- if (import_node_fs12.default.existsSync(candidate)) {
11618
+ if (import_node_fs14.default.existsSync(candidate)) {
11311
11619
  try {
11312
11620
  return require(candidate);
11313
11621
  } catch {
@@ -11324,8 +11632,8 @@ init_errors();
11324
11632
 
11325
11633
  // packages/infrastructure/cli/src/utils/whyService.ts
11326
11634
  init_cjs_shims();
11327
- var import_node_fs13 = __toESM(require("fs"), 1);
11328
- var import_node_path30 = __toESM(require("path"), 1);
11635
+ var import_node_fs15 = __toESM(require("fs"), 1);
11636
+ var import_node_path32 = __toESM(require("path"), 1);
11329
11637
  init_internal();
11330
11638
  init_src2();
11331
11639
  function extractVariantChain(usage) {
@@ -11374,7 +11682,7 @@ async function whyClass(className, options) {
11374
11682
  for (const file of scanResult.files) {
11375
11683
  const source = (() => {
11376
11684
  try {
11377
- return import_node_fs13.default.readFileSync(file.file, "utf8");
11685
+ return import_node_fs15.default.readFileSync(file.file, "utf8");
11378
11686
  } catch {
11379
11687
  return "";
11380
11688
  }
@@ -11388,7 +11696,7 @@ async function whyClass(className, options) {
11388
11696
  className
11389
11697
  ]);
11390
11698
  usedIn.push({
11391
- file: import_node_path30.default.relative(root, file.file) || import_node_path30.default.basename(file.file),
11699
+ file: import_node_path32.default.relative(root, file.file) || import_node_path32.default.basename(file.file),
11392
11700
  line: location.line,
11393
11701
  column: location.column,
11394
11702
  usage: normalizeScannedClass(fileClass)
@@ -11695,6 +12003,12 @@ function buildMainProgram(context) {
11695
12003
  );
11696
12004
  });
11697
12005
  });
12006
+ const figmaTopLevel = program2.command("figma").description("Figma design token sync");
12007
+ ["pull", "push", "diff"].forEach((subcommand) => {
12008
+ figmaTopLevel.command(`${subcommand} [args...]`).description(`Figma ${subcommand}`).allowUnknownOption(true).action(async (args) => {
12009
+ await figmaCommand.run(contextArgs([subcommand, ...toVariadic(args)], context), context);
12010
+ });
12011
+ });
11698
12012
  program2.command("test").description("Test shortcut wrapper").option("--watch", "Watch mode").action(async (...actionArgs) => {
11699
12013
  const options = actionCommand(actionArgs).opts();
11700
12014
  const args = [];
@@ -11858,6 +12172,7 @@ if (process.argv[1] === __currentFile) {
11858
12172
  }
11859
12173
  // Annotate the CommonJS export names for ESM import in node:
11860
12174
  0 && (module.exports = {
12175
+ buildMainProgram,
11861
12176
  createCliOutput,
11862
12177
  ensureFlag,
11863
12178
  parseCliArgs,