tauri-plugin-system-symbols 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 insd47
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # tauri-plugin-system-symbols
2
+
3
+ Resolve platform system symbols into SVG path data from a Tauri app.
4
+
5
+ This plugin is designed for apps that want native-looking symbols without
6
+ bundling icon fonts or SVG assets.
7
+
8
+ ## Packages
9
+
10
+ - Rust crate: [`tauri-plugin-system-symbols`](https://github.com/insd47/tauri-plugin-system-symbols)
11
+ - JavaScript package: [`tauri-plugin-system-symbols`](https://github.com/insd47/tauri-plugin-system-symbols)
12
+ - React package: [`tauri-plugin-system-symbols-react`](https://github.com/insd47/tauri-plugin-system-symbols-react)
13
+
14
+ ## Status
15
+
16
+ - Windows: `Segoe Fluent Icons` is resolved first, with `Segoe MDL2 Assets` as the fallback.
17
+ - macOS: `SF Symbols` command/API boundaries are in place, but vector extraction is still pending.
18
+ - Other platforms: unsupported.
19
+
20
+ Calling a platform-specific API on the wrong platform rejects with a Rust backend error.
21
+
22
+ ## Install
23
+
24
+ Install the Rust plugin in your Tauri app:
25
+
26
+ ```toml
27
+ # src-tauri/Cargo.toml
28
+ [dependencies]
29
+ tauri-plugin-system-symbols = "0.1"
30
+ ```
31
+
32
+ Install the JavaScript package:
33
+
34
+ ```sh
35
+ pnpm add tauri-plugin-system-symbols
36
+ ```
37
+
38
+ Register the plugin:
39
+
40
+ ```rust
41
+ tauri::Builder::default()
42
+ .plugin(tauri_plugin_system_symbols::init());
43
+ ```
44
+
45
+ Add the default permission to your capability file:
46
+
47
+ ```json
48
+ {
49
+ "permissions": ["system-symbols:default"]
50
+ }
51
+ ```
52
+
53
+ ## JavaScript API
54
+
55
+ ```ts
56
+ import {
57
+ getCachedFluentIcon,
58
+ getCachedSfSymbol,
59
+ getFluentIcon,
60
+ getSfSymbol,
61
+ preloadFluentIcons,
62
+ preloadSfSymbols,
63
+ } from 'tauri-plugin-system-symbols'
64
+
65
+ await preloadFluentIcons('\uE8BB', '\uE921')
66
+ await preloadSfSymbols('square.and.arrow.up')
67
+
68
+ const close = getCachedFluentIcon('\uE8BB') ?? await getFluentIcon('\uE8BB')
69
+ const share = getCachedSfSymbol('square.and.arrow.up') ?? await getSfSymbol('square.and.arrow.up')
70
+ ```
71
+
72
+ Tauri IPC is asynchronous, so first-time symbol resolution returns a `Promise<Symbol>`.
73
+ Use `preloadFluentIcons(...icons)` and `preloadSfSymbols(...symbols)` to warm the cache before rendering.
74
+
75
+ ## Types
76
+
77
+ ```ts
78
+ interface Symbol {
79
+ viewBox: string
80
+ paths: Path[]
81
+ }
82
+
83
+ interface Path {
84
+ d: string
85
+ fillRule?: 'nonzero' | 'evenodd'
86
+ opacity?: number
87
+ }
88
+ ```
89
+
90
+ ## React
91
+
92
+ React components are provided by
93
+ [`tauri-plugin-system-symbols-react`](https://github.com/insd47/tauri-plugin-system-symbols-react).
94
+
95
+ ```sh
96
+ pnpm add tauri-plugin-system-symbols-react @tauri-apps/plugin-os
97
+ ```
98
+
99
+ ## Development
100
+
101
+ ```sh
102
+ pnpm install
103
+ pnpm run check
104
+ pnpm run build
105
+ cargo check
106
+ cargo test
107
+ ```
108
+
109
+ ## License
110
+
111
+ MIT
@@ -0,0 +1,58 @@
1
+ import type { FluentIconOptions, SfSymbolOptions, SvgSymbol } from './types';
2
+ /**
3
+ * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.
4
+ *
5
+ * `Segoe Fluent Icons` is preferred by the Rust backend, with
6
+ * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows
7
+ * platform rejects with the backend platform error.
8
+ *
9
+ * @param icon Glyph text or codepoint, for example `"\uE8BB"` or `"U+E8BB"`.
10
+ * @param options Reserved for future Fluent icon rendering options.
11
+ * @returns SVG path data and viewBox metadata for the icon.
12
+ */
13
+ export declare function getFluentIcon(icon: string, options?: FluentIconOptions): Promise<SvgSymbol>;
14
+ /**
15
+ * Returns a previously resolved Windows Fluent icon without starting IPC.
16
+ *
17
+ * @param icon Glyph text or codepoint used to resolve the icon.
18
+ * @param options Options used when the icon was resolved.
19
+ * @returns Cached SVG data, or `undefined` when the icon has not been loaded.
20
+ */
21
+ export declare function getCachedFluentIcon(icon: string, options?: FluentIconOptions): SvgSymbol | undefined;
22
+ /**
23
+ * Preloads Windows Fluent icons in one backend request.
24
+ *
25
+ * @param icons Glyph texts or codepoints to preload.
26
+ */
27
+ export declare function preloadFluentIcons(...icons: string[]): Promise<void>;
28
+ /**
29
+ * Resolves a macOS SF Symbol name to SVG path data.
30
+ *
31
+ * Calling this on a non-macOS platform rejects with the backend platform error.
32
+ *
33
+ * @param symbol SF Symbols name, for example `"square.and.arrow.up"`.
34
+ * @param options Reserved for future SF Symbols rendering options.
35
+ * @returns SVG path data and viewBox metadata for the symbol.
36
+ */
37
+ export declare function getSfSymbol(symbol: string, options?: SfSymbolOptions): Promise<SvgSymbol>;
38
+ /**
39
+ * Returns a previously resolved SF Symbol without starting IPC.
40
+ *
41
+ * @param symbol SF Symbols name used to resolve the symbol.
42
+ * @param options Options used when the symbol was resolved.
43
+ * @returns Cached SVG data, or `undefined` when the symbol has not been loaded.
44
+ */
45
+ export declare function getCachedSfSymbol(symbol: string, options?: SfSymbolOptions): SvgSymbol | undefined;
46
+ /**
47
+ * Preloads macOS SF Symbols in one backend request.
48
+ *
49
+ * @param symbols SF Symbols names to preload.
50
+ */
51
+ export declare function preloadSfSymbols(...symbols: string[]): Promise<void>;
52
+ /**
53
+ * Clears the in-memory JavaScript symbol cache.
54
+ *
55
+ * This only affects frontend-side caching. The Rust backend keeps its own
56
+ * process-local cache.
57
+ */
58
+ export declare function clearSymbolCache(): void;
package/dist-js/api.js ADDED
@@ -0,0 +1,102 @@
1
+ import { clear, get, load, save } from './cache.js';
2
+ import { fluent as fluent$1, sf as sf$1 } from './commands.js';
3
+ import { fluent, sf } from './key.js';
4
+ import { assert, unique } from './text.js';
5
+
6
+ /**
7
+ * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.
8
+ *
9
+ * `Segoe Fluent Icons` is preferred by the Rust backend, with
10
+ * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows
11
+ * platform rejects with the backend platform error.
12
+ *
13
+ * @param icon Glyph text or codepoint, for example `"\uE8BB"` or `"U+E8BB"`.
14
+ * @param options Reserved for future Fluent icon rendering options.
15
+ * @returns SVG path data and viewBox metadata for the icon.
16
+ */
17
+ function getFluentIcon(icon, options) {
18
+ assert(icon, 'icon');
19
+ return load(fluent(icon, options), async () => {
20
+ const [symbol] = await fluent$1([icon], options);
21
+ return symbol;
22
+ });
23
+ }
24
+ /**
25
+ * Returns a previously resolved Windows Fluent icon without starting IPC.
26
+ *
27
+ * @param icon Glyph text or codepoint used to resolve the icon.
28
+ * @param options Options used when the icon was resolved.
29
+ * @returns Cached SVG data, or `undefined` when the icon has not been loaded.
30
+ */
31
+ function getCachedFluentIcon(icon, options) {
32
+ assert(icon, 'icon');
33
+ return get(fluent(icon, options));
34
+ }
35
+ /**
36
+ * Preloads Windows Fluent icons in one backend request.
37
+ *
38
+ * @param icons Glyph texts or codepoints to preload.
39
+ */
40
+ async function preloadFluentIcons(...icons) {
41
+ const unique$1 = unique(icons);
42
+ unique$1.forEach((icon) => assert(icon, 'icon'));
43
+ const missing = unique$1.filter((icon) => !get(fluent(icon)));
44
+ if (missing.length === 0) {
45
+ return;
46
+ }
47
+ const symbols = await fluent$1(missing);
48
+ save(symbols, missing.map((icon) => fluent(icon)));
49
+ }
50
+ /**
51
+ * Resolves a macOS SF Symbol name to SVG path data.
52
+ *
53
+ * Calling this on a non-macOS platform rejects with the backend platform error.
54
+ *
55
+ * @param symbol SF Symbols name, for example `"square.and.arrow.up"`.
56
+ * @param options Reserved for future SF Symbols rendering options.
57
+ * @returns SVG path data and viewBox metadata for the symbol.
58
+ */
59
+ function getSfSymbol(symbol, options) {
60
+ assert(symbol, 'symbol');
61
+ return load(sf(symbol, options), async () => {
62
+ const [icon] = await sf$1([symbol], options);
63
+ return icon;
64
+ });
65
+ }
66
+ /**
67
+ * Returns a previously resolved SF Symbol without starting IPC.
68
+ *
69
+ * @param symbol SF Symbols name used to resolve the symbol.
70
+ * @param options Options used when the symbol was resolved.
71
+ * @returns Cached SVG data, or `undefined` when the symbol has not been loaded.
72
+ */
73
+ function getCachedSfSymbol(symbol, options) {
74
+ assert(symbol, 'symbol');
75
+ return get(sf(symbol, options));
76
+ }
77
+ /**
78
+ * Preloads macOS SF Symbols in one backend request.
79
+ *
80
+ * @param symbols SF Symbols names to preload.
81
+ */
82
+ async function preloadSfSymbols(...symbols) {
83
+ const unique$1 = unique(symbols);
84
+ unique$1.forEach((symbol) => assert(symbol, 'symbol'));
85
+ const missing = unique$1.filter((symbol) => !get(sf(symbol)));
86
+ if (missing.length === 0) {
87
+ return;
88
+ }
89
+ const icons = await sf$1(missing);
90
+ save(icons, missing.map((symbol) => sf(symbol)));
91
+ }
92
+ /**
93
+ * Clears the in-memory JavaScript symbol cache.
94
+ *
95
+ * This only affects frontend-side caching. The Rust backend keeps its own
96
+ * process-local cache.
97
+ */
98
+ function clearSymbolCache() {
99
+ clear();
100
+ }
101
+
102
+ export { clearSymbolCache, getCachedFluentIcon, getCachedSfSymbol, getFluentIcon, getSfSymbol, preloadFluentIcons, preloadSfSymbols };
@@ -0,0 +1,5 @@
1
+ import type { Symbol } from './types';
2
+ export declare function get(key: string): Symbol | undefined;
3
+ export declare function load(key: string, create: () => Promise<Symbol>): Promise<Symbol>;
4
+ export declare function save(symbols: Symbol[], keys: string[]): void;
5
+ export declare function clear(): void;
@@ -0,0 +1,36 @@
1
+ const resolved = new Map();
2
+ const pending = new Map();
3
+ function get(key) {
4
+ return resolved.get(key);
5
+ }
6
+ function load(key, create) {
7
+ const cached = resolved.get(key);
8
+ if (cached) {
9
+ return Promise.resolve(cached);
10
+ }
11
+ const inflight = pending.get(key);
12
+ if (inflight) {
13
+ return inflight;
14
+ }
15
+ const request = create().then((symbol) => {
16
+ pending.delete(key);
17
+ resolved.set(key, symbol);
18
+ return symbol;
19
+ }, (error) => {
20
+ pending.delete(key);
21
+ throw error;
22
+ });
23
+ pending.set(key, request);
24
+ return request;
25
+ }
26
+ function save(symbols, keys) {
27
+ symbols.forEach((symbol, index) => {
28
+ resolved.set(keys[index], symbol);
29
+ });
30
+ }
31
+ function clear() {
32
+ resolved.clear();
33
+ pending.clear();
34
+ }
35
+
36
+ export { clear, get, load, save };
@@ -0,0 +1,3 @@
1
+ import type { Symbol } from './types';
2
+ export declare function fluent(icons: string[]): Promise<Symbol[]>;
3
+ export declare function sf(symbols: string[]): Promise<Symbol[]>;
@@ -0,0 +1,15 @@
1
+ import { invoke } from '@tauri-apps/api/core';
2
+
3
+ const COMMAND_PREFIX = 'plugin:system-symbols|';
4
+ function fluent(icons) {
5
+ return invoke(`${COMMAND_PREFIX}get_fluent_icons`, {
6
+ icons
7
+ });
8
+ }
9
+ function sf(symbols) {
10
+ return invoke(`${COMMAND_PREFIX}get_sf_symbols`, {
11
+ symbols
12
+ });
13
+ }
14
+
15
+ export { fluent, sf };
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ var core = require('@tauri-apps/api/core');
4
+
5
+ const resolved = new Map();
6
+ const pending = new Map();
7
+ function get(key) {
8
+ return resolved.get(key);
9
+ }
10
+ function load(key, create) {
11
+ const cached = resolved.get(key);
12
+ if (cached) {
13
+ return Promise.resolve(cached);
14
+ }
15
+ const inflight = pending.get(key);
16
+ if (inflight) {
17
+ return inflight;
18
+ }
19
+ const request = create().then((symbol) => {
20
+ pending.delete(key);
21
+ resolved.set(key, symbol);
22
+ return symbol;
23
+ }, (error) => {
24
+ pending.delete(key);
25
+ throw error;
26
+ });
27
+ pending.set(key, request);
28
+ return request;
29
+ }
30
+ function save(symbols, keys) {
31
+ symbols.forEach((symbol, index) => {
32
+ resolved.set(keys[index], symbol);
33
+ });
34
+ }
35
+ function clear() {
36
+ resolved.clear();
37
+ pending.clear();
38
+ }
39
+
40
+ const COMMAND_PREFIX = 'plugin:system-symbols|';
41
+ function fluent$1(icons) {
42
+ return core.invoke(`${COMMAND_PREFIX}get_fluent_icons`, {
43
+ icons
44
+ });
45
+ }
46
+ function sf$1(symbols) {
47
+ return core.invoke(`${COMMAND_PREFIX}get_sf_symbols`, {
48
+ symbols
49
+ });
50
+ }
51
+
52
+ function fluent(icon) {
53
+ return `fluent:${icon}`;
54
+ }
55
+ function sf(symbol) {
56
+ return `sf:${symbol}`;
57
+ }
58
+
59
+ function assert(value, name) {
60
+ if (value.trim().length === 0) {
61
+ throw new Error(`${name} must not be empty`);
62
+ }
63
+ }
64
+ function unique(values) {
65
+ return [...new Set(values)];
66
+ }
67
+
68
+ /**
69
+ * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.
70
+ *
71
+ * `Segoe Fluent Icons` is preferred by the Rust backend, with
72
+ * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows
73
+ * platform rejects with the backend platform error.
74
+ *
75
+ * @param icon Glyph text or codepoint, for example `"\uE8BB"` or `"U+E8BB"`.
76
+ * @returns SVG path data and viewBox metadata for the icon.
77
+ */
78
+ function getFluentIcon(icon) {
79
+ assert(icon, 'icon');
80
+ return load(fluent(icon), async () => {
81
+ const [symbol] = await fluent$1([icon]);
82
+ return symbol;
83
+ });
84
+ }
85
+ /**
86
+ * Returns a previously resolved Windows Fluent icon without starting IPC.
87
+ *
88
+ * @param icon Glyph text or codepoint used to resolve the icon.
89
+ * @returns Cached SVG data, or `undefined` when the icon has not been loaded.
90
+ */
91
+ function getCachedFluentIcon(icon) {
92
+ assert(icon, 'icon');
93
+ return get(fluent(icon));
94
+ }
95
+ /**
96
+ * Preloads Windows Fluent icons in one backend request.
97
+ *
98
+ * @param icons Glyph texts or codepoints to preload.
99
+ */
100
+ async function preloadFluentIcons(...icons) {
101
+ const unique$1 = unique(icons);
102
+ unique$1.forEach((icon) => assert(icon, 'icon'));
103
+ const missing = unique$1.filter((icon) => !get(fluent(icon)));
104
+ if (missing.length === 0) {
105
+ return;
106
+ }
107
+ const symbols = await fluent$1(missing);
108
+ save(symbols, missing.map((icon) => fluent(icon)));
109
+ }
110
+ /**
111
+ * Resolves a macOS SF Symbol name to SVG path data.
112
+ *
113
+ * Calling this on a non-macOS platform rejects with the backend platform error.
114
+ *
115
+ * @param symbol SF Symbols name, for example `"square.and.arrow.up"`.
116
+ * @returns SVG path data and viewBox metadata for the symbol.
117
+ */
118
+ function getSfSymbol(symbol) {
119
+ assert(symbol, 'symbol');
120
+ return load(sf(symbol), async () => {
121
+ const [icon] = await sf$1([symbol]);
122
+ return icon;
123
+ });
124
+ }
125
+ /**
126
+ * Returns a previously resolved SF Symbol without starting IPC.
127
+ *
128
+ * @param symbol SF Symbols name used to resolve the symbol.
129
+ * @returns Cached SVG data, or `undefined` when the symbol has not been loaded.
130
+ */
131
+ function getCachedSfSymbol(symbol) {
132
+ assert(symbol, 'symbol');
133
+ return get(sf(symbol));
134
+ }
135
+ /**
136
+ * Preloads macOS SF Symbols in one backend request.
137
+ *
138
+ * @param symbols SF Symbols names to preload.
139
+ */
140
+ async function preloadSfSymbols(...symbols) {
141
+ const unique$1 = unique(symbols);
142
+ unique$1.forEach((symbol) => assert(symbol, 'symbol'));
143
+ const missing = unique$1.filter((symbol) => !get(sf(symbol)));
144
+ if (missing.length === 0) {
145
+ return;
146
+ }
147
+ const icons = await sf$1(missing);
148
+ save(icons, missing.map((symbol) => sf(symbol)));
149
+ }
150
+ /**
151
+ * Clears the in-memory JavaScript symbol cache.
152
+ *
153
+ * This only affects frontend-side caching. The Rust backend keeps its own
154
+ * process-local cache.
155
+ */
156
+ function clearSymbolCache() {
157
+ clear();
158
+ }
159
+
160
+ exports.clearSymbolCache = clearSymbolCache;
161
+ exports.getCachedFluentIcon = getCachedFluentIcon;
162
+ exports.getCachedSfSymbol = getCachedSfSymbol;
163
+ exports.getFluentIcon = getFluentIcon;
164
+ exports.getSfSymbol = getSfSymbol;
165
+ exports.preloadFluentIcons = preloadFluentIcons;
166
+ exports.preloadSfSymbols = preloadSfSymbols;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../guest-js/index.ts"],"sourcesContent":["import { invoke } from '@tauri-apps/api/core'\n\nconst COMMAND_PREFIX = 'plugin:system-symbols|'\n\nexport type SymbolSet = 'fluent' | 'sfSymbols'\nexport type FillRule = 'nonzero' | 'evenodd'\n\nexport interface SvgPath {\n d: string\n fillRule?: FillRule\n opacity?: number\n}\n\nexport interface SvgSymbol {\n set: SymbolSet\n symbol: string\n viewBox: string\n paths: SvgPath[]\n}\n\nexport interface FluentIconOptions {}\n\nexport interface SfSymbolOptions {}\n\nconst cache = new Map<string, Promise<SvgSymbol>>()\n\n/**\n * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.\n *\n * `Segoe Fluent Icons` is preferred by the Rust backend, with\n * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows\n * platform rejects with the backend platform error.\n *\n * @param icon Glyph text or codepoint, for example `\"\\uE8BB\"` or `\"U+E8BB\"`.\n * @param options Reserved for future Fluent icon rendering options.\n * @returns SVG path data and viewBox metadata for the icon.\n */\nexport function getFluentIcon(\n icon: string,\n options?: FluentIconOptions\n): Promise<SvgSymbol> {\n assertText(icon, 'icon')\n return load('fluent', icon, options, 'get_fluent_icon', {\n icon,\n options: options ?? null\n })\n}\n\n/**\n * Resolves a macOS SF Symbol name to SVG path data.\n *\n * Calling this on a non-macOS platform rejects with the backend platform error.\n *\n * @param symbol SF Symbols name, for example `\"square.and.arrow.up\"`.\n * @param options Reserved for future SF Symbols rendering options.\n * @returns SVG path data and viewBox metadata for the symbol.\n */\nexport function getSfSymbol(\n symbol: string,\n options?: SfSymbolOptions\n): Promise<SvgSymbol> {\n assertText(symbol, 'symbol')\n return load('sfSymbols', symbol, options, 'get_sf_symbol', {\n symbol,\n options: options ?? null\n })\n}\n\n/**\n * Clears the in-memory JavaScript symbol cache.\n *\n * This only affects frontend-side Promise caching. The Rust backend keeps its\n * own process-local cache.\n */\nexport function clearSymbolCache(): void {\n cache.clear()\n}\n\nfunction load(\n set: SymbolSet,\n symbol: string,\n options: FluentIconOptions | SfSymbolOptions | undefined,\n command: string,\n args: Record<string, unknown>\n): Promise<SvgSymbol> {\n const key = cacheKey(set, symbol, options)\n const cached = cache.get(key)\n if (cached) {\n return cached\n }\n\n const pending = invoke<SvgSymbol>(`${COMMAND_PREFIX}${command}`, args).catch(\n (error) => {\n cache.delete(key)\n throw error\n }\n )\n\n cache.set(key, pending)\n return pending\n}\n\nfunction assertText(value: string, name: string): void {\n if (value.trim().length === 0) {\n throw new Error(`${name} must not be empty`)\n }\n}\n\nfunction cacheKey(\n set: SymbolSet,\n symbol: string,\n options: FluentIconOptions | SfSymbolOptions | undefined\n): string {\n return `${set}:${symbol}:${JSON.stringify(options ?? {})}`\n}\n"],"names":["invoke"],"mappings":";;;;AAEA,MAAM,cAAc,GAAG,wBAAwB;AAsB/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B;AAEnD;;;;;;;;;;AAUG;AACG,SAAU,aAAa,CAC3B,IAAY,EACZ,OAA2B,EAAA;AAE3B,IAAA,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;IACxB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE;QACtD,IAAI;QACJ,OAAO,EAAE,OAAO,IAAI;AACrB,KAAA,CAAC;AACJ;AAEA;;;;;;;;AAQG;AACG,SAAU,WAAW,CACzB,MAAc,EACd,OAAyB,EAAA;AAEzB,IAAA,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE;QACzD,MAAM;QACN,OAAO,EAAE,OAAO,IAAI;AACrB,KAAA,CAAC;AACJ;AAEA;;;;;AAKG;SACa,gBAAgB,GAAA;IAC9B,KAAK,CAAC,KAAK,EAAE;AACf;AAEA,SAAS,IAAI,CACX,GAAc,EACd,MAAc,EACd,OAAwD,EACxD,OAAe,EACf,IAA6B,EAAA;IAE7B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7B,IAAI,MAAM,EAAE;AACV,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,MAAM,OAAO,GAAGA,WAAM,CAAY,CAAA,EAAG,cAAc,GAAG,OAAO,CAAA,CAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAC1E,CAAC,KAAK,KAAI;AACR,QAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;AACjB,QAAA,MAAM,KAAK;AACb,IAAA,CAAC,CACF;AAED,IAAA,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;AACvB,IAAA,OAAO,OAAO;AAChB;AAEA,SAAS,UAAU,CAAC,KAAa,EAAE,IAAY,EAAA;IAC7C,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;AAC7B,QAAA,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAA,kBAAA,CAAoB,CAAC;IAC9C;AACF;AAEA,SAAS,QAAQ,CACf,GAAc,EACd,MAAc,EACd,OAAwD,EAAA;AAExD,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;AAC5D;;;;;;"}
@@ -0,0 +1,66 @@
1
+ interface Path {
2
+ d: string;
3
+ fillRule?: 'nonzero' | 'evenodd';
4
+ opacity?: number;
5
+ }
6
+ interface Symbol {
7
+ viewBox: string;
8
+ paths: Path[];
9
+ }
10
+
11
+ /**
12
+ * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.
13
+ *
14
+ * `Segoe Fluent Icons` is preferred by the Rust backend, with
15
+ * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows
16
+ * platform rejects with the backend platform error.
17
+ *
18
+ * @param icon Glyph text or codepoint, for example `"\uE8BB"` or `"U+E8BB"`.
19
+ * @returns SVG path data and viewBox metadata for the icon.
20
+ */
21
+ declare function getFluentIcon(icon: string): Promise<Symbol>;
22
+ /**
23
+ * Returns a previously resolved Windows Fluent icon without starting IPC.
24
+ *
25
+ * @param icon Glyph text or codepoint used to resolve the icon.
26
+ * @returns Cached SVG data, or `undefined` when the icon has not been loaded.
27
+ */
28
+ declare function getCachedFluentIcon(icon: string): Symbol | undefined;
29
+ /**
30
+ * Preloads Windows Fluent icons in one backend request.
31
+ *
32
+ * @param icons Glyph texts or codepoints to preload.
33
+ */
34
+ declare function preloadFluentIcons(...icons: string[]): Promise<void>;
35
+ /**
36
+ * Resolves a macOS SF Symbol name to SVG path data.
37
+ *
38
+ * Calling this on a non-macOS platform rejects with the backend platform error.
39
+ *
40
+ * @param symbol SF Symbols name, for example `"square.and.arrow.up"`.
41
+ * @returns SVG path data and viewBox metadata for the symbol.
42
+ */
43
+ declare function getSfSymbol(symbol: string): Promise<Symbol>;
44
+ /**
45
+ * Returns a previously resolved SF Symbol without starting IPC.
46
+ *
47
+ * @param symbol SF Symbols name used to resolve the symbol.
48
+ * @returns Cached SVG data, or `undefined` when the symbol has not been loaded.
49
+ */
50
+ declare function getCachedSfSymbol(symbol: string): Symbol | undefined;
51
+ /**
52
+ * Preloads macOS SF Symbols in one backend request.
53
+ *
54
+ * @param symbols SF Symbols names to preload.
55
+ */
56
+ declare function preloadSfSymbols(...symbols: string[]): Promise<void>;
57
+ /**
58
+ * Clears the in-memory JavaScript symbol cache.
59
+ *
60
+ * This only affects frontend-side caching. The Rust backend keeps its own
61
+ * process-local cache.
62
+ */
63
+ declare function clearSymbolCache(): void;
64
+
65
+ export { clearSymbolCache, getCachedFluentIcon, getCachedSfSymbol, getFluentIcon, getSfSymbol, preloadFluentIcons, preloadSfSymbols };
66
+ export type { Path, Symbol };
@@ -0,0 +1,98 @@
1
+ import { clear, get, load, save } from './cache.js';
2
+ import { fluent, sf } from './commands.js';
3
+ import { fluent as fluent$1, sf as sf$1 } from './key.js';
4
+ import { assert, unique } from './text.js';
5
+
6
+ /**
7
+ * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.
8
+ *
9
+ * `Segoe Fluent Icons` is preferred by the Rust backend, with
10
+ * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows
11
+ * platform rejects with the backend platform error.
12
+ *
13
+ * @param icon Glyph text or codepoint, for example `"\uE8BB"` or `"U+E8BB"`.
14
+ * @returns SVG path data and viewBox metadata for the icon.
15
+ */
16
+ function getFluentIcon(icon) {
17
+ assert(icon, 'icon');
18
+ return load(fluent$1(icon), async () => {
19
+ const [symbol] = await fluent([icon]);
20
+ return symbol;
21
+ });
22
+ }
23
+ /**
24
+ * Returns a previously resolved Windows Fluent icon without starting IPC.
25
+ *
26
+ * @param icon Glyph text or codepoint used to resolve the icon.
27
+ * @returns Cached SVG data, or `undefined` when the icon has not been loaded.
28
+ */
29
+ function getCachedFluentIcon(icon) {
30
+ assert(icon, 'icon');
31
+ return get(fluent$1(icon));
32
+ }
33
+ /**
34
+ * Preloads Windows Fluent icons in one backend request.
35
+ *
36
+ * @param icons Glyph texts or codepoints to preload.
37
+ */
38
+ async function preloadFluentIcons(...icons) {
39
+ const unique$1 = unique(icons);
40
+ unique$1.forEach((icon) => assert(icon, 'icon'));
41
+ const missing = unique$1.filter((icon) => !get(fluent$1(icon)));
42
+ if (missing.length === 0) {
43
+ return;
44
+ }
45
+ const symbols = await fluent(missing);
46
+ save(symbols, missing.map((icon) => fluent$1(icon)));
47
+ }
48
+ /**
49
+ * Resolves a macOS SF Symbol name to SVG path data.
50
+ *
51
+ * Calling this on a non-macOS platform rejects with the backend platform error.
52
+ *
53
+ * @param symbol SF Symbols name, for example `"square.and.arrow.up"`.
54
+ * @returns SVG path data and viewBox metadata for the symbol.
55
+ */
56
+ function getSfSymbol(symbol) {
57
+ assert(symbol, 'symbol');
58
+ return load(sf$1(symbol), async () => {
59
+ const [icon] = await sf([symbol]);
60
+ return icon;
61
+ });
62
+ }
63
+ /**
64
+ * Returns a previously resolved SF Symbol without starting IPC.
65
+ *
66
+ * @param symbol SF Symbols name used to resolve the symbol.
67
+ * @returns Cached SVG data, or `undefined` when the symbol has not been loaded.
68
+ */
69
+ function getCachedSfSymbol(symbol) {
70
+ assert(symbol, 'symbol');
71
+ return get(sf$1(symbol));
72
+ }
73
+ /**
74
+ * Preloads macOS SF Symbols in one backend request.
75
+ *
76
+ * @param symbols SF Symbols names to preload.
77
+ */
78
+ async function preloadSfSymbols(...symbols) {
79
+ const unique$1 = unique(symbols);
80
+ unique$1.forEach((symbol) => assert(symbol, 'symbol'));
81
+ const missing = unique$1.filter((symbol) => !get(sf$1(symbol)));
82
+ if (missing.length === 0) {
83
+ return;
84
+ }
85
+ const icons = await sf(missing);
86
+ save(icons, missing.map((symbol) => sf$1(symbol)));
87
+ }
88
+ /**
89
+ * Clears the in-memory JavaScript symbol cache.
90
+ *
91
+ * This only affects frontend-side caching. The Rust backend keeps its own
92
+ * process-local cache.
93
+ */
94
+ function clearSymbolCache() {
95
+ clear();
96
+ }
97
+
98
+ export { clearSymbolCache, getCachedFluentIcon, getCachedSfSymbol, getFluentIcon, getSfSymbol, preloadFluentIcons, preloadSfSymbols };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../guest-js/index.ts"],"sourcesContent":["import { invoke } from '@tauri-apps/api/core'\n\nconst COMMAND_PREFIX = 'plugin:system-symbols|'\n\nexport type SymbolSet = 'fluent' | 'sfSymbols'\nexport type FillRule = 'nonzero' | 'evenodd'\n\nexport interface SvgPath {\n d: string\n fillRule?: FillRule\n opacity?: number\n}\n\nexport interface SvgSymbol {\n set: SymbolSet\n symbol: string\n viewBox: string\n paths: SvgPath[]\n}\n\nexport interface FluentIconOptions {}\n\nexport interface SfSymbolOptions {}\n\nconst cache = new Map<string, Promise<SvgSymbol>>()\n\n/**\n * Resolves a Windows Segoe Fluent Icons glyph to SVG path data.\n *\n * `Segoe Fluent Icons` is preferred by the Rust backend, with\n * `Segoe MDL2 Assets` used as the fallback font. Calling this on a non-Windows\n * platform rejects with the backend platform error.\n *\n * @param icon Glyph text or codepoint, for example `\"\\uE8BB\"` or `\"U+E8BB\"`.\n * @param options Reserved for future Fluent icon rendering options.\n * @returns SVG path data and viewBox metadata for the icon.\n */\nexport function getFluentIcon(\n icon: string,\n options?: FluentIconOptions\n): Promise<SvgSymbol> {\n assertText(icon, 'icon')\n return load('fluent', icon, options, 'get_fluent_icon', {\n icon,\n options: options ?? null\n })\n}\n\n/**\n * Resolves a macOS SF Symbol name to SVG path data.\n *\n * Calling this on a non-macOS platform rejects with the backend platform error.\n *\n * @param symbol SF Symbols name, for example `\"square.and.arrow.up\"`.\n * @param options Reserved for future SF Symbols rendering options.\n * @returns SVG path data and viewBox metadata for the symbol.\n */\nexport function getSfSymbol(\n symbol: string,\n options?: SfSymbolOptions\n): Promise<SvgSymbol> {\n assertText(symbol, 'symbol')\n return load('sfSymbols', symbol, options, 'get_sf_symbol', {\n symbol,\n options: options ?? null\n })\n}\n\n/**\n * Clears the in-memory JavaScript symbol cache.\n *\n * This only affects frontend-side Promise caching. The Rust backend keeps its\n * own process-local cache.\n */\nexport function clearSymbolCache(): void {\n cache.clear()\n}\n\nfunction load(\n set: SymbolSet,\n symbol: string,\n options: FluentIconOptions | SfSymbolOptions | undefined,\n command: string,\n args: Record<string, unknown>\n): Promise<SvgSymbol> {\n const key = cacheKey(set, symbol, options)\n const cached = cache.get(key)\n if (cached) {\n return cached\n }\n\n const pending = invoke<SvgSymbol>(`${COMMAND_PREFIX}${command}`, args).catch(\n (error) => {\n cache.delete(key)\n throw error\n }\n )\n\n cache.set(key, pending)\n return pending\n}\n\nfunction assertText(value: string, name: string): void {\n if (value.trim().length === 0) {\n throw new Error(`${name} must not be empty`)\n }\n}\n\nfunction cacheKey(\n set: SymbolSet,\n symbol: string,\n options: FluentIconOptions | SfSymbolOptions | undefined\n): string {\n return `${set}:${symbol}:${JSON.stringify(options ?? {})}`\n}\n"],"names":[],"mappings":";;AAEA,MAAM,cAAc,GAAG,wBAAwB;AAsB/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B;AAEnD;;;;;;;;;;AAUG;AACG,SAAU,aAAa,CAC3B,IAAY,EACZ,OAA2B,EAAA;AAE3B,IAAA,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;IACxB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE;QACtD,IAAI;QACJ,OAAO,EAAE,OAAO,IAAI;AACrB,KAAA,CAAC;AACJ;AAEA;;;;;;;;AAQG;AACG,SAAU,WAAW,CACzB,MAAc,EACd,OAAyB,EAAA;AAEzB,IAAA,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE;QACzD,MAAM;QACN,OAAO,EAAE,OAAO,IAAI;AACrB,KAAA,CAAC;AACJ;AAEA;;;;;AAKG;SACa,gBAAgB,GAAA;IAC9B,KAAK,CAAC,KAAK,EAAE;AACf;AAEA,SAAS,IAAI,CACX,GAAc,EACd,MAAc,EACd,OAAwD,EACxD,OAAe,EACf,IAA6B,EAAA;IAE7B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7B,IAAI,MAAM,EAAE;AACV,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,MAAM,OAAO,GAAG,MAAM,CAAY,CAAA,EAAG,cAAc,GAAG,OAAO,CAAA,CAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAC1E,CAAC,KAAK,KAAI;AACR,QAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;AACjB,QAAA,MAAM,KAAK;AACb,IAAA,CAAC,CACF;AAED,IAAA,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;AACvB,IAAA,OAAO,OAAO;AAChB;AAEA,SAAS,UAAU,CAAC,KAAa,EAAE,IAAY,EAAA;IAC7C,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;AAC7B,QAAA,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAA,kBAAA,CAAoB,CAAC;IAC9C;AACF;AAEA,SAAS,QAAQ,CACf,GAAc,EACd,MAAc,EACd,OAAwD,EAAA;AAExD,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;AAC5D;;;;"}
@@ -0,0 +1,2 @@
1
+ export declare function fluent(icon: string): string;
2
+ export declare function sf(symbol: string): string;
package/dist-js/key.js ADDED
@@ -0,0 +1,8 @@
1
+ function fluent(icon) {
2
+ return `fluent:${icon}`;
3
+ }
4
+ function sf(symbol) {
5
+ return `sf:${symbol}`;
6
+ }
7
+
8
+ export { fluent, sf };
@@ -0,0 +1,2 @@
1
+ export declare function assert(value: string, name: string): void;
2
+ export declare function unique(values: string[]): string[];
@@ -0,0 +1,10 @@
1
+ function assert(value, name) {
2
+ if (value.trim().length === 0) {
3
+ throw new Error(`${name} must not be empty`);
4
+ }
5
+ }
6
+ function unique(values) {
7
+ return [...new Set(values)];
8
+ }
9
+
10
+ export { assert, unique };
@@ -0,0 +1,9 @@
1
+ export interface Path {
2
+ d: string;
3
+ fillRule?: 'nonzero' | 'evenodd';
4
+ opacity?: number;
5
+ }
6
+ export interface Symbol {
7
+ viewBox: string;
8
+ paths: Path[];
9
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "tauri-plugin-system-symbols",
3
+ "version": "0.1.0",
4
+ "description": "System symbol SVG paths for Tauri apps.",
5
+ "license": "MIT",
6
+ "author": "insd47",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/insd47/tauri-plugin-system-symbols.git"
10
+ },
11
+ "packageManager": "pnpm@10.24.0",
12
+ "type": "module",
13
+ "types": "./dist-js/index.d.ts",
14
+ "main": "./dist-js/index.cjs",
15
+ "module": "./dist-js/index.js",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist-js/index.d.ts",
19
+ "import": "./dist-js/index.js",
20
+ "require": "./dist-js/index.cjs"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist-js",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "scripts": {
29
+ "build": "rollup -c",
30
+ "check": "tsc --noEmit",
31
+ "prepack": "pnpm run build"
32
+ },
33
+ "dependencies": {
34
+ "@tauri-apps/api": "^2.11.0"
35
+ },
36
+ "devDependencies": {
37
+ "@rollup/plugin-typescript": "^12.3.0",
38
+ "prettier": "^3.8.4",
39
+ "rollup": "^4.44.0",
40
+ "rollup-plugin-dts": "^6.2.1",
41
+ "tslib": "^2.8.1",
42
+ "typescript": "^5.8.3"
43
+ }
44
+ }