@swiftbrowser/web 0.1.0 → 0.2.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 (98) hide show
  1. package/README.md +43 -6
  2. package/app/index.html +11 -0
  3. package/node/dist/node/apps.d.ts +16 -0
  4. package/node/dist/node/apps.d.ts.map +1 -1
  5. package/node/dist/node/apps.js +9 -0
  6. package/node/dist/node/apps.js.map +1 -1
  7. package/node/dist/node/config.d.ts +14 -1
  8. package/node/dist/node/config.d.ts.map +1 -1
  9. package/node/dist/node/config.js +20 -3
  10. package/node/dist/node/config.js.map +1 -1
  11. package/node/dist/node/examples.d.ts +2 -1
  12. package/node/dist/node/examples.d.ts.map +1 -1
  13. package/node/dist/node/examples.js +11 -2
  14. package/node/dist/node/examples.js.map +1 -1
  15. package/node/dist/plugins/app-manifests.d.ts +4 -1
  16. package/node/dist/plugins/app-manifests.d.ts.map +1 -1
  17. package/node/dist/plugins/app-manifests.js +3 -2
  18. package/node/dist/plugins/app-manifests.js.map +1 -1
  19. package/node/dist/plugins/asset-catalogs.d.ts +15 -3
  20. package/node/dist/plugins/asset-catalogs.d.ts.map +1 -1
  21. package/node/dist/plugins/asset-catalogs.js +111 -13
  22. package/node/dist/plugins/asset-catalogs.js.map +1 -1
  23. package/node/dist/plugins/included-sites.d.ts +26 -0
  24. package/node/dist/plugins/included-sites.d.ts.map +1 -0
  25. package/node/dist/plugins/included-sites.js +70 -0
  26. package/node/dist/plugins/included-sites.js.map +1 -0
  27. package/node/dist/plugins/pdfImages.d.ts +27 -0
  28. package/node/dist/plugins/pdfImages.d.ts.map +1 -0
  29. package/node/dist/plugins/pdfImages.js +145 -0
  30. package/node/dist/plugins/pdfImages.js.map +1 -0
  31. package/node/dist/plugins/swift-wasm.d.ts +19 -1
  32. package/node/dist/plugins/swift-wasm.d.ts.map +1 -1
  33. package/node/dist/plugins/swift-wasm.js +45 -7
  34. package/node/dist/plugins/swift-wasm.js.map +1 -1
  35. package/node/dist/plugins/symbolTemplates.d.ts +22 -0
  36. package/node/dist/plugins/symbolTemplates.d.ts.map +1 -0
  37. package/node/dist/plugins/symbolTemplates.js +83 -0
  38. package/node/dist/plugins/symbolTemplates.js.map +1 -0
  39. package/package.json +4 -2
  40. package/plugins/app-manifests.ts +3 -2
  41. package/plugins/asset-catalogs.ts +119 -14
  42. package/plugins/included-sites.ts +74 -0
  43. package/plugins/pdfImages.ts +163 -0
  44. package/plugins/swift-wasm.ts +52 -6
  45. package/plugins/symbolTemplates.ts +88 -0
  46. package/public/_headers +7 -0
  47. package/public/app/oauth-callback.html +62 -0
  48. package/src/animation.ts +235 -8
  49. package/src/appFiles.ts +201 -0
  50. package/src/base64.ts +43 -0
  51. package/src/bitmapPlan.ts +143 -0
  52. package/src/bitmapStore.ts +206 -0
  53. package/src/bitmapWorker.ts +41 -0
  54. package/src/bitmapWorkerProtocol.ts +15 -0
  55. package/src/bitmaps.ts +283 -0
  56. package/src/blockedHosts.ts +29 -0
  57. package/src/canvasDrawing.ts +361 -0
  58. package/src/chartDom.ts +2 -2
  59. package/src/chromeColor.ts +179 -0
  60. package/src/clipboard.ts +78 -0
  61. package/src/colorMultiply.ts +93 -0
  62. package/src/colorPicker.ts +44 -0
  63. package/src/corsProxy.ts +45 -0
  64. package/src/gaugeRing.ts +74 -0
  65. package/src/gif.ts +297 -0
  66. package/src/hostRequests.ts +426 -0
  67. package/src/imageOps.ts +592 -0
  68. package/src/interaction.ts +18 -1
  69. package/src/landing.ts +2 -2
  70. package/src/layout/chart.ts +9 -3
  71. package/src/layout/engine.ts +279 -25
  72. package/src/layout/index.ts +3 -1
  73. package/src/layout/text.ts +217 -1
  74. package/src/layout/types.ts +31 -0
  75. package/src/layout/typography.ts +24 -7
  76. package/src/layout/video.ts +24 -0
  77. package/src/layoutDom.ts +53 -3
  78. package/src/main.ts +124 -4
  79. package/src/media.ts +132 -0
  80. package/src/mock.ts +2 -1
  81. package/src/notifications.ts +109 -0
  82. package/src/pathShape.ts +156 -0
  83. package/src/protocol.ts +761 -12
  84. package/src/renderer.ts +584 -36
  85. package/src/richText.ts +65 -0
  86. package/src/scanner.ts +234 -0
  87. package/src/scrollTo.ts +123 -0
  88. package/src/styles.css +212 -7
  89. package/src/styles.ts +31 -0
  90. package/src/swiftData.ts +128 -0
  91. package/src/symbols.ts +564 -21
  92. package/src/translation.ts +126 -0
  93. package/src/video.ts +299 -0
  94. package/src/vite-env.d.ts +6 -0
  95. package/src/wasm.ts +227 -32
  96. package/src/webAuth.ts +267 -0
  97. package/src/webSocket.ts +148 -0
  98. package/src/zoneinfo.ts +269 -0
package/src/symbols.ts CHANGED
@@ -14,9 +14,18 @@
14
14
 
15
15
  import {
16
16
  Accessibility,
17
+ Activity,
18
+ Airplay,
19
+ ALargeSmall,
17
20
  AlarmClock,
18
21
  Archive,
22
+ ArrowBigDown,
23
+ ArrowBigLeft,
24
+ ArrowBigRight,
25
+ ArrowBigUp,
19
26
  ArrowDown,
27
+ ArrowDownLeft,
28
+ ArrowDownRight,
20
29
  ArrowDownToLine,
21
30
  ArrowLeft,
22
31
  ArrowLeftRight,
@@ -24,35 +33,63 @@ import {
24
33
  ArrowUp,
25
34
  ArrowUpDown,
26
35
  ArrowUpFromLine,
36
+ ArrowUpLeft,
27
37
  ArrowUpRight,
28
38
  AtSign,
39
+ AudioWaveform,
40
+ Award,
41
+ BadgeCheck,
42
+ BadgeQuestionMark,
43
+ Ban,
44
+ Bandage,
45
+ Banknote,
46
+ Barcode,
29
47
  Battery,
48
+ BatteryFull,
49
+ BatteryLow,
50
+ BatteryMedium,
51
+ BatteryWarning,
52
+ BedDouble,
30
53
  Bell,
54
+ BellDot,
55
+ BellOff,
31
56
  Bike,
57
+ Bird,
58
+ Bitcoin,
32
59
  Bluetooth,
60
+ Bold,
33
61
  Book,
34
- BookOpen,
35
62
  Bookmark,
63
+ BookOpen,
64
+ Brain,
36
65
  Briefcase,
66
+ BriefcaseMedical,
37
67
  Bug,
38
68
  Building,
39
69
  Bus,
70
+ Cake,
40
71
  Calendar,
72
+ CalendarClock,
73
+ CalendarPlus,
74
+ CalendarX,
41
75
  Camera,
42
76
  Car,
77
+ Carrot,
78
+ Cat,
43
79
  ChartBar,
80
+ ChartColumn,
44
81
  ChartLine,
45
82
  ChartPie,
46
83
  Check,
47
84
  ChevronDown,
48
85
  ChevronLeft,
49
86
  ChevronRight,
50
- ChevronUp,
51
87
  ChevronsDown,
52
88
  ChevronsLeft,
53
89
  ChevronsRight,
54
90
  ChevronsUp,
55
91
  ChevronsUpDown,
92
+ ChevronUp,
56
93
  Circle,
57
94
  CircleAlert,
58
95
  CircleArrowDown,
@@ -60,152 +97,325 @@ import {
60
97
  CircleArrowRight,
61
98
  CircleArrowUp,
62
99
  CircleCheck,
100
+ CircleDollarSign,
63
101
  CircleDot,
64
102
  CircleEllipsis,
65
103
  CircleMinus,
66
104
  CirclePause,
67
105
  CirclePlay,
68
106
  CirclePlus,
69
- CircleStop,
70
107
  CircleQuestionMark,
108
+ CircleStop,
71
109
  CircleUser,
72
110
  CircleX,
111
+ Clapperboard,
73
112
  Clipboard,
113
+ ClipboardList,
74
114
  Clock,
115
+ ClockCheck,
75
116
  Cloud,
117
+ CloudDownload,
118
+ CloudDrizzle,
119
+ CloudFog,
120
+ CloudHail,
76
121
  CloudLightning,
77
122
  CloudMoon,
78
123
  CloudRain,
124
+ CloudRainWind,
79
125
  CloudSnow,
80
126
  CloudSun,
127
+ CloudUpload,
81
128
  Code,
129
+ Coffee,
82
130
  Cog,
131
+ Columns2,
132
+ Command,
83
133
  Compass,
134
+ Contact,
84
135
  Copy,
136
+ CornerDownLeft,
85
137
  CreditCard,
138
+ Crop,
139
+ Cross,
86
140
  Crown,
141
+ Database,
142
+ Delete,
143
+ Diamond,
144
+ Dices,
145
+ Dog,
146
+ DollarSign,
87
147
  Download,
88
148
  Droplet,
149
+ Droplets,
150
+ Dumbbell,
151
+ Earth,
89
152
  Ellipsis,
153
+ Euro,
90
154
  Eye,
91
155
  EyeOff,
92
156
  FaceSlightlySmiling,
93
157
  File,
158
+ FilePlus,
94
159
  FileText,
160
+ Film,
161
+ Fingerprint,
162
+ Fish,
95
163
  Flag,
96
164
  Flame,
97
165
  Folder,
166
+ FolderMinus,
167
+ FolderPlus,
168
+ Forward,
169
+ Fuel,
98
170
  Funnel,
171
+ GalleryVerticalEnd,
99
172
  Gamepad2,
173
+ Gauge,
100
174
  Gift,
175
+ GitBranch,
176
+ GitMerge,
177
+ Glasses,
101
178
  Globe,
102
179
  GraduationCap,
180
+ Grid3x3,
181
+ Hammer,
103
182
  Hand,
104
- Hourglass,
183
+ HardDrive,
184
+ Hash,
105
185
  Headphones,
106
186
  Heart,
187
+ HeartOff,
188
+ Hexagon,
189
+ Highlighter,
190
+ History,
191
+ Hourglass,
107
192
  House,
193
+ IdCard,
108
194
  Image,
195
+ Images,
109
196
  Inbox,
197
+ Infinity,
110
198
  Info,
199
+ Italic,
200
+ JapaneseYen,
111
201
  Key,
112
202
  Keyboard,
203
+ Landmark,
113
204
  Laptop,
205
+ Lasso,
206
+ Layers,
207
+ Layers3,
208
+ LayoutGrid,
209
+ LayoutList,
114
210
  Leaf,
211
+ Library,
115
212
  Lightbulb,
116
213
  Link,
214
+ Link2,
117
215
  List,
118
216
  ListChecks,
217
+ ListIndentIncrease,
218
+ ListMusic,
119
219
  ListOrdered,
120
220
  LoaderCircle,
221
+ LocateFixed,
121
222
  Lock,
122
223
  LockOpen,
123
224
  LogIn,
124
225
  LogOut,
125
226
  Mail,
227
+ MailOpen,
228
+ MailWarning,
126
229
  Map,
127
230
  MapPin,
231
+ MapPinOff,
232
+ Maximize2,
233
+ Medal,
128
234
  Menu,
129
235
  MessageCircle,
130
236
  MessageSquare,
237
+ MessageSquareMore,
238
+ MessageSquarePlus,
239
+ MessageSquareQuote,
240
+ MessageSquareText,
241
+ MessageSquareWarning,
242
+ MessagesSquare,
131
243
  Mic,
132
244
  MicOff,
245
+ MicVocal,
246
+ Minimize2,
133
247
  Minus,
134
248
  Monitor,
249
+ MonitorPlay,
135
250
  Moon,
251
+ Mountain,
136
252
  Music,
253
+ Navigation2,
254
+ Network,
255
+ Newspaper,
256
+ Octagon,
257
+ OctagonAlert,
258
+ OctagonX,
259
+ Option,
137
260
  Package,
261
+ Paintbrush,
262
+ Palette,
263
+ PanelLeft,
264
+ PanelRight,
138
265
  Paperclip,
139
266
  Pause,
267
+ PawPrint,
140
268
  Pencil,
269
+ PencilOff,
270
+ PenTool,
271
+ Percent,
272
+ PersonStanding,
141
273
  Phone,
274
+ PhoneIncoming,
275
+ PhoneOff,
276
+ PhoneOutgoing,
277
+ Pill,
142
278
  Pin,
279
+ Pipette,
143
280
  Plane,
144
281
  Play,
145
282
  Plus,
283
+ Pointer,
284
+ PoundSterling,
146
285
  Power,
147
286
  Printer,
287
+ Puzzle,
148
288
  QrCode,
289
+ Rabbit,
290
+ Radio,
291
+ RectangleHorizontal,
292
+ RectangleVertical,
293
+ Redo2,
149
294
  RefreshCw,
150
295
  Repeat,
296
+ Reply,
297
+ ReplyAll,
151
298
  RotateCcw,
152
299
  RotateCw,
300
+ Rows2,
301
+ Ruler,
302
+ Sailboat,
303
+ Scan,
304
+ ScanBarcode,
305
+ ScanFace,
306
+ ScanQrCode,
307
+ School,
308
+ Scissors,
153
309
  Search,
154
310
  Send,
311
+ Server,
155
312
  Settings,
156
313
  Share,
314
+ Share2,
157
315
  Shield,
158
316
  ShieldCheck,
317
+ Ship,
159
318
  ShoppingBag,
319
+ ShoppingBasket,
160
320
  ShoppingCart,
161
321
  Shuffle,
322
+ Sigma,
323
+ Signal,
324
+ Signpost,
162
325
  SkipBack,
163
326
  SkipForward,
164
327
  SlidersHorizontal,
165
328
  Smartphone,
329
+ Snowflake,
330
+ Sparkle,
166
331
  Sparkles,
167
332
  Speaker,
168
333
  Square,
334
+ SquareArrowDown,
335
+ SquareArrowLeft,
336
+ SquareArrowOutUpRight,
337
+ SquareArrowRight,
338
+ SquareArrowUp,
169
339
  SquareCheck,
340
+ SquareMinus,
341
+ SquareParking,
170
342
  SquarePen,
343
+ SquarePlay,
344
+ SquarePlus,
345
+ SquareUser,
346
+ SquareX,
171
347
  Star,
348
+ StarHalf,
349
+ StarOff,
350
+ Stethoscope,
351
+ StickyNote,
352
+ Store,
353
+ Strikethrough,
172
354
  Sun,
355
+ SunDim,
356
+ Sunrise,
357
+ Sunset,
358
+ SwitchCamera,
173
359
  Tag,
174
360
  Target,
361
+ Tent,
175
362
  Terminal,
176
- Timer,
363
+ TextAlignCenter,
364
+ TextAlignEnd,
365
+ TextAlignJustify,
366
+ TextAlignStart,
367
+ Thermometer,
368
+ ThumbsDown,
177
369
  ThumbsUp,
370
+ Ticket,
371
+ Timer,
372
+ Tornado,
373
+ TrainFront,
374
+ TramFront,
178
375
  Trash,
179
- TriangleAlert,
376
+ Trash2,
377
+ TreeDeciduous,
378
+ TrendingDown,
180
379
  TrendingUp,
380
+ Triangle,
381
+ TriangleAlert,
181
382
  Trophy,
383
+ Truck,
384
+ Turtle,
182
385
  Tv,
183
386
  Type,
387
+ Umbrella,
388
+ Underline,
389
+ Undo2,
184
390
  Upload,
185
391
  User,
392
+ UserCheck,
393
+ UserMinus,
394
+ UserPlus,
186
395
  Users,
396
+ UserX,
397
+ Utensils,
398
+ Video,
399
+ VideoOff,
187
400
  Volume,
188
401
  Volume1,
189
402
  Volume2,
190
403
  VolumeX,
191
404
  Wallet,
405
+ WandSparkles,
192
406
  Watch,
193
407
  Wifi,
408
+ WifiOff,
194
409
  Wind,
410
+ Wine,
195
411
  Wrench,
196
412
  X,
197
413
  Zap,
414
+ ZapOff,
198
415
  ZoomIn,
199
416
  ZoomOut,
200
417
  createElement,
201
418
  type IconNode,
202
- Grid3x3,
203
- LayoutGrid,
204
- LayoutList,
205
- MessageSquarePlus,
206
- MessageSquareText,
207
- Truck,
208
- Utensils,
209
419
  } from 'lucide';
210
420
 
211
421
  /** How a glyph is painted; see the file comment. */
@@ -549,17 +759,346 @@ export const SF_SYMBOLS: Readonly<Record<string, SymbolGlyph>> = {
549
759
  // Activity
550
760
  'rays': outline(LoaderCircle),
551
761
  'circle.dotted': outline(LoaderCircle),
762
+
763
+ // More common symbols: people, documents, arrows, text, shapes, money,
764
+ // health, travel, weather, nature, media, devices, tools.
765
+ 'bed.double': outline(BedDouble),
766
+ 'bed.double.fill': solid(BedDouble),
767
+ 'qrcode.viewfinder': outline(ScanQrCode),
768
+ barcode: outline(Barcode),
769
+ 'barcode.viewfinder': outline(ScanBarcode),
770
+ viewfinder: outline(Scan),
771
+ 'questionmark.diamond': outline(BadgeQuestionMark),
772
+ 'rectangle.on.rectangle': outline(Copy),
773
+ 'rectangle.on.rectangle.angled': outline(GalleryVerticalEnd),
774
+ 'person.badge.plus': outline(UserPlus),
775
+ 'person.badge.minus': outline(UserMinus),
776
+ 'person.crop.circle.badge.plus': outline(UserPlus),
777
+ 'person.crop.circle.badge.xmark': outline(UserX),
778
+ 'person.crop.circle.badge.checkmark': outline(UserCheck),
779
+ 'person.crop.circle.fill.badge.checkmark': outline(UserCheck),
780
+ 'person.crop.square': outline(SquareUser),
781
+ 'person.crop.square.fill': knockout(SquareUser),
782
+ 'person.2.fill': solid(Users),
783
+ 'person.2.circle': outline(Users),
784
+ 'person.text.rectangle': outline(IdCard),
785
+ 'person.crop.rectangle': outline(Contact),
786
+ 'folder.badge.plus': outline(FolderPlus),
787
+ 'folder.badge.minus': outline(FolderMinus),
788
+ 'doc.badge.plus': outline(FilePlus),
789
+ 'doc.on.doc.fill': outline(Copy),
790
+ 'calendar.badge.plus': outline(CalendarPlus),
791
+ 'calendar.badge.clock': outline(CalendarClock),
792
+ 'calendar.badge.exclamationmark': outline(CalendarX),
793
+ 'calendar.circle': outline(Calendar),
794
+ 'clock.arrow.circlepath': outline(History),
795
+ 'clock.badge.checkmark': outline(ClockCheck),
796
+ 'arrow.uturn.backward': outline(Undo2),
797
+ 'arrow.uturn.forward': outline(Redo2),
798
+ 'arrow.uturn.left': outline(Undo2),
799
+ 'arrow.uturn.right': outline(Redo2),
800
+ 'arrow.up.left.and.arrow.down.right': outline(Maximize2),
801
+ 'arrow.down.right.and.arrow.up.left': outline(Minimize2),
802
+ 'arrow.up.right.square': outline(SquareArrowOutUpRight),
803
+ 'arrow.up.forward.app': outline(SquareArrowOutUpRight),
804
+ 'arrow.right.square': outline(SquareArrowRight),
805
+ 'arrow.left.square': outline(SquareArrowLeft),
806
+ 'arrow.up.square': outline(SquareArrowUp),
807
+ 'arrow.down.square': outline(SquareArrowDown),
808
+ 'arrow.triangle.branch': outline(GitBranch),
809
+ 'arrow.triangle.merge': outline(GitMerge),
810
+ 'arrow.triangle.swap': outline(ArrowLeftRight),
811
+ 'arrow.up.and.down': outline(ArrowUpDown),
812
+ 'arrow.left.and.right': outline(ArrowLeftRight),
813
+ 'arrow.down.left': outline(ArrowDownLeft),
814
+ 'arrow.down.right': outline(ArrowDownRight),
815
+ 'arrow.up.left': outline(ArrowUpLeft),
816
+ 'arrowshape.turn.up.left': outline(Reply),
817
+ 'arrowshape.turn.up.right': outline(Forward),
818
+ 'arrowshape.turn.up.left.2': outline(ReplyAll),
819
+ 'arrowshape.left': outline(ArrowBigLeft),
820
+ 'arrowshape.right': outline(ArrowBigRight),
821
+ 'arrowshape.up': outline(ArrowBigUp),
822
+ 'arrowshape.down': outline(ArrowBigDown),
823
+ 'square.on.square': outline(Copy),
824
+ 'plus.square': outline(SquarePlus),
825
+ 'plus.square.fill': knockout(SquarePlus),
826
+ 'minus.square': outline(SquareMinus),
827
+ 'minus.square.fill': knockout(SquareMinus),
828
+ 'xmark.square': outline(SquareX),
829
+ 'xmark.square.fill': knockout(SquareX),
830
+ 'plus.app': outline(SquarePlus),
831
+ 'star.circle': outline(Star),
832
+ 'star.leadinghalf.filled': outline(StarHalf),
833
+ 'star.slash': outline(StarOff),
834
+ 'heart.slash': outline(HeartOff),
835
+ 'heart.circle': outline(Heart),
836
+ 'bell.slash': outline(BellOff),
837
+ 'bell.badge': outline(BellDot),
838
+ 'bell.badge.fill': outline(BellDot),
839
+ 'envelope.badge': outline(MailWarning),
840
+ 'envelope.open.fill': outline(MailOpen),
841
+ 'tray.full': outline(Inbox),
842
+ 'tray.fill': solid(Inbox),
843
+ 'tray.and.arrow.down': outline(Inbox),
844
+ 'tray.and.arrow.up': outline(Inbox),
845
+ 'phone.arrow.up.right': outline(PhoneOutgoing),
846
+ 'phone.arrow.down.left': outline(PhoneIncoming),
847
+ 'phone.down': outline(PhoneOff),
848
+ video: outline(Video),
849
+ 'video.fill': solid(Video),
850
+ 'video.slash': outline(VideoOff),
851
+ 'bubble.left.and.bubble.right': outline(MessagesSquare),
852
+ 'bubble.left.and.bubble.right.fill': outline(MessagesSquare),
853
+ 'bubble.right': outline(MessageSquare),
854
+ 'bubble.left.fill': solid(MessageSquare),
855
+ 'quote.bubble': outline(MessageSquareQuote),
856
+ 'ellipsis.bubble': outline(MessageSquareMore),
857
+ 'exclamationmark.bubble': outline(MessageSquareWarning),
858
+ 'text.alignleft': outline(TextAlignStart),
859
+ 'text.aligncenter': outline(TextAlignCenter),
860
+ 'text.alignright': outline(TextAlignEnd),
861
+ 'text.justify': outline(TextAlignJustify),
862
+ bold: outline(Bold),
863
+ italic: outline(Italic),
864
+ underline: outline(Underline),
865
+ strikethrough: outline(Strikethrough),
866
+ 'textformat.size': outline(ALargeSmall),
867
+ character: outline(Type),
868
+ 'list.dash': outline(List),
869
+ 'list.bullet.indent': outline(ListIndentIncrease),
870
+ 'list.clipboard': outline(ClipboardList),
871
+ 'square.grid.3x3': outline(Grid3x3),
872
+ 'square.grid.2x2.fill': solid(LayoutGrid),
873
+ 'rectangle.grid.1x2': outline(Rows2),
874
+ 'rectangle.split.2x1': outline(Columns2),
875
+ 'sidebar.left': outline(PanelLeft),
876
+ 'sidebar.right': outline(PanelRight),
877
+ 'rectangle.stack': outline(Layers),
878
+ 'square.stack': outline(Layers),
879
+ 'square.stack.3d.up': outline(Layers3),
880
+ rectangle: outline(RectangleHorizontal),
881
+ 'rectangle.fill': solid(RectangleHorizontal),
882
+ 'rectangle.portrait': outline(RectangleVertical),
883
+ triangle: outline(Triangle),
884
+ 'triangle.fill': solid(Triangle),
885
+ diamond: outline(Diamond),
886
+ 'diamond.fill': solid(Diamond),
887
+ hexagon: outline(Hexagon),
888
+ 'hexagon.fill': solid(Hexagon),
889
+ octagon: outline(Octagon),
890
+ 'checkmark.seal': outline(BadgeCheck),
891
+ 'checkmark.seal.fill': knockout(BadgeCheck),
892
+ 'xmark.octagon': outline(OctagonX),
893
+ 'xmark.octagon.fill': outline(OctagonX),
894
+ 'exclamationmark.octagon': outline(OctagonAlert),
895
+ nosign: outline(Ban),
896
+ 'slash.circle': outline(Ban),
897
+ number: outline(Hash),
898
+ percent: outline(Percent),
899
+ dollarsign: outline(DollarSign),
900
+ 'dollarsign.circle': outline(CircleDollarSign),
901
+ 'dollarsign.circle.fill': knockout(CircleDollarSign),
902
+ eurosign: outline(Euro),
903
+ sterlingsign: outline(PoundSterling),
904
+ yensign: outline(JapaneseYen),
905
+ bitcoinsign: outline(Bitcoin),
906
+ banknote: outline(Banknote),
907
+ basket: outline(ShoppingBasket),
908
+ storefront: outline(Store),
909
+ 'building.columns': outline(Landmark),
910
+ ticket: outline(Ticket),
911
+ 'chart.bar.fill': outline(ChartBar),
912
+ 'chart.bar.xaxis': outline(ChartColumn),
913
+ 'chart.line.downtrend.xyaxis': outline(TrendingDown),
914
+ waveform: outline(AudioWaveform),
915
+ 'waveform.path.ecg': outline(Activity),
916
+ cross: outline(Cross),
917
+ 'cross.case': outline(BriefcaseMedical),
918
+ pills: outline(Pill),
919
+ bandage: outline(Bandage),
920
+ stethoscope: outline(Stethoscope),
921
+ brain: outline(Brain),
922
+ 'brain.head.profile': outline(Brain),
923
+ 'figure.stand': outline(PersonStanding),
924
+ dumbbell: outline(Dumbbell),
925
+ tram: outline(TramFront),
926
+ 'train.side.front.car': outline(TrainFront),
927
+ ferry: outline(Ship),
928
+ sailboat: outline(Sailboat),
929
+ fuelpump: outline(Fuel),
930
+ parkingsign: outline(SquareParking),
931
+ tent: outline(Tent),
932
+ 'mountain.2': outline(Mountain),
933
+ tree: outline(TreeDeciduous),
934
+ thermometer: outline(Thermometer),
935
+ 'thermometer.medium': outline(Thermometer),
936
+ umbrella: outline(Umbrella),
937
+ snowflake: outline(Snowflake),
938
+ 'sun.min': outline(SunDim),
939
+ sunrise: outline(Sunrise),
940
+ sunset: outline(Sunset),
941
+ 'cloud.drizzle': outline(CloudDrizzle),
942
+ 'cloud.fog': outline(CloudFog),
943
+ 'cloud.heavyrain': outline(CloudRainWind),
944
+ 'cloud.hail': outline(CloudHail),
945
+ tornado: outline(Tornado),
946
+ humidity: outline(Droplets),
947
+ pawprint: outline(PawPrint),
948
+ hare: outline(Rabbit),
949
+ tortoise: outline(Turtle),
950
+ fish: outline(Fish),
951
+ bird: outline(Bird),
952
+ cat: outline(Cat),
953
+ dog: outline(Dog),
954
+ carrot: outline(Carrot),
955
+ 'cup.and.saucer': outline(Coffee),
956
+ mug: outline(Coffee),
957
+ wineglass: outline(Wine),
958
+ 'birthday.cake': outline(Cake),
959
+ film: outline(Film),
960
+ 'film.stack': outline(Clapperboard),
961
+ 'camera.rotate': outline(SwitchCamera),
962
+ 'photo.stack': outline(Images),
963
+ 'photo.on.rectangle.angled': outline(Images),
964
+ 'music.note.list': outline(ListMusic),
965
+ 'music.mic': outline(MicVocal),
966
+ radio: outline(Radio),
967
+ airplayaudio: outline(Airplay),
968
+ airplayvideo: outline(Airplay),
969
+ 'play.rectangle': outline(MonitorPlay),
970
+ 'play.square': outline(SquarePlay),
971
+ icloud: outline(Cloud),
972
+ 'icloud.fill': solid(Cloud),
973
+ 'icloud.and.arrow.up': outline(CloudUpload),
974
+ 'icloud.and.arrow.down': outline(CloudDownload),
975
+ externaldrive: outline(HardDrive),
976
+ 'server.rack': outline(Server),
977
+ cylinder: outline(Database),
978
+ network: outline(Network),
979
+ faceid: outline(ScanFace),
980
+ touchid: outline(Fingerprint),
981
+ 'lock.shield': outline(ShieldCheck),
982
+ 'hand.tap': outline(Pointer),
983
+ 'hand.wave': outline(Hand),
984
+ 'hand.thumbsdown': outline(ThumbsDown),
985
+ 'hand.thumbsdown.fill': solid(ThumbsDown),
986
+ eyeglasses: outline(Glasses),
987
+ sparkle: outline(Sparkle),
988
+ 'wand.and.stars': outline(WandSparkles),
989
+ paintbrush: outline(Paintbrush),
990
+ paintpalette: outline(Palette),
991
+ 'pencil.tip': outline(PenTool),
992
+ 'pencil.slash': outline(PencilOff),
993
+ highlighter: outline(Highlighter),
994
+ scissors: outline(Scissors),
995
+ ruler: outline(Ruler),
996
+ eyedropper: outline(Pipette),
997
+ lasso: outline(Lasso),
998
+ crop: outline(Crop),
999
+ gauge: outline(Gauge),
1000
+ speedometer: outline(Gauge),
1001
+ hammer: outline(Hammer),
1002
+ puzzlepiece: outline(Puzzle),
1003
+ dice: outline(Dices),
1004
+ newspaper: outline(Newspaper),
1005
+ 'books.vertical': outline(Library),
1006
+ 'note.text': outline(StickyNote),
1007
+ note: outline(StickyNote),
1008
+ 'location.circle': outline(LocateFixed),
1009
+ 'location.north': outline(Navigation2),
1010
+ 'location.slash': outline(MapPinOff),
1011
+ 'signpost.right': outline(Signpost),
1012
+ 'globe.americas': outline(Earth),
1013
+ 'globe.europe.africa': outline(Earth),
1014
+ 'bolt.slash': outline(ZapOff),
1015
+ 'battery.25': outline(BatteryLow),
1016
+ 'battery.50': outline(BatteryMedium),
1017
+ 'battery.75': outline(BatteryFull),
1018
+ 'battery.0': outline(BatteryWarning),
1019
+ 'wifi.slash': outline(WifiOff),
1020
+ cellularbars: outline(Signal),
1021
+ infinity: outline(Infinity),
1022
+ sum: outline(Sigma),
1023
+ command: outline(Command),
1024
+ option: outline(Option),
1025
+ 'delete.left': outline(Delete),
1026
+ return: outline(CornerDownLeft),
1027
+ 'xmark.bin': outline(Trash2),
1028
+ 'square.and.arrow.up.on.square': outline(Share2),
1029
+ 'link.badge.plus': outline(Link2),
1030
+ 'shippingbox.circle': outline(Package),
1031
+ 'graduationcap.fill': solid(GraduationCap),
1032
+ medal: outline(Medal),
1033
+ rosette: outline(Award),
1034
+ 'gift.circle': outline(Gift),
1035
+ studentdesk: outline(School),
552
1036
  };
553
1037
 
554
- /** Number of SF Symbol names the renderer can draw. */
1038
+ /** Number of SF Symbol names the map lists (more resolve as variants, see `lookupSymbol`). */
555
1039
  export const SF_SYMBOL_COUNT = Object.keys(SF_SYMBOLS).length;
556
1040
 
557
1041
  export function lookupSymbol(systemName: string): SymbolGlyph | undefined {
558
- return SF_SYMBOLS[systemName];
1042
+ const exact = SF_SYMBOLS[systemName];
1043
+ if (exact) return exact;
1044
+ if (!(systemName in variants)) variants[systemName] = resolveVariant(systemName) ?? null;
1045
+ return variants[systemName] ?? undefined;
1046
+ }
1047
+
1048
+ /** Resolved variants (null: none); an object because lucide's `Map` icon shadows the global. */
1049
+ const variants: Record<string, SymbolGlyph | null> = Object.create(null);
1050
+
1051
+ /** Shapes that alone would stand in for too much (`circle.grid.2x2` is not a circle). */
1052
+ const GENERIC_SHAPES = new Set(['circle', 'square', 'rectangle', 'app', 'capsule', 'triangle', 'diamond', 'hexagon', 'octagon', 'seal', 'shield']);
1053
+
1054
+ /**
1055
+ * A name the map does not list is drawn as the closest listed one: SF Symbol
1056
+ * names extend a base with modifiers, so `person.crop.circle.badge.xmark`
1057
+ * is drawn as `person.crop.circle`, `trash.circle.fill` as `trash.fill` and
1058
+ * `speaker.wave.2.fill` as `speaker.wave.2`. A `.badge…` suffix is dropped,
1059
+ * then trailing parts one at a time; a name with `.fill` tries every filled
1060
+ * form first. A `.slash` variant is never drawn as its base, which would
1061
+ * mean the opposite (`bell.slash` is "notifications off"); nor is a name
1062
+ * drawn as a bare shape. Unresolved names get the caller's placeholder.
1063
+ */
1064
+ function resolveVariant(systemName: string): SymbolGlyph | undefined {
1065
+ let parts = systemName.split('.');
1066
+ if (parts.includes('slash')) return undefined;
1067
+ const fill = parts.includes('fill');
1068
+ parts = parts.filter((part) => part !== 'fill');
1069
+ const badge = parts.indexOf('badge');
1070
+ if (badge > 0) parts = parts.slice(0, badge);
1071
+ const bases: string[] = [];
1072
+ for (let length = parts.length; length > 0; length--) {
1073
+ const base = parts.slice(0, length).join('.');
1074
+ if (length === 1 && parts.length > 1 && GENERIC_SHAPES.has(base)) break;
1075
+ bases.push(base);
1076
+ }
1077
+ // A filled form at any length before an outline: `heart.circle.fill` is
1078
+ // closer to `heart.fill` than to `heart.circle`.
1079
+ const candidates = fill ? [...bases.map((base) => `${base}.fill`), ...bases] : bases;
1080
+ for (const name of candidates) {
1081
+ const glyph = SF_SYMBOLS[name];
1082
+ if (glyph) return glyph;
1083
+ }
1084
+ return undefined;
559
1085
  }
560
1086
 
561
1087
  const SVG_NS = 'http://www.w3.org/2000/svg';
562
1088
 
1089
+ /**
1090
+ * The shape a `knockout` glyph fills: the enclosing circle or rectangle
1091
+ * (lucide lists it first in most glyphs but not all: `CirclePlay` starts
1092
+ * with its triangle), else the first shape.
1093
+ */
1094
+ export function outerShapeIndex(icon: IconNode): number {
1095
+ const index = icon.findIndex(([tag, attrs]) => {
1096
+ const n = (key: string): number => Number(attrs[key] ?? 0);
1097
+ return (tag === 'circle' && n('r') >= 9) || (tag === 'rect' && n('width') >= 16 && n('height') >= 12);
1098
+ });
1099
+ return index >= 0 ? index : 0;
1100
+ }
1101
+
563
1102
  /** Color used for inner marks of `knockout` glyphs; styles.css sets the variable. */
564
1103
  const KNOCKOUT_COLOR = 'var(--sb-icon-knockout, var(--sb-color-system-background, #fff))';
565
1104
 
@@ -584,12 +1123,16 @@ export function renderSymbol(systemName: string): SVGElement | null {
584
1123
  shape.setAttribute('fill', 'currentColor');
585
1124
  }
586
1125
  } else if (glyph.fill === 'knockout') {
587
- const [outer, ...inner] = Array.from(svg.children);
588
- outer?.setAttribute('fill', 'currentColor');
589
- for (const mark of inner) {
590
- mark.setAttribute('stroke', KNOCKOUT_COLOR);
591
- mark.setAttribute('fill', 'none');
592
- }
1126
+ const shapes = Array.from(svg.children);
1127
+ const outer = outerShapeIndex(glyph.icon);
1128
+ shapes.forEach((shape, index) => {
1129
+ if (index === outer) {
1130
+ shape.setAttribute('fill', 'currentColor');
1131
+ } else {
1132
+ shape.setAttribute('stroke', KNOCKOUT_COLOR);
1133
+ shape.setAttribute('fill', 'none');
1134
+ }
1135
+ });
593
1136
  }
594
1137
  return svg;
595
1138
  }