@pro-laico/payload-icons 0.0.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 (119) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +9 -0
  3. package/dist/cache/index.d.ts +9 -0
  4. package/dist/cache/index.d.ts.map +1 -0
  5. package/dist/cache/index.js +96 -0
  6. package/dist/cache/index.js.map +1 -0
  7. package/dist/collections/Icon.d.ts +14 -0
  8. package/dist/collections/Icon.d.ts.map +1 -0
  9. package/dist/collections/Icon.js +96 -0
  10. package/dist/collections/Icon.js.map +1 -0
  11. package/dist/collections/IconRequest.d.ts +30 -0
  12. package/dist/collections/IconRequest.d.ts.map +1 -0
  13. package/dist/collections/IconRequest.js +82 -0
  14. package/dist/collections/IconRequest.js.map +1 -0
  15. package/dist/collections/IconSet.d.ts +43 -0
  16. package/dist/collections/IconSet.d.ts.map +1 -0
  17. package/dist/collections/IconSet.js +168 -0
  18. package/dist/collections/IconSet.js.map +1 -0
  19. package/dist/components/Icon.d.ts +35 -0
  20. package/dist/components/Icon.d.ts.map +1 -0
  21. package/dist/components/Icon.js +56 -0
  22. package/dist/components/Icon.js.map +1 -0
  23. package/dist/components/admin/clearIconRequests.d.ts +14 -0
  24. package/dist/components/admin/clearIconRequests.d.ts.map +1 -0
  25. package/dist/components/admin/clearIconRequests.js +52 -0
  26. package/dist/components/admin/clearIconRequests.js.map +1 -0
  27. package/dist/components/admin/iconPreview.d.ts +7 -0
  28. package/dist/components/admin/iconPreview.d.ts.map +1 -0
  29. package/dist/components/admin/iconPreview.js +49 -0
  30. package/dist/components/admin/iconPreview.js.map +1 -0
  31. package/dist/components/admin/iconRowLabel.d.ts +8 -0
  32. package/dist/components/admin/iconRowLabel.d.ts.map +1 -0
  33. package/dist/components/admin/iconRowLabel.js +28 -0
  34. package/dist/components/admin/iconRowLabel.js.map +1 -0
  35. package/dist/components/admin/iconUsagePanel.client.d.ts +26 -0
  36. package/dist/components/admin/iconUsagePanel.client.d.ts.map +1 -0
  37. package/dist/components/admin/iconUsagePanel.client.js +290 -0
  38. package/dist/components/admin/iconUsagePanel.client.js.map +1 -0
  39. package/dist/components/admin/iconUsagePanel.d.ts +12 -0
  40. package/dist/components/admin/iconUsagePanel.d.ts.map +1 -0
  41. package/dist/components/admin/iconUsagePanel.js +68 -0
  42. package/dist/components/admin/iconUsagePanel.js.map +1 -0
  43. package/dist/hooks/formatSVG.d.ts +22 -0
  44. package/dist/hooks/formatSVG.d.ts.map +1 -0
  45. package/dist/hooks/formatSVG.js +270 -0
  46. package/dist/hooks/formatSVG.js.map +1 -0
  47. package/dist/index.d.ts +7 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +10 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lib/activeField.d.ts +24 -0
  52. package/dist/lib/activeField.d.ts.map +1 -0
  53. package/dist/lib/activeField.js +71 -0
  54. package/dist/lib/activeField.js.map +1 -0
  55. package/dist/lib/authenticated.d.ts +5 -0
  56. package/dist/lib/authenticated.d.ts.map +1 -0
  57. package/dist/lib/authenticated.js +4 -0
  58. package/dist/lib/authenticated.js.map +1 -0
  59. package/dist/lib/defaultAccess.d.ts +8 -0
  60. package/dist/lib/defaultAccess.d.ts.map +1 -0
  61. package/dist/lib/defaultAccess.js +6 -0
  62. package/dist/lib/defaultAccess.js.map +1 -0
  63. package/dist/lib/extractSVG.d.ts +3 -0
  64. package/dist/lib/extractSVG.d.ts.map +1 -0
  65. package/dist/lib/extractSVG.js +27 -0
  66. package/dist/lib/extractSVG.js.map +1 -0
  67. package/dist/lib/getPayloadClient.d.ts +22 -0
  68. package/dist/lib/getPayloadClient.d.ts.map +1 -0
  69. package/dist/lib/getPayloadClient.js +39 -0
  70. package/dist/lib/getPayloadClient.js.map +1 -0
  71. package/dist/lib/mergeHooks.d.ts +8 -0
  72. package/dist/lib/mergeHooks.d.ts.map +1 -0
  73. package/dist/lib/mergeHooks.js +19 -0
  74. package/dist/lib/mergeHooks.js.map +1 -0
  75. package/dist/lib/titleCase.d.ts +7 -0
  76. package/dist/lib/titleCase.d.ts.map +1 -0
  77. package/dist/lib/titleCase.js +17 -0
  78. package/dist/lib/titleCase.js.map +1 -0
  79. package/dist/plugin.d.ts +91 -0
  80. package/dist/plugin.d.ts.map +1 -0
  81. package/dist/plugin.js +72 -0
  82. package/dist/plugin.js.map +1 -0
  83. package/dist/scan/cli.d.ts +14 -0
  84. package/dist/scan/cli.d.ts.map +1 -0
  85. package/dist/scan/cli.js +114 -0
  86. package/dist/scan/cli.js.map +1 -0
  87. package/dist/scan/extract.d.ts +58 -0
  88. package/dist/scan/extract.d.ts.map +1 -0
  89. package/dist/scan/extract.js +286 -0
  90. package/dist/scan/extract.js.map +1 -0
  91. package/dist/scan/index.d.ts +81 -0
  92. package/dist/scan/index.d.ts.map +1 -0
  93. package/dist/scan/index.js +133 -0
  94. package/dist/scan/index.js.map +1 -0
  95. package/dist/scan/live.d.ts +20 -0
  96. package/dist/scan/live.d.ts.map +1 -0
  97. package/dist/scan/live.js +109 -0
  98. package/dist/scan/live.js.map +1 -0
  99. package/dist/scan/load.d.ts +28 -0
  100. package/dist/scan/load.d.ts.map +1 -0
  101. package/dist/scan/load.js +37 -0
  102. package/dist/scan/load.js.map +1 -0
  103. package/dist/scan/types.d.ts +29 -0
  104. package/dist/scan/types.d.ts.map +1 -0
  105. package/dist/scan/types.js +8 -0
  106. package/dist/scan/types.js.map +1 -0
  107. package/dist/types.d.ts +38 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +3 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/usage/recordMiss.d.ts +17 -0
  112. package/dist/usage/recordMiss.d.ts.map +1 -0
  113. package/dist/usage/recordMiss.js +60 -0
  114. package/dist/usage/recordMiss.js.map +1 -0
  115. package/dist/usage/trackIconMiss.d.ts +16 -0
  116. package/dist/usage/trackIconMiss.d.ts.map +1 -0
  117. package/dist/usage/trackIconMiss.js +43 -0
  118. package/dist/usage/trackIconMiss.js.map +1 -0
  119. package/package.json +106 -0
@@ -0,0 +1,290 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useMemo, useState } from "react";
4
+ import { Button, Pill, toast, useAllFormFields } from "@payloadcms/ui";
5
+ import { clearIconRequests } from "./clearIconRequests.js";
6
+ /** Matches the live `name` field of each `iconsArray` row so we can read the
7
+ * set's current names straight from form state (updates as you edit). */ const ICON_NAME_PATH = /^iconsArray\.\d+\.name$/;
8
+ const panelStyle = {
9
+ border: '1px solid var(--theme-elevation-150)',
10
+ borderRadius: 'var(--style-radius-m, 4px)',
11
+ padding: '1rem',
12
+ marginBlockStart: '0.5rem',
13
+ background: 'var(--theme-elevation-50)'
14
+ };
15
+ const noteStyle = {
16
+ color: 'var(--theme-elevation-500)',
17
+ fontSize: '0.8rem',
18
+ margin: '0.25rem 0 0'
19
+ };
20
+ const codeStyle = {
21
+ fontFamily: 'var(--font-mono, monospace)',
22
+ background: 'var(--theme-elevation-100)',
23
+ padding: '0.15rem 0.35rem',
24
+ borderRadius: '3px'
25
+ };
26
+ /** Groups manifest usages by icon name, preserving the manifest's stable order. */ const groupByName = (usages)=>{
27
+ const map = new Map();
28
+ for (const u of usages){
29
+ const list = map.get(u.name);
30
+ if (list) list.push(u);
31
+ else map.set(u.name, [
32
+ u
33
+ ]);
34
+ }
35
+ return map;
36
+ };
37
+ const formatDate = (iso)=>{
38
+ if (!iso) return '';
39
+ const t = Date.parse(iso);
40
+ return Number.isNaN(t) ? '' : new Date(t).toLocaleDateString();
41
+ };
42
+ /**
43
+ * Three-way compare for the IconSet edit view: the names this repo requests in
44
+ * code (the build-time manifest), the names actually requested in production
45
+ * that didn't resolve (the `iconRequest` collection), and the names defined in
46
+ * the set being edited (live form state). Adding a row clears its "missing"
47
+ * badge immediately.
48
+ */ export const IconUsagePanelClient = ({ manifest, scanCommand, liveRequests })=>{
49
+ const [fields] = useAllFormFields();
50
+ // Local working copy so the "Clear runtime requests" action can empty the list
51
+ // immediately without a full page reload.
52
+ const [live, setLive] = useState(liveRequests);
53
+ const [clearing, setClearing] = useState(false);
54
+ // All hooks run unconditionally (before any early return) so hook order stays
55
+ // stable across renders.
56
+ const defined = useMemo(()=>{
57
+ const set = new Set();
58
+ for (const [path, state] of Object.entries(fields)){
59
+ const value = state?.value;
60
+ if (ICON_NAME_PATH.test(path) && typeof value === 'string' && value.length > 0) set.add(value);
61
+ }
62
+ return set;
63
+ }, [
64
+ fields
65
+ ]);
66
+ const usagesByName = useMemo(()=>groupByName(manifest?.usages ?? []), [
67
+ manifest
68
+ ]);
69
+ const liveByName = useMemo(()=>new Map(live.map((r)=>[
70
+ r.name,
71
+ r
72
+ ])), [
73
+ live
74
+ ]);
75
+ const staticNames = manifest?.names ?? [];
76
+ // Union of names missing from this set: requested in code OR requested live.
77
+ const missing = useMemo(()=>{
78
+ const names = new Set();
79
+ for (const n of staticNames)if (!defined.has(n)) names.add(n);
80
+ for (const r of live)if (!defined.has(r.name)) names.add(r.name);
81
+ return [
82
+ ...names
83
+ ].sort((a, b)=>a.localeCompare(b));
84
+ }, [
85
+ staticNames,
86
+ live,
87
+ defined
88
+ ]);
89
+ const present = staticNames.filter((name)=>defined.has(name));
90
+ const liveMissing = live.filter((r)=>!defined.has(r.name)).length;
91
+ const handleClear = async ()=>{
92
+ setClearing(true);
93
+ try {
94
+ const result = await clearIconRequests();
95
+ if (result.success) {
96
+ setLive([]);
97
+ toast.success(result.message);
98
+ } else {
99
+ toast.error(result.message);
100
+ }
101
+ } catch (error) {
102
+ toast.error(error instanceof Error ? error.message : 'Failed to clear icon requests.');
103
+ } finally{
104
+ setClearing(false);
105
+ }
106
+ };
107
+ if (!manifest && live.length === 0) {
108
+ return /*#__PURE__*/ _jsxs("div", {
109
+ style: panelStyle,
110
+ children: [
111
+ /*#__PURE__*/ _jsx("strong", {
112
+ children: "Requested icons"
113
+ }),
114
+ /*#__PURE__*/ _jsxs("p", {
115
+ style: noteStyle,
116
+ children: [
117
+ "No usage manifest found. Run ",
118
+ /*#__PURE__*/ _jsx("code", {
119
+ style: codeStyle,
120
+ children: scanCommand
121
+ }),
122
+ " in your project to scan source for",
123
+ ' ',
124
+ /*#__PURE__*/ _jsx("code", {
125
+ style: codeStyle,
126
+ children: '<Icon name="…" />'
127
+ }),
128
+ " and list the names your repo needs here. Enable",
129
+ ' ',
130
+ /*#__PURE__*/ _jsx("code", {
131
+ style: codeStyle,
132
+ children: "trackRequests"
133
+ }),
134
+ " to also capture runtime misses."
135
+ ]
136
+ })
137
+ ]
138
+ });
139
+ }
140
+ return /*#__PURE__*/ _jsxs("div", {
141
+ style: panelStyle,
142
+ children: [
143
+ /*#__PURE__*/ _jsx("strong", {
144
+ children: "Requested icons"
145
+ }),
146
+ /*#__PURE__*/ _jsxs("p", {
147
+ style: noteStyle,
148
+ children: [
149
+ manifest ? /*#__PURE__*/ _jsxs(_Fragment, {
150
+ children: [
151
+ present.length,
152
+ " of ",
153
+ staticNames.length,
154
+ " name",
155
+ staticNames.length === 1 ? '' : 's',
156
+ " requested in code are defined here."
157
+ ]
158
+ }) : /*#__PURE__*/ _jsx(_Fragment, {
159
+ children: "No build-time manifest — showing runtime requests only."
160
+ }),
161
+ liveMissing > 0 ? ` ${liveMissing} requested in production but missing.` : missing.length === 0 ? ' All present ✅' : ''
162
+ ]
163
+ }),
164
+ live.length > 0 && /*#__PURE__*/ _jsx("div", {
165
+ style: {
166
+ marginTop: '0.5rem'
167
+ },
168
+ children: /*#__PURE__*/ _jsx(Button, {
169
+ type: "button",
170
+ buttonStyle: "secondary",
171
+ size: "small",
172
+ disabled: clearing,
173
+ onClick: handleClear,
174
+ children: clearing ? 'Clearing…' : `Clear ${live.length} runtime request${live.length === 1 ? '' : 's'}`
175
+ })
176
+ }),
177
+ missing.length > 0 && /*#__PURE__*/ _jsxs("div", {
178
+ style: {
179
+ marginTop: '0.75rem'
180
+ },
181
+ children: [
182
+ /*#__PURE__*/ _jsx("div", {
183
+ style: {
184
+ ...noteStyle,
185
+ fontWeight: 600
186
+ },
187
+ children: "Missing from this set"
188
+ }),
189
+ /*#__PURE__*/ _jsx("ul", {
190
+ style: {
191
+ listStyle: 'none',
192
+ margin: '0.35rem 0 0',
193
+ padding: 0,
194
+ display: 'flex',
195
+ flexDirection: 'column',
196
+ gap: '0.4rem'
197
+ },
198
+ children: missing.map((name)=>{
199
+ const where = usagesByName.get(name) ?? [];
200
+ const first = where[0];
201
+ const liveReq = liveByName.get(name);
202
+ return /*#__PURE__*/ _jsxs("li", {
203
+ style: {
204
+ display: 'flex',
205
+ alignItems: 'center',
206
+ gap: '0.5rem',
207
+ flexWrap: 'wrap'
208
+ },
209
+ children: [
210
+ /*#__PURE__*/ _jsx(Pill, {
211
+ pillStyle: liveReq ? 'error' : 'warning',
212
+ size: "small",
213
+ children: name
214
+ }),
215
+ first && /*#__PURE__*/ _jsxs("span", {
216
+ style: {
217
+ ...noteStyle,
218
+ margin: 0
219
+ },
220
+ children: [
221
+ /*#__PURE__*/ _jsxs("code", {
222
+ style: codeStyle,
223
+ children: [
224
+ first.file,
225
+ ":",
226
+ first.line
227
+ ]
228
+ }),
229
+ where.length > 1 ? ` +${where.length - 1} more` : ''
230
+ ]
231
+ }),
232
+ liveReq && /*#__PURE__*/ _jsxs("span", {
233
+ style: {
234
+ ...noteStyle,
235
+ margin: 0
236
+ },
237
+ children: [
238
+ "live ×",
239
+ liveReq.count,
240
+ liveReq.lastRequestedAt ? ` · last ${formatDate(liveReq.lastRequestedAt)}` : '',
241
+ !first ? ' · dynamic (not in code scan)' : ''
242
+ ]
243
+ })
244
+ ]
245
+ }, name);
246
+ })
247
+ })
248
+ ]
249
+ }),
250
+ present.length > 0 && /*#__PURE__*/ _jsxs("details", {
251
+ style: {
252
+ marginTop: '0.75rem'
253
+ },
254
+ children: [
255
+ /*#__PURE__*/ _jsxs("summary", {
256
+ style: {
257
+ ...noteStyle,
258
+ margin: 0,
259
+ cursor: 'pointer'
260
+ },
261
+ children: [
262
+ present.length,
263
+ " present"
264
+ ]
265
+ }),
266
+ /*#__PURE__*/ _jsx("ul", {
267
+ style: {
268
+ listStyle: 'none',
269
+ margin: '0.35rem 0 0',
270
+ padding: 0,
271
+ display: 'flex',
272
+ flexWrap: 'wrap',
273
+ gap: '0.35rem'
274
+ },
275
+ children: present.map((name)=>/*#__PURE__*/ _jsx("li", {
276
+ children: /*#__PURE__*/ _jsx(Pill, {
277
+ pillStyle: "white",
278
+ size: "small",
279
+ children: name
280
+ })
281
+ }, name))
282
+ })
283
+ ]
284
+ })
285
+ ]
286
+ });
287
+ };
288
+ export default IconUsagePanelClient;
289
+
290
+ //# sourceMappingURL=iconUsagePanel.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/admin/iconUsagePanel.client.tsx"],"sourcesContent":["'use client'\n\nimport type React from 'react'\nimport { useMemo, useState } from 'react'\nimport { Button, Pill, toast, useAllFormFields } from '@payloadcms/ui'\n\nimport type { IconUsage, IconUsageManifest } from '../../scan/types'\nimport { clearIconRequests } from './clearIconRequests'\n\n/** Matches the live `name` field of each `iconsArray` row so we can read the\n * set's current names straight from form state (updates as you edit). */\nconst ICON_NAME_PATH = /^iconsArray\\.\\d+\\.name$/\n\n/** A name requested at runtime that didn't resolve (from the `iconRequest` collection). */\nexport interface LiveRequest {\n name: string\n count: number\n lastRequestedAt: string | null\n}\n\nexport interface IconUsagePanelClientProps {\n /** The build-time manifest, or `null` when it hasn't been generated yet. */\n manifest: IconUsageManifest | null\n /** CLI command shown in the empty state so the editor knows how to populate it. */\n scanCommand: string\n /** Runtime misses recorded in production (empty unless `trackRequests` is on). */\n liveRequests: LiveRequest[]\n}\n\nconst panelStyle: React.CSSProperties = {\n border: '1px solid var(--theme-elevation-150)',\n borderRadius: 'var(--style-radius-m, 4px)',\n padding: '1rem',\n marginBlockStart: '0.5rem',\n background: 'var(--theme-elevation-50)',\n}\n\nconst noteStyle: React.CSSProperties = { color: 'var(--theme-elevation-500)', fontSize: '0.8rem', margin: '0.25rem 0 0' }\nconst codeStyle: React.CSSProperties = {\n fontFamily: 'var(--font-mono, monospace)',\n background: 'var(--theme-elevation-100)',\n padding: '0.15rem 0.35rem',\n borderRadius: '3px',\n}\n\n/** Groups manifest usages by icon name, preserving the manifest's stable order. */\nconst groupByName = (usages: IconUsage[]): Map<string, IconUsage[]> => {\n const map = new Map<string, IconUsage[]>()\n for (const u of usages) {\n const list = map.get(u.name)\n if (list) list.push(u)\n else map.set(u.name, [u])\n }\n return map\n}\n\nconst formatDate = (iso: string | null): string => {\n if (!iso) return ''\n const t = Date.parse(iso)\n return Number.isNaN(t) ? '' : new Date(t).toLocaleDateString()\n}\n\n/**\n * Three-way compare for the IconSet edit view: the names this repo requests in\n * code (the build-time manifest), the names actually requested in production\n * that didn't resolve (the `iconRequest` collection), and the names defined in\n * the set being edited (live form state). Adding a row clears its \"missing\"\n * badge immediately.\n */\nexport const IconUsagePanelClient: React.FC<IconUsagePanelClientProps> = ({ manifest, scanCommand, liveRequests }) => {\n const [fields] = useAllFormFields()\n // Local working copy so the \"Clear runtime requests\" action can empty the list\n // immediately without a full page reload.\n const [live, setLive] = useState<LiveRequest[]>(liveRequests)\n const [clearing, setClearing] = useState(false)\n\n // All hooks run unconditionally (before any early return) so hook order stays\n // stable across renders.\n const defined = useMemo(() => {\n const set = new Set<string>()\n for (const [path, state] of Object.entries(fields)) {\n const value = (state as { value?: unknown } | undefined)?.value\n if (ICON_NAME_PATH.test(path) && typeof value === 'string' && value.length > 0) set.add(value)\n }\n return set\n }, [fields])\n\n const usagesByName = useMemo(() => groupByName(manifest?.usages ?? []), [manifest])\n const liveByName = useMemo(() => new Map(live.map((r) => [r.name, r])), [live])\n\n const staticNames = manifest?.names ?? []\n // Union of names missing from this set: requested in code OR requested live.\n const missing = useMemo(() => {\n const names = new Set<string>()\n for (const n of staticNames) if (!defined.has(n)) names.add(n)\n for (const r of live) if (!defined.has(r.name)) names.add(r.name)\n return [...names].sort((a, b) => a.localeCompare(b))\n }, [staticNames, live, defined])\n\n const present = staticNames.filter((name) => defined.has(name))\n const liveMissing = live.filter((r) => !defined.has(r.name)).length\n\n const handleClear = async (): Promise<void> => {\n setClearing(true)\n try {\n const result = await clearIconRequests()\n if (result.success) {\n setLive([])\n toast.success(result.message)\n } else {\n toast.error(result.message)\n }\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Failed to clear icon requests.')\n } finally {\n setClearing(false)\n }\n }\n\n if (!manifest && live.length === 0) {\n return (\n <div style={panelStyle}>\n <strong>Requested icons</strong>\n <p style={noteStyle}>\n No usage manifest found. Run <code style={codeStyle}>{scanCommand}</code> in your project to scan source for{' '}\n <code style={codeStyle}>{'<Icon name=\"…\" />'}</code> and list the names your repo needs here. Enable{' '}\n <code style={codeStyle}>trackRequests</code> to also capture runtime misses.\n </p>\n </div>\n )\n }\n\n return (\n <div style={panelStyle}>\n <strong>Requested icons</strong>\n <p style={noteStyle}>\n {manifest ? (\n <>\n {present.length} of {staticNames.length} name{staticNames.length === 1 ? '' : 's'} requested in code are defined here.\n </>\n ) : (\n <>No build-time manifest — showing runtime requests only.</>\n )}\n {liveMissing > 0 ? ` ${liveMissing} requested in production but missing.` : missing.length === 0 ? ' All present ✅' : ''}\n </p>\n\n {live.length > 0 && (\n <div style={{ marginTop: '0.5rem' }}>\n {/* type=\"button\" so it never submits the surrounding IconSet edit form. */}\n <Button type=\"button\" buttonStyle=\"secondary\" size=\"small\" disabled={clearing} onClick={handleClear}>\n {clearing ? 'Clearing…' : `Clear ${live.length} runtime request${live.length === 1 ? '' : 's'}`}\n </Button>\n </div>\n )}\n\n {missing.length > 0 && (\n <div style={{ marginTop: '0.75rem' }}>\n <div style={{ ...noteStyle, fontWeight: 600 }}>Missing from this set</div>\n <ul style={{ listStyle: 'none', margin: '0.35rem 0 0', padding: 0, display: 'flex', flexDirection: 'column', gap: '0.4rem' }}>\n {missing.map((name) => {\n const where = usagesByName.get(name) ?? []\n const first = where[0]\n const liveReq = liveByName.get(name)\n return (\n <li key={name} style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', flexWrap: 'wrap' }}>\n {/* Live (production) misses are the most urgent → error pill. */}\n <Pill pillStyle={liveReq ? 'error' : 'warning'} size=\"small\">\n {name}\n </Pill>\n {first && (\n <span style={{ ...noteStyle, margin: 0 }}>\n <code style={codeStyle}>\n {first.file}:{first.line}\n </code>\n {where.length > 1 ? ` +${where.length - 1} more` : ''}\n </span>\n )}\n {liveReq && (\n <span style={{ ...noteStyle, margin: 0 }}>\n live ×{liveReq.count}\n {liveReq.lastRequestedAt ? ` · last ${formatDate(liveReq.lastRequestedAt)}` : ''}\n {!first ? ' · dynamic (not in code scan)' : ''}\n </span>\n )}\n </li>\n )\n })}\n </ul>\n </div>\n )}\n\n {present.length > 0 && (\n <details style={{ marginTop: '0.75rem' }}>\n <summary style={{ ...noteStyle, margin: 0, cursor: 'pointer' }}>{present.length} present</summary>\n <ul style={{ listStyle: 'none', margin: '0.35rem 0 0', padding: 0, display: 'flex', flexWrap: 'wrap', gap: '0.35rem' }}>\n {present.map((name) => (\n <li key={name}>\n <Pill pillStyle=\"white\" size=\"small\">\n {name}\n </Pill>\n </li>\n ))}\n </ul>\n </details>\n )}\n </div>\n )\n}\n\nexport default IconUsagePanelClient\n"],"names":["useMemo","useState","Button","Pill","toast","useAllFormFields","clearIconRequests","ICON_NAME_PATH","panelStyle","border","borderRadius","padding","marginBlockStart","background","noteStyle","color","fontSize","margin","codeStyle","fontFamily","groupByName","usages","map","Map","u","list","get","name","push","set","formatDate","iso","t","Date","parse","Number","isNaN","toLocaleDateString","IconUsagePanelClient","manifest","scanCommand","liveRequests","fields","live","setLive","clearing","setClearing","defined","Set","path","state","Object","entries","value","test","length","add","usagesByName","liveByName","r","staticNames","names","missing","n","has","sort","a","b","localeCompare","present","filter","liveMissing","handleClear","result","success","message","error","Error","div","style","strong","p","code","marginTop","type","buttonStyle","size","disabled","onClick","fontWeight","ul","listStyle","display","flexDirection","gap","where","first","liveReq","li","alignItems","flexWrap","pillStyle","span","file","line","count","lastRequestedAt","details","summary","cursor"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import 'server-only';
2
+ import type { UIFieldServerComponent } from 'payload';
3
+ /**
4
+ * Server `UIField` for the IconSet edit view. Gets the usage manifest (live scan
5
+ * in dev, CLI-written file in prod — see {@link getManifest}) plus the runtime
6
+ * misses from the `iconRequest` collection, and hands both to
7
+ * {@link IconUsagePanelClient}, which diffs them against the set's `iconsArray`.
8
+ * Server-only, so no `fs` reaches the client bundle.
9
+ */
10
+ export declare const IconUsagePanel: UIFieldServerComponent;
11
+ export default IconUsagePanel;
12
+ //# sourceMappingURL=iconUsagePanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconUsagePanel.d.ts","sourceRoot":"","sources":["../../../src/components/admin/iconUsagePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAkB,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAsDrE;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,sBAI5B,CAAA;AAED,eAAe,cAAc,CAAA"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import "server-only";
3
+ import { ICON_REQUEST_SLUG } from "../../collections/IconRequest.js";
4
+ import { getPayloadClient } from "../../lib/getPayloadClient.js";
5
+ import { loadIconUsageManifest } from "../../scan/load.js";
6
+ import { scanIconUsagesLive } from "../../scan/live.js";
7
+ import { IconUsagePanelClient } from "./iconUsagePanel.client.js";
8
+ /** Default scan command surfaced in the panel's empty state (production, no manifest). */ const DEFAULT_SCAN_COMMAND = 'npx payload-icons-scan';
9
+ /**
10
+ * The usage manifest for the panel. In **development** the source is on disk, so
11
+ * scan it live — no build step / CLI / manifest file needed to see what the code
12
+ * requests. In **production** the source isn't on disk at runtime, so read the
13
+ * manifest the CLI wrote at build time.
14
+ */ const getManifest = (manifestPath)=>{
15
+ if (process.env.NODE_ENV !== 'production') {
16
+ try {
17
+ return scanIconUsagesLive();
18
+ } catch {
19
+ // Fall through to the file if the live scan can't run for any reason.
20
+ }
21
+ }
22
+ return loadIconUsageManifest(manifestPath);
23
+ };
24
+ /**
25
+ * Loads runtime icon misses from the `iconRequest` collection. Returns `[]`
26
+ * when tracking isn't enabled (collection absent) or on any error — the panel
27
+ * degrades to the static-only view.
28
+ */ const loadLiveRequests = async ()=>{
29
+ try {
30
+ const payload = await getPayloadClient();
31
+ if (!payload.collections?.[ICON_REQUEST_SLUG]) return [];
32
+ const res = await payload.find({
33
+ collection: ICON_REQUEST_SLUG,
34
+ limit: 500,
35
+ depth: 0,
36
+ sort: '-count',
37
+ overrideAccess: true
38
+ });
39
+ return res.docs.map((d)=>{
40
+ const r = d;
41
+ return {
42
+ name: r.name ?? '',
43
+ count: r.count ?? 0,
44
+ lastRequestedAt: r.lastRequestedAt ?? null
45
+ };
46
+ });
47
+ } catch {
48
+ return [];
49
+ }
50
+ };
51
+ /**
52
+ * Server `UIField` for the IconSet edit view. Gets the usage manifest (live scan
53
+ * in dev, CLI-written file in prod — see {@link getManifest}) plus the runtime
54
+ * misses from the `iconRequest` collection, and hands both to
55
+ * {@link IconUsagePanelClient}, which diffs them against the set's `iconsArray`.
56
+ * Server-only, so no `fs` reaches the client bundle.
57
+ */ export const IconUsagePanel = async ()=>{
58
+ const manifest = getManifest();
59
+ const liveRequests = await loadLiveRequests();
60
+ return /*#__PURE__*/ _jsx(IconUsagePanelClient, {
61
+ manifest: manifest,
62
+ scanCommand: DEFAULT_SCAN_COMMAND,
63
+ liveRequests: liveRequests
64
+ });
65
+ };
66
+ export default IconUsagePanel;
67
+
68
+ //# sourceMappingURL=iconUsagePanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/admin/iconUsagePanel.tsx"],"sourcesContent":["import 'server-only'\n\nimport type { CollectionSlug, UIFieldServerComponent } from 'payload'\n\nimport { ICON_REQUEST_SLUG } from '../../collections/IconRequest'\nimport { getPayloadClient } from '../../lib/getPayloadClient'\nimport { loadIconUsageManifest } from '../../scan/load'\nimport { scanIconUsagesLive } from '../../scan/live'\nimport type { IconUsageManifest } from '../../scan/types'\nimport { IconUsagePanelClient, type LiveRequest } from './iconUsagePanel.client'\n\n/** Default scan command surfaced in the panel's empty state (production, no manifest). */\nconst DEFAULT_SCAN_COMMAND = 'npx payload-icons-scan'\n\n/**\n * The usage manifest for the panel. In **development** the source is on disk, so\n * scan it live — no build step / CLI / manifest file needed to see what the code\n * requests. In **production** the source isn't on disk at runtime, so read the\n * manifest the CLI wrote at build time.\n */\nconst getManifest = (manifestPath?: string): IconUsageManifest | null => {\n if (process.env.NODE_ENV !== 'production') {\n try {\n return scanIconUsagesLive()\n } catch {\n // Fall through to the file if the live scan can't run for any reason.\n }\n }\n return loadIconUsageManifest(manifestPath)\n}\n\n/**\n * Loads runtime icon misses from the `iconRequest` collection. Returns `[]`\n * when tracking isn't enabled (collection absent) or on any error — the panel\n * degrades to the static-only view.\n */\nconst loadLiveRequests = async (): Promise<LiveRequest[]> => {\n try {\n const payload = await getPayloadClient()\n if (!(payload.collections as Record<string, unknown>)?.[ICON_REQUEST_SLUG]) return []\n const res = await payload.find({\n collection: ICON_REQUEST_SLUG as CollectionSlug,\n limit: 500,\n depth: 0,\n sort: '-count',\n overrideAccess: true,\n })\n return res.docs.map((d) => {\n const r = d as { name?: string; count?: number | null; lastRequestedAt?: string | null }\n return { name: r.name ?? '', count: r.count ?? 0, lastRequestedAt: r.lastRequestedAt ?? null }\n })\n } catch {\n return []\n }\n}\n\n/**\n * Server `UIField` for the IconSet edit view. Gets the usage manifest (live scan\n * in dev, CLI-written file in prod — see {@link getManifest}) plus the runtime\n * misses from the `iconRequest` collection, and hands both to\n * {@link IconUsagePanelClient}, which diffs them against the set's `iconsArray`.\n * Server-only, so no `fs` reaches the client bundle.\n */\nexport const IconUsagePanel: UIFieldServerComponent = async () => {\n const manifest = getManifest()\n const liveRequests = await loadLiveRequests()\n return <IconUsagePanelClient manifest={manifest} scanCommand={DEFAULT_SCAN_COMMAND} liveRequests={liveRequests} />\n}\n\nexport default IconUsagePanel\n"],"names":["ICON_REQUEST_SLUG","getPayloadClient","loadIconUsageManifest","scanIconUsagesLive","IconUsagePanelClient","DEFAULT_SCAN_COMMAND","getManifest","manifestPath","process","env","NODE_ENV","loadLiveRequests","payload","collections","res","find","collection","limit","depth","sort","overrideAccess","docs","map","d","r","name","count","lastRequestedAt","IconUsagePanel","manifest","liveRequests","scanCommand"],"mappings":";AAAA,OAAO,cAAa;AAIpB,SAASA,iBAAiB,QAAQ,mCAA+B;AACjE,SAASC,gBAAgB,QAAQ,gCAA4B;AAC7D,SAASC,qBAAqB,QAAQ,qBAAiB;AACvD,SAASC,kBAAkB,QAAQ,qBAAiB;AAEpD,SAASC,oBAAoB,QAA0B,6BAAyB;AAEhF,wFAAwF,GACxF,MAAMC,uBAAuB;AAE7B;;;;;CAKC,GACD,MAAMC,cAAc,CAACC;IACnB,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,IAAI;YACF,OAAOP;QACT,EAAE,OAAM;QACN,sEAAsE;QACxE;IACF;IACA,OAAOD,sBAAsBK;AAC/B;AAEA;;;;CAIC,GACD,MAAMI,mBAAmB;IACvB,IAAI;QACF,MAAMC,UAAU,MAAMX;QACtB,IAAI,CAAEW,QAAQC,WAAW,EAA8B,CAACb,kBAAkB,EAAE,OAAO,EAAE;QACrF,MAAMc,MAAM,MAAMF,QAAQG,IAAI,CAAC;YAC7BC,YAAYhB;YACZiB,OAAO;YACPC,OAAO;YACPC,MAAM;YACNC,gBAAgB;QAClB;QACA,OAAON,IAAIO,IAAI,CAACC,GAAG,CAAC,CAACC;YACnB,MAAMC,IAAID;YACV,OAAO;gBAAEE,MAAMD,EAAEC,IAAI,IAAI;gBAAIC,OAAOF,EAAEE,KAAK,IAAI;gBAAGC,iBAAiBH,EAAEG,eAAe,IAAI;YAAK;QAC/F;IACF,EAAE,OAAM;QACN,OAAO,EAAE;IACX;AACF;AAEA;;;;;;CAMC,GACD,OAAO,MAAMC,iBAAyC;IACpD,MAAMC,WAAWvB;IACjB,MAAMwB,eAAe,MAAMnB;IAC3B,qBAAO,KAACP;QAAqByB,UAAUA;QAAUE,aAAa1B;QAAsByB,cAAcA;;AACpG,EAAC;AAED,eAAeF,eAAc"}
@@ -0,0 +1,22 @@
1
+ import type { CollectionBeforeChangeHook, Payload } from 'payload';
2
+ /** The subset of an icon doc this hook writes. */
3
+ type IconData = Record<string, unknown> & {
4
+ filesize?: number;
5
+ optimized?: string;
6
+ svgString?: string;
7
+ };
8
+ /**
9
+ * Optimize and sanitize an uploaded SVG: run svgo (sanitize → preset-default → strip presentation
10
+ * attrs → re-add `currentColor` fill/stroke so the icon themes with CSS color), tighten the
11
+ * `viewBox` to the real path bounds, and store the result as `svgString` for inline rendering.
12
+ *
13
+ * svgo + svg-path-bbox are imported dynamically so they never land in a frontend/edge bundle —
14
+ * this only runs server-side when an SVG is actually uploaded. On failure the raw upload is still
15
+ * stored (never optimized/inlined) and the `optimized` field carries the error so the doc shows it.
16
+ */
17
+ export declare const formatSvg: (icon: IconData, svgData: Buffer, logger: Payload["logger"]) => Promise<IconData>;
18
+ /** `beforeChange` hook: when an SVG file is uploaded (create or update), optimize + sanitize it
19
+ * and fold `svgString`/`optimized` into the doc. A no-op for changes that carry no new file. */
20
+ export declare const formatSVGHook: CollectionBeforeChangeHook;
21
+ export {};
22
+ //# sourceMappingURL=formatSVG.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatSVG.d.ts","sourceRoot":"","sources":["../../src/hooks/formatSVG.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAGlE,kDAAkD;AAClD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAuBvG;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,GAAU,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAE,QAAQ,OAAO,CAAC,QAAQ,CAAC,KAAG,OAAO,CAAC,QAAQ,CAgK5G,CAAA;AAED;iGACiG;AACjG,eAAO,MAAM,aAAa,EAAE,0BAY3B,CAAA"}