@frontify/fondue 13.5.0 → 13.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/components/AssetInput/AssetInput.es.js.map +1 -1
  2. package/dist/components/AssetInput/AssetThumbnail.es.js.map +1 -1
  3. package/dist/components/AssetInput/MultiAssetPreview/MultiAssetPreview.es.js.map +1 -1
  4. package/dist/components/AssetInput/MultiAssetPreview/SelectedAssetsThumbnail.es.js.map +1 -1
  5. package/dist/components/AssetInput/SingleAsset/AssetSubline.es.js.map +1 -1
  6. package/dist/components/AssetInput/SingleAsset/SelectedAsset.es.js.map +1 -1
  7. package/dist/components/AssetInput/SingleAsset/SpinningCircle.es.js.map +1 -1
  8. package/dist/components/AssetInput/types.es.js.map +1 -1
  9. package/dist/index.cjs.js.map +1 -1
  10. package/dist/index.d.ts +48 -0
  11. package/dist/index.umd.js.map +1 -1
  12. package/dist/packages/charts/style.css +1 -1
  13. package/dist/packages/components/style.css +1 -1
  14. package/dist/packages/locales/de-CH.js +4 -2
  15. package/dist/packages/locales/de-CH.js.map +1 -1
  16. package/dist/packages/locales/de-DE.js +2 -0
  17. package/dist/packages/locales/de-DE.js.map +1 -1
  18. package/dist/packages/locales/en-US.d.ts +2 -0
  19. package/dist/packages/locales/en-US.js +2 -0
  20. package/dist/packages/locales/en-US.js.map +1 -1
  21. package/dist/packages/locales/es-ES.js +2 -0
  22. package/dist/packages/locales/es-ES.js.map +1 -1
  23. package/dist/packages/locales/fr-CH.js +2 -0
  24. package/dist/packages/locales/fr-CH.js.map +1 -1
  25. package/dist/packages/locales/fr-FR.js +2 -0
  26. package/dist/packages/locales/fr-FR.js.map +1 -1
  27. package/dist/packages/locales/it-CH.js +2 -0
  28. package/dist/packages/locales/it-CH.js.map +1 -1
  29. package/dist/packages/locales/it-IT.js +2 -0
  30. package/dist/packages/locales/it-IT.js.map +1 -1
  31. package/dist/packages/locales/nl-NL.js +2 -0
  32. package/dist/packages/locales/nl-NL.js.map +1 -1
  33. package/dist/packages/locales/pl-PL.js +2 -0
  34. package/dist/packages/locales/pl-PL.js.map +1 -1
  35. package/dist/packages/locales/pt-PT.js +4 -2
  36. package/dist/packages/locales/pt-PT.js.map +1 -1
  37. package/dist/packages/rte/style.css +1 -1
  38. package/dist/packages/sdk/fondue-sdk.js +1 -0
  39. package/dist/packages/sdk/sdk.d.ts +1 -0
  40. package/dist/packages/tokens/manifest.json +2747 -0
  41. package/dist/tools/codemod/index.js +16 -0
  42. package/dist/tools/internal/index.js +16 -16
  43. package/dist/tools/sdk-cli/adapters/claude-skill/skill/SKILL.md +207 -0
  44. package/dist/tools/sdk-cli/adapters/claude-skill/skill/reference.md +235 -0
  45. package/dist/tools/sdk-cli/index.js +224 -0
  46. package/package.json +17 -10
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, rmSync, mkdirSync, copyFileSync } from "node:fs";
4
+ import { dirname, resolve, join } from "node:path";
5
+ import { homedir } from "node:os";
6
+ import { fileURLToPath } from "node:url";
7
+ const log = (message) => {
8
+ process.stdout.write(`${message}
9
+ `);
10
+ };
11
+ const fail = (message, code = 1) => {
12
+ process.stderr.write(`fondue: ${message}
13
+ `);
14
+ process.exit(code);
15
+ };
16
+ const TOOL_DIR = dirname(fileURLToPath(import.meta.url));
17
+ const SKILL_SOURCE_DIR = resolve(TOOL_DIR, "adapters", "claude-skill", "skill");
18
+ const SKILL_NAME = "fondue";
19
+ const CONSUMER_PACKAGE = "@frontify/fondue";
20
+ const FONDUE_VERSION = "13.6.0";
21
+ const scopeOf = (options) => options.user ? "user" : "project";
22
+ const projectRoot = () => {
23
+ let dir = process.cwd();
24
+ while (true) {
25
+ if (existsSync(join(dir, "package.json")) || existsSync(join(dir, ".git"))) {
26
+ return dir;
27
+ }
28
+ const parent = dirname(dir);
29
+ if (parent === dir) {
30
+ return process.cwd();
31
+ }
32
+ dir = parent;
33
+ }
34
+ };
35
+ const skillsRoot = (scope) => scope === "user" ? join(homedir(), ".claude", "skills") : join(projectRoot(), ".claude", "skills");
36
+ const targetDirFor = (scope) => join(skillsRoot(scope), SKILL_NAME);
37
+ const stampPathFor = (scope) => join(skillsRoot(scope), `.${SKILL_NAME}-installed.json`);
38
+ const readStamp = (stampPath) => {
39
+ if (!existsSync(stampPath)) {
40
+ return { status: "missing" };
41
+ }
42
+ try {
43
+ const stamp = JSON.parse(readFileSync(stampPath, "utf8"));
44
+ return { status: "ok", stamp };
45
+ } catch (error) {
46
+ return { status: "corrupted", error: error instanceof Error ? error.message : String(error) };
47
+ }
48
+ };
49
+ const writeStamp = (stampPath, scope) => {
50
+ const stamp = {
51
+ package: CONSUMER_PACKAGE,
52
+ version: FONDUE_VERSION,
53
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
54
+ scope
55
+ };
56
+ writeFileSync(stampPath, `${JSON.stringify(stamp, null, 2)}
57
+ `);
58
+ };
59
+ const install = (options) => {
60
+ const scope = scopeOf(options);
61
+ const target = targetDirFor(scope);
62
+ const stampPath = stampPathFor(scope);
63
+ if (!existsSync(SKILL_SOURCE_DIR)) {
64
+ fail(`Bundled skill directory missing at ${SKILL_SOURCE_DIR}. Reinstall ${CONSUMER_PACKAGE}.`);
65
+ }
66
+ const files = readdirSync(SKILL_SOURCE_DIR).filter((name) => statSync(join(SKILL_SOURCE_DIR, name)).isFile());
67
+ if (!files.includes("SKILL.md")) {
68
+ fail(`Bundled skill is missing SKILL.md. Reinstall ${CONSUMER_PACKAGE}.`);
69
+ }
70
+ let previousVersion = null;
71
+ if (existsSync(target)) {
72
+ const read = readStamp(stampPath);
73
+ if (read.status === "ok") {
74
+ previousVersion = read.stamp.version;
75
+ } else if (read.status === "corrupted" && !options.force) {
76
+ fail(
77
+ `Stamp file at ${stampPath} is unreadable (${read.error}). Inspect it, or pass --force to overwrite both the stamp and the skill.`
78
+ );
79
+ } else if (read.status === "missing" && !options.force) {
80
+ fail(
81
+ `${target} exists and was not installed by this CLI. Remove it manually, or pass --force to overwrite.`
82
+ );
83
+ }
84
+ rmSync(target, { recursive: true, force: true });
85
+ }
86
+ mkdirSync(target, { recursive: true });
87
+ for (const name of files) {
88
+ copyFileSync(join(SKILL_SOURCE_DIR, name), join(target, name));
89
+ }
90
+ writeStamp(stampPath, scope);
91
+ if (previousVersion === null) {
92
+ log(`Installed Fondue Claude Code skill (${CONSUMER_PACKAGE}@${FONDUE_VERSION}) → ${target}`);
93
+ } else if (previousVersion === FONDUE_VERSION) {
94
+ log(`Refreshed Fondue Claude Code skill at ${CONSUMER_PACKAGE}@${FONDUE_VERSION} → ${target}`);
95
+ } else {
96
+ log(
97
+ `Updated Fondue Claude Code skill (${CONSUMER_PACKAGE}@${previousVersion} → @${FONDUE_VERSION}) → ${target}`
98
+ );
99
+ }
100
+ log(scope === "project" ? "Scope: project (this directory only)." : "Scope: user (every project).");
101
+ if (previousVersion === null) {
102
+ log("");
103
+ log("Next steps:");
104
+ log(` • Open Claude Code in a project that has \`${CONSUMER_PACKAGE}\` installed.`);
105
+ log(' • Ask "what Fondue component should I use for X?" — Claude picks the skill up automatically,');
106
+ log(` or invoke it explicitly with /${SKILL_NAME}.`);
107
+ if (scope === "project") {
108
+ log(` • Commit \`.claude/skills/${SKILL_NAME}/\` if you want it shared with your team.`);
109
+ }
110
+ }
111
+ };
112
+ const status = (options) => {
113
+ const scope = scopeOf(options);
114
+ const target = targetDirFor(scope);
115
+ const stampPath = stampPathFor(scope);
116
+ const targetExists = existsSync(target);
117
+ const read = readStamp(stampPath);
118
+ if (!targetExists && read.status === "missing") {
119
+ log(`Not installed at ${target}.`);
120
+ return;
121
+ }
122
+ if (read.status === "ok") {
123
+ if (!targetExists) {
124
+ log(`Stamp at ${stampPath} but skill directory is missing at ${target}.`);
125
+ log("Run `fondue adapter install claude-skill` to repair.");
126
+ return;
127
+ }
128
+ log(`Installed at ${target}`);
129
+ log(` package: ${read.stamp.package}@${read.stamp.version}`);
130
+ log(` scope: ${read.stamp.scope}`);
131
+ log(` installedAt: ${read.stamp.installedAt}`);
132
+ return;
133
+ }
134
+ if (read.status === "corrupted") {
135
+ log(`Stamp at ${stampPath} is unreadable (${read.error}).`);
136
+ if (targetExists) {
137
+ log(`Skill directory present at ${target}. Re-run install to repair, or pass --force.`);
138
+ }
139
+ return;
140
+ }
141
+ log(`Directory exists at ${target} but was not installed by this CLI.`);
142
+ };
143
+ const uninstall = (options) => {
144
+ const scope = scopeOf(options);
145
+ const target = targetDirFor(scope);
146
+ const stampPath = stampPathFor(scope);
147
+ const targetExists = existsSync(target);
148
+ const stampExists = existsSync(stampPath);
149
+ if (!targetExists && !stampExists) {
150
+ log(`Nothing to uninstall — no skill at ${target}.`);
151
+ return;
152
+ }
153
+ if (targetExists) {
154
+ const read = readStamp(stampPath);
155
+ if (read.status === "missing" && !options.force) {
156
+ fail(`${target} exists but was not installed by this CLI. Remove it manually, or pass --force.`);
157
+ }
158
+ if (read.status === "corrupted" && !options.force) {
159
+ fail(
160
+ `Stamp file at ${stampPath} is unreadable (${read.error}). Inspect it, or pass --force to remove the skill and the stamp.`
161
+ );
162
+ }
163
+ rmSync(target, { recursive: true, force: true });
164
+ }
165
+ if (stampExists) {
166
+ rmSync(stampPath, { force: true });
167
+ }
168
+ log(`Removed ${target}.`);
169
+ };
170
+ const claudeSkill = {
171
+ name: "claude-skill",
172
+ description: "Claude Code skill — teaches Claude to query the Fondue SDK directly",
173
+ install,
174
+ uninstall,
175
+ status
176
+ };
177
+ const ADAPTERS = [claudeSkill];
178
+ const adapterNames = () => ADAPTERS.map((i) => i.name).join(", ");
179
+ const adapterCatalog = () => {
180
+ const width = Math.max(...ADAPTERS.map((i) => i.name.length));
181
+ return ADAPTERS.map((i) => ` ${i.name.padEnd(width)} ${i.description}`).join("\n");
182
+ };
183
+ const requireAdapter = (name, verb) => {
184
+ if (name === void 0) {
185
+ return fail(
186
+ `Specify which adapter to ${verb}. Available:
187
+ ${adapterCatalog()}
188
+
189
+ Example: fondue adapter ${verb} ${ADAPTERS[0]?.name ?? "<name>"}`
190
+ );
191
+ }
192
+ const adapter2 = ADAPTERS.find((i) => i.name === name);
193
+ if (adapter2 !== void 0) {
194
+ return adapter2;
195
+ }
196
+ return fail(`Unknown adapter "${name}". Available: ${adapterNames()}.`);
197
+ };
198
+ const program = new Command().name("fondue").description("CLI for Frontify Fondue.").version("13.6.0");
199
+ const adapter = program.command("adapter").description("Install and manage Fondue SDK adapters (Claude Code skill, MCP, REST, …).");
200
+ adapter.command("install [name]").aliases(["add", "update"]).description(
201
+ "Install an adapter, or refresh an existing install in place. Run `adapter list` to see what `<name>` accepts."
202
+ ).option("--user", "Install for the current user instead of the current project").option("--force", "Overwrite a directory at the target path that was not installed by this CLI").action((name, options) => {
203
+ requireAdapter(name, "install").install(options);
204
+ });
205
+ adapter.command("uninstall [name]").alias("remove").description("Uninstall an adapter previously installed by this CLI.").option("--user", "Target the user-scope install").option("--force", "Force removal even if not installed by this CLI").action((name, options) => {
206
+ requireAdapter(name, "uninstall").uninstall(options);
207
+ });
208
+ adapter.command("status [name]").description("Show installation status for one adapter, or every adapter when no name is given.").option("--user", "Target the user-scope install").action((name, options) => {
209
+ if (name !== void 0) {
210
+ requireAdapter(name, "status").status(options);
211
+ return;
212
+ }
213
+ for (const [index, registered] of ADAPTERS.entries()) {
214
+ if (index > 0) {
215
+ log("");
216
+ }
217
+ log(`[${registered.name}]`);
218
+ registered.status(options);
219
+ }
220
+ });
221
+ adapter.command("list").alias("ls").description("List every registered adapter and what it does.").action(() => {
222
+ log(adapterCatalog());
223
+ });
224
+ program.parse();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@frontify/fondue",
3
3
  "type": "module",
4
- "version": "13.5.0",
4
+ "version": "13.6.0",
5
5
  "description": "Design system of Frontify",
6
6
  "author": "Frontify Developers <developers@frontify.com>",
7
7
  "homepage": "https://github.com/Frontify/fondue",
@@ -54,6 +54,10 @@
54
54
  "import": "./dist/packages/rte/fondue-rte.js"
55
55
  },
56
56
  "./rte/styles": "./dist/packages/rte/style.css",
57
+ "./sdk": {
58
+ "types": "./dist/packages/sdk/fondue-sdk.d.ts",
59
+ "import": "./dist/packages/sdk/fondue-sdk.js"
60
+ },
57
61
  "./charts/styles": "./dist/packages/charts/style.css",
58
62
  ".": {
59
63
  "types": "./dist/index.d.ts",
@@ -75,7 +79,8 @@
75
79
  "types": "dist/index.d.ts",
76
80
  "bin": {
77
81
  "codemod": "./dist/tools/codemod/index.js",
78
- "internal": "./dist/tools/internal/index.js"
82
+ "internal": "./dist/tools/internal/index.js",
83
+ "fondue": "./dist/tools/sdk-cli/index.js"
79
84
  },
80
85
  "files": [
81
86
  "dist",
@@ -133,11 +138,12 @@
133
138
  "react-is": "^18.3.1",
134
139
  "react-popper": "^2.3.0",
135
140
  "react-textarea-autosize": "^8.5.9",
136
- "@frontify/fondue-charts": "^7.0.1",
137
- "@frontify/fondue-icons": "^0.26.1",
138
- "@frontify/fondue-tokens": "^5.0.1",
139
- "@frontify/fondue-rte": "^0.1.4",
140
- "@frontify/fondue-components": "^30.4.0"
141
+ "@frontify/fondue-charts": "^7.1.0",
142
+ "@frontify/fondue-icons": "^0.26.2",
143
+ "@frontify/fondue-components": "^30.6.0",
144
+ "@frontify/fondue-sdk": "^0.1.1",
145
+ "@frontify/fondue-tokens": "^5.0.2",
146
+ "@frontify/fondue-rte": "^0.1.4"
141
147
  },
142
148
  "devDependencies": {
143
149
  "@babel/core": "^7.29.0",
@@ -179,10 +185,10 @@
179
185
  "vite-plugin-dts": "^4.5.4",
180
186
  "vite-plugin-static-copy": "^3.1.5",
181
187
  "vite-tsconfig-paths": "^5.1.4",
182
- "@frontify/fondue-icons": "^0.26.1"
188
+ "@frontify/fondue-icons": "^0.26.2"
183
189
  },
184
190
  "scripts": {
185
- "build": "pnpm clean && pnpm build:library && pnpm build:styles-with-tw && pnpm build:package:components && pnpm build:package:locales && pnpm build:package:icons && pnpm build:package:charts && pnpm build:package:tokens && pnpm build:package:rte && pnpm build:tools",
191
+ "build": "pnpm clean && pnpm build:library && pnpm build:styles-with-tw && pnpm build:package:components && pnpm build:package:locales && pnpm build:package:icons && pnpm build:package:charts && pnpm build:package:tokens && pnpm build:package:rte && pnpm build:package:sdk && pnpm build:tools",
186
192
  "build:library": "vite build",
187
193
  "build:styles-with-tw": "postcss ./src/components/**/*.css --config src/components/postcss.config.cjs -o dist/styles-without-tailwind.css",
188
194
  "build:storybook": "storybook build",
@@ -192,7 +198,8 @@
192
198
  "build:package:charts": "vite build -c charts.vite.config.ts",
193
199
  "build:package:tokens": "vite build -c tokens.vite.config.ts",
194
200
  "build:package:rte": "vite build -c rte.vite.config.ts",
195
- "build:tools": "tsx scripts/detectDeprecatedExports/detectDeprecatedExports.ts tools/constants/fondueExports.json && vite build -c codemod.vite.config.ts && vite build -c internal-tools.vite.config.ts",
201
+ "build:package:sdk": "vite build -c sdk.vite.config.ts",
202
+ "build:tools": "tsx scripts/detectDeprecatedExports/detectDeprecatedExports.ts tools/constants/fondueExports.json && vite build -c codemod.vite.config.ts && vite build -c internal-tools.vite.config.ts && vite build -c sdk-cli.vite.config.ts",
196
203
  "dev": "cross-env NODE_ENV=development pnpm dev:library",
197
204
  "dev:library": "vite build --emptyOutDir false --watch",
198
205
  "clean": "rimraf dist",