diff --git a/Cargo.lock b/Cargo.lock
index bc586381c2eb82c09b1a7a82a56d99b96c302c5e..029f9e5ce2dbe1e0cde225ca687440b1428ca710 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1419,8 +1419,10 @@ dependencies = [
"serde_derive",
"settings",
"theme",
+ "theme_selector",
"util",
"workspace",
+ "zed-actions",
]
[[package]]
@@ -9017,6 +9019,14 @@ dependencies = [
"vim",
"welcome",
"workspace",
+ "zed-actions",
+]
+
+[[package]]
+name = "zed-actions"
+version = "0.1.0"
+dependencies = [
+ "gpui",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 640384a79272fdd14df6291dcd076bbba7a18dd7..3f3953096eda1e0e05dad60b3507b1c0a0843295 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -67,6 +67,7 @@ members = [
"crates/welcome",
"crates/xtask",
"crates/zed",
+ "crates/zed-actions"
]
default-members = ["crates/zed"]
resolver = "2"
diff --git a/assets/icons/radix/accessibility.svg b/assets/icons/radix/accessibility.svg
new file mode 100644
index 0000000000000000000000000000000000000000..32d78f2d8da1c317727810706a892a63f588463e
--- /dev/null
+++ b/assets/icons/radix/accessibility.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/activity-log.svg b/assets/icons/radix/activity-log.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8feab7d44942915ef6d49602e272b03125ee8ea4
--- /dev/null
+++ b/assets/icons/radix/activity-log.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-baseline.svg b/assets/icons/radix/align-baseline.svg
new file mode 100644
index 0000000000000000000000000000000000000000..07213dc1ae61fbf49d3f72b107082b07892fa0c1
--- /dev/null
+++ b/assets/icons/radix/align-baseline.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-bottom.svg b/assets/icons/radix/align-bottom.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7d11c0cd5a6e11be048bcfc04c782fcd3e61f2ee
--- /dev/null
+++ b/assets/icons/radix/align-bottom.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-center-horizontally.svg b/assets/icons/radix/align-center-horizontally.svg
new file mode 100644
index 0000000000000000000000000000000000000000..69509a7d097821d2c0169ae468efc8d74a7e90c9
--- /dev/null
+++ b/assets/icons/radix/align-center-horizontally.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-center-vertically.svg b/assets/icons/radix/align-center-vertically.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4f1b50cc4366775a792bef2b4475ec864856a3a7
--- /dev/null
+++ b/assets/icons/radix/align-center-vertically.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-center.svg b/assets/icons/radix/align-center.svg
new file mode 100644
index 0000000000000000000000000000000000000000..caaec36477fbbf2bcfef558aa682092d0bbd9a01
--- /dev/null
+++ b/assets/icons/radix/align-center.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-end.svg b/assets/icons/radix/align-end.svg
new file mode 100644
index 0000000000000000000000000000000000000000..18f1b6491233806086baf55ab67c5d7f4e10ff54
--- /dev/null
+++ b/assets/icons/radix/align-end.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-horizontal-centers.svg b/assets/icons/radix/align-horizontal-centers.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2d1d64ea4b82ef5e0d933b9bf0ec439c9998dd98
--- /dev/null
+++ b/assets/icons/radix/align-horizontal-centers.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-left.svg b/assets/icons/radix/align-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0d5dba095c7d0756d489d415276064a91d4fd3ce
--- /dev/null
+++ b/assets/icons/radix/align-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-right.svg b/assets/icons/radix/align-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1b6b3f0ffa9c649b005739baafa9d973013af076
--- /dev/null
+++ b/assets/icons/radix/align-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-start.svg b/assets/icons/radix/align-start.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ada50e1079e481cde5f0f9ee5884a7030ebb0bc6
--- /dev/null
+++ b/assets/icons/radix/align-start.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-stretch.svg b/assets/icons/radix/align-stretch.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3cb28605cbf1b1a8470fabd1257370d74b3e5682
--- /dev/null
+++ b/assets/icons/radix/align-stretch.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-top.svg b/assets/icons/radix/align-top.svg
new file mode 100644
index 0000000000000000000000000000000000000000..23db80f4dd0ebb04ee703fe74d4b535abbd01da1
--- /dev/null
+++ b/assets/icons/radix/align-top.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/align-vertical-centers.svg b/assets/icons/radix/align-vertical-centers.svg
new file mode 100644
index 0000000000000000000000000000000000000000..07eaee7bf7d9274c402bb3f4bfaa0dea486eb09b
--- /dev/null
+++ b/assets/icons/radix/align-vertical-centers.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/all-sides.svg b/assets/icons/radix/all-sides.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8ace7df03f4d17ba1e8f858b94d418eb63618ea6
--- /dev/null
+++ b/assets/icons/radix/all-sides.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/angle.svg b/assets/icons/radix/angle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a0d93f3460ca940a1bf5e7ad94c46f56d40ccc7b
--- /dev/null
+++ b/assets/icons/radix/angle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/archive.svg b/assets/icons/radix/archive.svg
new file mode 100644
index 0000000000000000000000000000000000000000..74063f1d1e2346c09ee2a6a5297c30ef7e0c74ad
--- /dev/null
+++ b/assets/icons/radix/archive.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-bottom-left.svg b/assets/icons/radix/arrow-bottom-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7a4511aa2d69b39c305cd80c291c868007cba491
--- /dev/null
+++ b/assets/icons/radix/arrow-bottom-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-bottom-right.svg b/assets/icons/radix/arrow-bottom-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2ba9fef1019774f1e5094f5654d89df848cdbb5b
--- /dev/null
+++ b/assets/icons/radix/arrow-bottom-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-down.svg b/assets/icons/radix/arrow-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5dc21a66890fb27f537b4400e96d48b7f7ce84a6
--- /dev/null
+++ b/assets/icons/radix/arrow-down.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-left.svg b/assets/icons/radix/arrow-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3a64c8394f0825b3708634c2d003a648877c35cd
--- /dev/null
+++ b/assets/icons/radix/arrow-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-right.svg b/assets/icons/radix/arrow-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e3d30988d5e7b4547393281c7bdad60c3006f4f3
--- /dev/null
+++ b/assets/icons/radix/arrow-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-top-left.svg b/assets/icons/radix/arrow-top-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..69fef41dee621d3f8cf681e630c0ce623d65124d
--- /dev/null
+++ b/assets/icons/radix/arrow-top-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-top-right.svg b/assets/icons/radix/arrow-top-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c1016376e3232ead02dde954379ce74b7bfb68f7
--- /dev/null
+++ b/assets/icons/radix/arrow-top-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/arrow-up.svg b/assets/icons/radix/arrow-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ba426119e901d0a1132d0e47b34c0beebaec22ce
--- /dev/null
+++ b/assets/icons/radix/arrow-up.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/aspect-ratio.svg b/assets/icons/radix/aspect-ratio.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0851f2e1e9f46d52cd2974b77a65e3a8b95b339e
--- /dev/null
+++ b/assets/icons/radix/aspect-ratio.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/avatar.svg b/assets/icons/radix/avatar.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cb229c77fe827f64054b6bfa05f2ad2aaf17c2d3
--- /dev/null
+++ b/assets/icons/radix/avatar.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/backpack.svg b/assets/icons/radix/backpack.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a5c9cedbd32dd589c825852f447e8c6125c2a8fb
--- /dev/null
+++ b/assets/icons/radix/backpack.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/badge.svg b/assets/icons/radix/badge.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aa764d4726f449c163b00e1bd993d12c5aa95c24
--- /dev/null
+++ b/assets/icons/radix/badge.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/bar-chart.svg b/assets/icons/radix/bar-chart.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f8054781d9ec2ee79f0652ae20753e3e80752bff
--- /dev/null
+++ b/assets/icons/radix/bar-chart.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/bell.svg b/assets/icons/radix/bell.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ea1c6dd42e8821b632f6de97d143a7b9f4b97fd2
--- /dev/null
+++ b/assets/icons/radix/bell.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/blending-mode.svg b/assets/icons/radix/blending-mode.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bd58cf4ee38ee66e9860df11a9f4150899a9c8a8
--- /dev/null
+++ b/assets/icons/radix/blending-mode.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/bookmark-filled.svg b/assets/icons/radix/bookmark-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5b725cd88dbf9337d52095a7567a2bc12e15439a
--- /dev/null
+++ b/assets/icons/radix/bookmark-filled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/bookmark.svg b/assets/icons/radix/bookmark.svg
new file mode 100644
index 0000000000000000000000000000000000000000..90c4d827f13cd47a83a030c833a02e15492dc084
--- /dev/null
+++ b/assets/icons/radix/bookmark.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/border-all.svg b/assets/icons/radix/border-all.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3bfde7d59baa675eeae72eac6f7245eadbe10821
--- /dev/null
+++ b/assets/icons/radix/border-all.svg
@@ -0,0 +1,17 @@
+
diff --git a/assets/icons/radix/border-bottom.svg b/assets/icons/radix/border-bottom.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f2d3c3d554e09837c464ff425c3af74413db4eb6
--- /dev/null
+++ b/assets/icons/radix/border-bottom.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/icons/radix/border-dashed.svg b/assets/icons/radix/border-dashed.svg
new file mode 100644
index 0000000000000000000000000000000000000000..85fdcdfe5d7f3905f2056912a5bc56d229ca5ee0
--- /dev/null
+++ b/assets/icons/radix/border-dashed.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/border-dotted.svg b/assets/icons/radix/border-dotted.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5eb514ed2a60093e0c4eb904b4cc5c6d18b9a62f
--- /dev/null
+++ b/assets/icons/radix/border-dotted.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/border-left.svg b/assets/icons/radix/border-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5deb197da51a7db874b57e1a473d4287b2a3cd49
--- /dev/null
+++ b/assets/icons/radix/border-left.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/icons/radix/border-none.svg b/assets/icons/radix/border-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1ad3f59d7c9b93101657ad1523a2939d02f504d8
--- /dev/null
+++ b/assets/icons/radix/border-none.svg
@@ -0,0 +1,35 @@
+
diff --git a/assets/icons/radix/border-right.svg b/assets/icons/radix/border-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c939095ad78a75eeb5f8b2e31f57e56b201b8a4c
--- /dev/null
+++ b/assets/icons/radix/border-right.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/icons/radix/border-solid.svg b/assets/icons/radix/border-solid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5c0d26a0583140b8ba0b47e937bc0dedc81e4fb5
--- /dev/null
+++ b/assets/icons/radix/border-solid.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/border-split.svg b/assets/icons/radix/border-split.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7fdf6cc34e73e6543fa34e9b52e22382130d6f1a
--- /dev/null
+++ b/assets/icons/radix/border-split.svg
@@ -0,0 +1,21 @@
+
diff --git a/assets/icons/radix/border-style.svg b/assets/icons/radix/border-style.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f729cb993babfa12140deabc9451eceee6b7885a
--- /dev/null
+++ b/assets/icons/radix/border-style.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/border-top.svg b/assets/icons/radix/border-top.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bde739d75539be17496a8ce65b875b4f4b943940
--- /dev/null
+++ b/assets/icons/radix/border-top.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/icons/radix/border-width.svg b/assets/icons/radix/border-width.svg
new file mode 100644
index 0000000000000000000000000000000000000000..37c270756ec4ec5a8a42b81b64bfbbe8e24f892a
--- /dev/null
+++ b/assets/icons/radix/border-width.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/box-model.svg b/assets/icons/radix/box-model.svg
new file mode 100644
index 0000000000000000000000000000000000000000..45d1a7ce415aa508a8a8f8d39f8032a22c2b4e5a
--- /dev/null
+++ b/assets/icons/radix/box-model.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/box.svg b/assets/icons/radix/box.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6e035c21ed8fd3ad1eca7297921da359262e8445
--- /dev/null
+++ b/assets/icons/radix/box.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/button.svg b/assets/icons/radix/button.svg
new file mode 100644
index 0000000000000000000000000000000000000000..31622bcf159a83dbf7dbc7960da3c490711a14ff
--- /dev/null
+++ b/assets/icons/radix/button.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/calendar.svg b/assets/icons/radix/calendar.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2adbe0bc2868392e36079a5860ddf706543b210e
--- /dev/null
+++ b/assets/icons/radix/calendar.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/camera.svg b/assets/icons/radix/camera.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d7cccf74c2e416dd8abcd45be121f73eccea3c12
--- /dev/null
+++ b/assets/icons/radix/camera.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/card-stack-minus.svg b/assets/icons/radix/card-stack-minus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..04d8e51178a0a8ea38a5354aa421e20bd4091298
--- /dev/null
+++ b/assets/icons/radix/card-stack-minus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/card-stack-plus.svg b/assets/icons/radix/card-stack-plus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a184f4bc1aff9b3b212fc3cce7265cf58bba3948
--- /dev/null
+++ b/assets/icons/radix/card-stack-plus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/card-stack.svg b/assets/icons/radix/card-stack.svg
new file mode 100644
index 0000000000000000000000000000000000000000..defea0e1654f9267fa91a8b66e2bf1191b95aadd
--- /dev/null
+++ b/assets/icons/radix/card-stack.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/caret-down.svg b/assets/icons/radix/caret-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ff8b8c3b88b8885b52a090eeca3f21526bb0a456
--- /dev/null
+++ b/assets/icons/radix/caret-down.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/caret-left.svg b/assets/icons/radix/caret-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..969bc3b95c2194b922c1858ddf89b5d2461f11d3
--- /dev/null
+++ b/assets/icons/radix/caret-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/caret-right.svg b/assets/icons/radix/caret-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..75c55d8676eebdc09961d63b870e12fc0a91c5c5
--- /dev/null
+++ b/assets/icons/radix/caret-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/caret-sort.svg b/assets/icons/radix/caret-sort.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a65e20b660481333e4e27e32203c9a5d12a5f150
--- /dev/null
+++ b/assets/icons/radix/caret-sort.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/caret-up.svg b/assets/icons/radix/caret-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..53026b83d8b36505b4b0f32c6e6d4a4c690c7beb
--- /dev/null
+++ b/assets/icons/radix/caret-up.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/chat-bubble.svg b/assets/icons/radix/chat-bubble.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5766f46de868ad91fc0ff057691a7dea474a0dae
--- /dev/null
+++ b/assets/icons/radix/chat-bubble.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/check-circled.svg b/assets/icons/radix/check-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..19ee22eb511b987dd3acfc5c7c833d6561a4662d
--- /dev/null
+++ b/assets/icons/radix/check-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/check.svg b/assets/icons/radix/check.svg
new file mode 100644
index 0000000000000000000000000000000000000000..476a3baa18e42bb05edfd7ec0c3a2aef155cc003
--- /dev/null
+++ b/assets/icons/radix/check.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/checkbox.svg b/assets/icons/radix/checkbox.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d6bb3c7ef2f0e97b823bffb1d4ea1edd38609da9
--- /dev/null
+++ b/assets/icons/radix/checkbox.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/chevron-down.svg b/assets/icons/radix/chevron-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..175c1312fd37417cba0bbcd9230b4dffa24821e4
--- /dev/null
+++ b/assets/icons/radix/chevron-down.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/chevron-left.svg b/assets/icons/radix/chevron-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d7628202f29edf1642deb44bf93ff540aa728475
--- /dev/null
+++ b/assets/icons/radix/chevron-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/chevron-right.svg b/assets/icons/radix/chevron-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e3ebd73d9909a53e3fb721f2ea686f1dca0b477b
--- /dev/null
+++ b/assets/icons/radix/chevron-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/chevron-up.svg b/assets/icons/radix/chevron-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0e8e796dab46c9de345166aa4dba818305b68857
--- /dev/null
+++ b/assets/icons/radix/chevron-up.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/circle-backslash.svg b/assets/icons/radix/circle-backslash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..40c4dd5398b454220d4d22dbbec08bcdb335be71
--- /dev/null
+++ b/assets/icons/radix/circle-backslash.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/circle.svg b/assets/icons/radix/circle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ba4a8f22fe574008e076c7983dfc5f743d03f2df
--- /dev/null
+++ b/assets/icons/radix/circle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/clipboard-copy.svg b/assets/icons/radix/clipboard-copy.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5293fdc493f5577936977562c9457bbfa809f012
--- /dev/null
+++ b/assets/icons/radix/clipboard-copy.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/clipboard.svg b/assets/icons/radix/clipboard.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e18b32943be09aca0c53294e8e65187564ba1224
--- /dev/null
+++ b/assets/icons/radix/clipboard.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/clock.svg b/assets/icons/radix/clock.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ac3b526fbbda03c5984d7c9dfaf937be520910a2
--- /dev/null
+++ b/assets/icons/radix/clock.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/code.svg b/assets/icons/radix/code.svg
new file mode 100644
index 0000000000000000000000000000000000000000..70fe381b68c5b95065275b5163af76dabaa5b22e
--- /dev/null
+++ b/assets/icons/radix/code.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/codesandbox-logo.svg b/assets/icons/radix/codesandbox-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4a3f549c2f6d7271e9a8fb225e18285d90312df8
--- /dev/null
+++ b/assets/icons/radix/codesandbox-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/color-wheel.svg b/assets/icons/radix/color-wheel.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2153b84428f354843aa7ffd3be174680440be90c
--- /dev/null
+++ b/assets/icons/radix/color-wheel.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/column-spacing.svg b/assets/icons/radix/column-spacing.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aafcf555cb1ca06550c39419d20c257b02ea1934
--- /dev/null
+++ b/assets/icons/radix/column-spacing.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/columns.svg b/assets/icons/radix/columns.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e1607611b1a24957c7983041a540806b4275d289
--- /dev/null
+++ b/assets/icons/radix/columns.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/commit.svg b/assets/icons/radix/commit.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ac128a2b083d6b94f17ee065d88226ff7dc53da3
--- /dev/null
+++ b/assets/icons/radix/commit.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-1.svg b/assets/icons/radix/component-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e3e9f38af1fba0b278ed2c48bfc76cb2a6783307
--- /dev/null
+++ b/assets/icons/radix/component-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-2.svg b/assets/icons/radix/component-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..df2091d1437ba51b4d1d6647dfa4d16ebd7dac53
--- /dev/null
+++ b/assets/icons/radix/component-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-boolean.svg b/assets/icons/radix/component-boolean.svg
new file mode 100644
index 0000000000000000000000000000000000000000..942e8832eb4e99cd3af0dc61a1bde6ea01574cb8
--- /dev/null
+++ b/assets/icons/radix/component-boolean.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-instance.svg b/assets/icons/radix/component-instance.svg
new file mode 100644
index 0000000000000000000000000000000000000000..048c40129134426ed628de6d386be9017b484d32
--- /dev/null
+++ b/assets/icons/radix/component-instance.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-none.svg b/assets/icons/radix/component-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a622c3ee960ac4b61d03f4d7b755d98576e37b0d
--- /dev/null
+++ b/assets/icons/radix/component-none.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/component-placeholder.svg b/assets/icons/radix/component-placeholder.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b8892d5d23632fd251938af55c0ae34a112ba058
--- /dev/null
+++ b/assets/icons/radix/component-placeholder.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/radix/container.svg b/assets/icons/radix/container.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1c2a4fd0e18cf47ee793eb6196f6b21e99bda6c0
--- /dev/null
+++ b/assets/icons/radix/container.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cookie.svg b/assets/icons/radix/cookie.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8c165601a2a8af711ce771ea31b829405bccdfba
--- /dev/null
+++ b/assets/icons/radix/cookie.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/copy.svg b/assets/icons/radix/copy.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bf2b504ecfcb378b1a93cf893b4eb070da9471fb
--- /dev/null
+++ b/assets/icons/radix/copy.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/corner-bottom-left.svg b/assets/icons/radix/corner-bottom-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..26df9dbad8c28a6bd041e14bde9cb23624cf66ca
--- /dev/null
+++ b/assets/icons/radix/corner-bottom-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/corner-bottom-right.svg b/assets/icons/radix/corner-bottom-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..15e395712342d3f4d5625d6159f3c1a5ba78e108
--- /dev/null
+++ b/assets/icons/radix/corner-bottom-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/corner-top-left.svg b/assets/icons/radix/corner-top-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8fc1b84b825e7ed1d63ac0dee1b93c768ae42048
--- /dev/null
+++ b/assets/icons/radix/corner-top-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/corner-top-right.svg b/assets/icons/radix/corner-top-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..533ea6c678c2edb2355862ed4ab2712f2b338bab
--- /dev/null
+++ b/assets/icons/radix/corner-top-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/corners.svg b/assets/icons/radix/corners.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c41c4e01839621c0f3a3ec8c6a7c02d7345e97b2
--- /dev/null
+++ b/assets/icons/radix/corners.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/countdown-timer.svg b/assets/icons/radix/countdown-timer.svg
new file mode 100644
index 0000000000000000000000000000000000000000..58494bd416ab93113128a113c3dbaa5b5f268b2a
--- /dev/null
+++ b/assets/icons/radix/countdown-timer.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/counter-clockwise-clock.svg b/assets/icons/radix/counter-clockwise-clock.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0b3acbcebf2d7d71a23d9b89648df9ac532ae847
--- /dev/null
+++ b/assets/icons/radix/counter-clockwise-clock.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/crop.svg b/assets/icons/radix/crop.svg
new file mode 100644
index 0000000000000000000000000000000000000000..008457fff6861d102469ef46a234080e6fb0c634
--- /dev/null
+++ b/assets/icons/radix/crop.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cross-1.svg b/assets/icons/radix/cross-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..62135d27edf689ce7a06092a95248ffeb67b8f9e
--- /dev/null
+++ b/assets/icons/radix/cross-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cross-2.svg b/assets/icons/radix/cross-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4c557009286712b14e716f7e69309b0eb197d768
--- /dev/null
+++ b/assets/icons/radix/cross-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cross-circled.svg b/assets/icons/radix/cross-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..df3cb896c8f20de3614ce7adfd4a6774bead4ee5
--- /dev/null
+++ b/assets/icons/radix/cross-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/crosshair-1.svg b/assets/icons/radix/crosshair-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..05b22f8461a6d1a513b74aeb0ea976936e42f253
--- /dev/null
+++ b/assets/icons/radix/crosshair-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/crosshair-2.svg b/assets/icons/radix/crosshair-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f5ee0a92af713fb3bd8c366f7400194d291ee7b5
--- /dev/null
+++ b/assets/icons/radix/crosshair-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/crumpled-paper.svg b/assets/icons/radix/crumpled-paper.svg
new file mode 100644
index 0000000000000000000000000000000000000000..33e9b65581b6a35b7f8c687f1b9dbab9edbb32cf
--- /dev/null
+++ b/assets/icons/radix/crumpled-paper.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cube.svg b/assets/icons/radix/cube.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b327158be4afc35744fe0c2e84b5f73662a93472
--- /dev/null
+++ b/assets/icons/radix/cube.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cursor-arrow.svg b/assets/icons/radix/cursor-arrow.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b0227e4ded7aef4a78baebcf10a511e0c5659f6c
--- /dev/null
+++ b/assets/icons/radix/cursor-arrow.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/cursor-text.svg b/assets/icons/radix/cursor-text.svg
new file mode 100644
index 0000000000000000000000000000000000000000..05939503b8a5c4caed24fe8ab938fbef8406ffdd
--- /dev/null
+++ b/assets/icons/radix/cursor-text.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dash.svg b/assets/icons/radix/dash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d70daf7fed6ec8e6346e5800ef89249d7cf62984
--- /dev/null
+++ b/assets/icons/radix/dash.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dashboard.svg b/assets/icons/radix/dashboard.svg
new file mode 100644
index 0000000000000000000000000000000000000000..38008c64e41e2addfea23f4c5f88bc04a2a49e86
--- /dev/null
+++ b/assets/icons/radix/dashboard.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/desktop-mute.svg b/assets/icons/radix/desktop-mute.svg
new file mode 100644
index 0000000000000000000000000000000000000000..83d249176fbf067a2732fa4379740cfa54bd018a
--- /dev/null
+++ b/assets/icons/radix/desktop-mute.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/radix/desktop.svg b/assets/icons/radix/desktop.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ad252e64cf5c73d4cd6ae48dd0abede47d3323e6
--- /dev/null
+++ b/assets/icons/radix/desktop.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dimensions.svg b/assets/icons/radix/dimensions.svg
new file mode 100644
index 0000000000000000000000000000000000000000..767d1d289641510dca8f75431192786f294be2a1
--- /dev/null
+++ b/assets/icons/radix/dimensions.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/disc.svg b/assets/icons/radix/disc.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6e19caab3504eef094cd4cffbe43b657dc1913ad
--- /dev/null
+++ b/assets/icons/radix/disc.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/discord-logo.svg b/assets/icons/radix/discord-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..50567c212eda4dca3f87df399dd0e6d0dc076c2b
--- /dev/null
+++ b/assets/icons/radix/discord-logo.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/radix/divider-horizontal.svg b/assets/icons/radix/divider-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..59e43649c93b1767739548a6bc8122886c6061ad
--- /dev/null
+++ b/assets/icons/radix/divider-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/divider-vertical.svg b/assets/icons/radix/divider-vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..95f5cc8f2f45dabe00fd376a8ac2db99155e686f
--- /dev/null
+++ b/assets/icons/radix/divider-vertical.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dot-filled.svg b/assets/icons/radix/dot-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0c1a17b3bd8a904d7274a18b5a4432681fb867ca
--- /dev/null
+++ b/assets/icons/radix/dot-filled.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/dot-solid.svg b/assets/icons/radix/dot-solid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0c1a17b3bd8a904d7274a18b5a4432681fb867ca
--- /dev/null
+++ b/assets/icons/radix/dot-solid.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/dot.svg b/assets/icons/radix/dot.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c553a1422dbd52775efacadede6863d2dc0256c9
--- /dev/null
+++ b/assets/icons/radix/dot.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dots-horizontal.svg b/assets/icons/radix/dots-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..347d1ae13d84eaef1bf4ab33d65a9dfcf11292d5
--- /dev/null
+++ b/assets/icons/radix/dots-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dots-vertical.svg b/assets/icons/radix/dots-vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5ca1a181e3887e4b5459c899aedb25acf60d4bed
--- /dev/null
+++ b/assets/icons/radix/dots-vertical.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/double-arrow-down.svg b/assets/icons/radix/double-arrow-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8b86db2f8a0baa6350a0ad772c083b22fd520be9
--- /dev/null
+++ b/assets/icons/radix/double-arrow-down.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/double-arrow-left.svg b/assets/icons/radix/double-arrow-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0ef30ff9554c558469c75252ef56a828cad2c777
--- /dev/null
+++ b/assets/icons/radix/double-arrow-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/double-arrow-right.svg b/assets/icons/radix/double-arrow-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9997fdc40398d3cf1c6ce30c78ae4d5b4f319457
--- /dev/null
+++ b/assets/icons/radix/double-arrow-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/double-arrow-up.svg b/assets/icons/radix/double-arrow-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8d571fcd66980e46d4e26eaf96870df6ff469408
--- /dev/null
+++ b/assets/icons/radix/double-arrow-up.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/download.svg b/assets/icons/radix/download.svg
new file mode 100644
index 0000000000000000000000000000000000000000..49a05d5f47f7c07faa1403c5320268e6df2581a5
--- /dev/null
+++ b/assets/icons/radix/download.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/drag-handle-dots-1.svg b/assets/icons/radix/drag-handle-dots-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fc046bb9d9b03b5bdd5ea49dc1bedab8aacab656
--- /dev/null
+++ b/assets/icons/radix/drag-handle-dots-1.svg
@@ -0,0 +1,26 @@
+
diff --git a/assets/icons/radix/drag-handle-dots-2.svg b/assets/icons/radix/drag-handle-dots-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aed0e702d7635421fc6674e2daafbccb0573314c
--- /dev/null
+++ b/assets/icons/radix/drag-handle-dots-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/drag-handle-horizontal.svg b/assets/icons/radix/drag-handle-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c1bb138a244147fc61333952ee898979ce67351f
--- /dev/null
+++ b/assets/icons/radix/drag-handle-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/drag-handle-vertical.svg b/assets/icons/radix/drag-handle-vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8d48c7894afcb4949b1784f93c062014dcd207c6
--- /dev/null
+++ b/assets/icons/radix/drag-handle-vertical.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/drawing-pin-filled.svg b/assets/icons/radix/drawing-pin-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e1894619c34441eb228587b9c50fc6af61193a44
--- /dev/null
+++ b/assets/icons/radix/drawing-pin-filled.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/radix/drawing-pin-solid.svg b/assets/icons/radix/drawing-pin-solid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e1894619c34441eb228587b9c50fc6af61193a44
--- /dev/null
+++ b/assets/icons/radix/drawing-pin-solid.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/radix/drawing-pin.svg b/assets/icons/radix/drawing-pin.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5625e7588f1f33f057bf8ad15bc261c45072b1a9
--- /dev/null
+++ b/assets/icons/radix/drawing-pin.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/dropdown-menu.svg b/assets/icons/radix/dropdown-menu.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c938052be8e21698e89e8a0f57215c71410492c9
--- /dev/null
+++ b/assets/icons/radix/dropdown-menu.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/enter-full-screen.svg b/assets/icons/radix/enter-full-screen.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d368a6d415fc340db7595a06b5686cbb920ad48a
--- /dev/null
+++ b/assets/icons/radix/enter-full-screen.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/enter.svg b/assets/icons/radix/enter.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cc57d74ceae76b56074e8be073916301a280b9a2
--- /dev/null
+++ b/assets/icons/radix/enter.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/envelope-closed.svg b/assets/icons/radix/envelope-closed.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4b5e0378401cd9f8530355d84da28d7ca507d0a2
--- /dev/null
+++ b/assets/icons/radix/envelope-closed.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/envelope-open.svg b/assets/icons/radix/envelope-open.svg
new file mode 100644
index 0000000000000000000000000000000000000000..df1e3fea9515984d0207b80e3ab03b39511d52db
--- /dev/null
+++ b/assets/icons/radix/envelope-open.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/eraser.svg b/assets/icons/radix/eraser.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bb448d4d23511c57ab4216dd28af17232949c0b4
--- /dev/null
+++ b/assets/icons/radix/eraser.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/exclamation-triangle.svg b/assets/icons/radix/exclamation-triangle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..210d4c45c666164985e0f1998201d444c9a5f2a7
--- /dev/null
+++ b/assets/icons/radix/exclamation-triangle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/exit-full-screen.svg b/assets/icons/radix/exit-full-screen.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9b6439b043b367c5c300949f511ecb9866f2eaca
--- /dev/null
+++ b/assets/icons/radix/exit-full-screen.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/exit.svg b/assets/icons/radix/exit.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2cc6ce120dc9af17a642ac3bf2f2451209cb5e5e
--- /dev/null
+++ b/assets/icons/radix/exit.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/external-link.svg b/assets/icons/radix/external-link.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0ee7420162a88fa92afc958ec9a61242a9a8640c
--- /dev/null
+++ b/assets/icons/radix/external-link.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/eye-closed.svg b/assets/icons/radix/eye-closed.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f824fe55f9e2f45e7e12b77420eaeb24d6e9c913
--- /dev/null
+++ b/assets/icons/radix/eye-closed.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/eye-none.svg b/assets/icons/radix/eye-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d4beecd33a4a4a305407e1adfa2f4584c4359635
--- /dev/null
+++ b/assets/icons/radix/eye-none.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/eye-open.svg b/assets/icons/radix/eye-open.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d39d26b2c1bbc40af8548cafe219f7cef2373373
--- /dev/null
+++ b/assets/icons/radix/eye-open.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/face.svg b/assets/icons/radix/face.svg
new file mode 100644
index 0000000000000000000000000000000000000000..81b14dd8d7932f9db417843798c726422890b32e
--- /dev/null
+++ b/assets/icons/radix/face.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/figma-logo.svg b/assets/icons/radix/figma-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6c19276554908b11c8742deb0ab4e971bf6856a7
--- /dev/null
+++ b/assets/icons/radix/figma-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/file-minus.svg b/assets/icons/radix/file-minus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bd1a841881c0cfa6a52364dfe57fd55e5a539fa0
--- /dev/null
+++ b/assets/icons/radix/file-minus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/file-plus.svg b/assets/icons/radix/file-plus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2396e20015984b69e2c194c2c9e8552b1a2cc3b5
--- /dev/null
+++ b/assets/icons/radix/file-plus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/file-text.svg b/assets/icons/radix/file-text.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f341ab8abfdba5a9aaac3a81b709c75def92e46c
--- /dev/null
+++ b/assets/icons/radix/file-text.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/file.svg b/assets/icons/radix/file.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5f256b42e1fde343b8194d199f52921e8ad01b7c
--- /dev/null
+++ b/assets/icons/radix/file.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/font-bold.svg b/assets/icons/radix/font-bold.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7dc6caf3b052c956c9bb9ad4adc9ca245cfcf083
--- /dev/null
+++ b/assets/icons/radix/font-bold.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/font-family.svg b/assets/icons/radix/font-family.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9134b9086dd5ddb9aa40a01875033392b2f92f89
--- /dev/null
+++ b/assets/icons/radix/font-family.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/font-italic.svg b/assets/icons/radix/font-italic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6e6288d6bc3ffae240721c50c1a85c1a80270aa2
--- /dev/null
+++ b/assets/icons/radix/font-italic.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/font-roman.svg b/assets/icons/radix/font-roman.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c595b790fc5065d5e4b276d4e73be1ccdeba7be2
--- /dev/null
+++ b/assets/icons/radix/font-roman.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/font-size.svg b/assets/icons/radix/font-size.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e389a58d73bc4997d64b78426be26e964fd5b2b8
--- /dev/null
+++ b/assets/icons/radix/font-size.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/font-style.svg b/assets/icons/radix/font-style.svg
new file mode 100644
index 0000000000000000000000000000000000000000..31c3730130fad5367eb87f1b5ce52b243ee4c1f5
--- /dev/null
+++ b/assets/icons/radix/font-style.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/frame.svg b/assets/icons/radix/frame.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ec61a48efabfc82a55a749860976dd694aee7a83
--- /dev/null
+++ b/assets/icons/radix/frame.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/framer-logo.svg b/assets/icons/radix/framer-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68be3b317b90d2fa990622857645bf21c1768c74
--- /dev/null
+++ b/assets/icons/radix/framer-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/gear.svg b/assets/icons/radix/gear.svg
new file mode 100644
index 0000000000000000000000000000000000000000..52f9e17312fb364b410edbcb21f3aa4b6f3c133c
--- /dev/null
+++ b/assets/icons/radix/gear.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/github-logo.svg b/assets/icons/radix/github-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e46612cf566f59ffc8d8b8b6f4a8bcecd8779b12
--- /dev/null
+++ b/assets/icons/radix/github-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/globe.svg b/assets/icons/radix/globe.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4728b827df862d2e4db3363d9d518cebc860986a
--- /dev/null
+++ b/assets/icons/radix/globe.svg
@@ -0,0 +1,26 @@
+
diff --git a/assets/icons/radix/grid.svg b/assets/icons/radix/grid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5d9af3357295415ea824128b9806d1ca895e8bb6
--- /dev/null
+++ b/assets/icons/radix/grid.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/group.svg b/assets/icons/radix/group.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c3c91d211f47df42ad1c89911fc63e60499d3db6
--- /dev/null
+++ b/assets/icons/radix/group.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/half-1.svg b/assets/icons/radix/half-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9890e26bb815242173bf8a60a01194a9130a361f
--- /dev/null
+++ b/assets/icons/radix/half-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/half-2.svg b/assets/icons/radix/half-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4db1d564cba5c32aae6260095811291c0614fdcf
--- /dev/null
+++ b/assets/icons/radix/half-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/hamburger-menu.svg b/assets/icons/radix/hamburger-menu.svg
new file mode 100644
index 0000000000000000000000000000000000000000..039168055b20d615f19400c4324857d0c038806e
--- /dev/null
+++ b/assets/icons/radix/hamburger-menu.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/hand.svg b/assets/icons/radix/hand.svg
new file mode 100644
index 0000000000000000000000000000000000000000..12afac8f5f9fdff743a7b628437ebfb4424fba2a
--- /dev/null
+++ b/assets/icons/radix/hand.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/heading.svg b/assets/icons/radix/heading.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0a5e2caaf1b10b271da7664dc3636528c6c00942
--- /dev/null
+++ b/assets/icons/radix/heading.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/heart-filled.svg b/assets/icons/radix/heart-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..94928accd7e353b655baf5840ca2be8fb4afd49c
--- /dev/null
+++ b/assets/icons/radix/heart-filled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/heart.svg b/assets/icons/radix/heart.svg
new file mode 100644
index 0000000000000000000000000000000000000000..91cbc450fd0418c590a1519da9834b6cdb72ff5e
--- /dev/null
+++ b/assets/icons/radix/heart.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/height.svg b/assets/icons/radix/height.svg
new file mode 100644
index 0000000000000000000000000000000000000000..28424f4d51e008fafd30347e06e1deb8b3a6942f
--- /dev/null
+++ b/assets/icons/radix/height.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/hobby-knife.svg b/assets/icons/radix/hobby-knife.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c2ed3fb1ed89ef2b9ba74e1c94ec778af5dbc7cd
--- /dev/null
+++ b/assets/icons/radix/hobby-knife.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/home.svg b/assets/icons/radix/home.svg
new file mode 100644
index 0000000000000000000000000000000000000000..733bd791138444e03cb01f52b2e7428f93fbbc36
--- /dev/null
+++ b/assets/icons/radix/home.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/iconjar-logo.svg b/assets/icons/radix/iconjar-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c154b4e86413741786fa3d608f6e466e91c01aab
--- /dev/null
+++ b/assets/icons/radix/iconjar-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/id-card.svg b/assets/icons/radix/id-card.svg
new file mode 100644
index 0000000000000000000000000000000000000000..efde9ffa7e612179911c972a3c048fd389fe3276
--- /dev/null
+++ b/assets/icons/radix/id-card.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/image.svg b/assets/icons/radix/image.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0ff44752528fa0d4b31613a72446ed9164c419cb
--- /dev/null
+++ b/assets/icons/radix/image.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/info-circled.svg b/assets/icons/radix/info-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ab1b260e3d35f9a6243e44ebf0f903add40b6b8
--- /dev/null
+++ b/assets/icons/radix/info-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/inner-shadow.svg b/assets/icons/radix/inner-shadow.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1056a7bffc268fef67c209f4c81f606d40fa66d6
--- /dev/null
+++ b/assets/icons/radix/inner-shadow.svg
@@ -0,0 +1,78 @@
+
diff --git a/assets/icons/radix/input.svg b/assets/icons/radix/input.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ed4605b2c60da836327a7064469425d5233858d
--- /dev/null
+++ b/assets/icons/radix/input.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/instagram-logo.svg b/assets/icons/radix/instagram-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5d7893796655c947c0e6bc0dba60c6e82c86bd65
--- /dev/null
+++ b/assets/icons/radix/instagram-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/justify-center.svg b/assets/icons/radix/justify-center.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7999a4ea468e87d9f0cd793e80c2a43454c4aeac
--- /dev/null
+++ b/assets/icons/radix/justify-center.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/justify-end.svg b/assets/icons/radix/justify-end.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bb52f493d75d79f91e3a6f34e103023e2cc8b87c
--- /dev/null
+++ b/assets/icons/radix/justify-end.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/justify-start.svg b/assets/icons/radix/justify-start.svg
new file mode 100644
index 0000000000000000000000000000000000000000..648ca0b60324f4b92a617f377d890b8f1e1adf13
--- /dev/null
+++ b/assets/icons/radix/justify-start.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/justify-stretch.svg b/assets/icons/radix/justify-stretch.svg
new file mode 100644
index 0000000000000000000000000000000000000000..83df0a8959381ef48a3bd97b53f63f8d9a8bba0f
--- /dev/null
+++ b/assets/icons/radix/justify-stretch.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/keyboard.svg b/assets/icons/radix/keyboard.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fc6f86bfc2b48bdd4fb7acf8e9e08422fed2e91e
--- /dev/null
+++ b/assets/icons/radix/keyboard.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/icons/radix/lap-timer.svg b/assets/icons/radix/lap-timer.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1de0b3be6ce99de994a905cfbaf5e342754bb651
--- /dev/null
+++ b/assets/icons/radix/lap-timer.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/laptop.svg b/assets/icons/radix/laptop.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6aff5d6d446ea46b131bdea1efbd183bc0010381
--- /dev/null
+++ b/assets/icons/radix/laptop.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/layers.svg b/assets/icons/radix/layers.svg
new file mode 100644
index 0000000000000000000000000000000000000000..821993fc70c13ebdb18a997d849db95424399d82
--- /dev/null
+++ b/assets/icons/radix/layers.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/layout.svg b/assets/icons/radix/layout.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8e4a352f5022fe33402bd5267f32f925958a2a01
--- /dev/null
+++ b/assets/icons/radix/layout.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/letter-case-capitalize.svg b/assets/icons/radix/letter-case-capitalize.svg
new file mode 100644
index 0000000000000000000000000000000000000000..16617ecf7e052db05c5bccfe1da0bb378835f686
--- /dev/null
+++ b/assets/icons/radix/letter-case-capitalize.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/letter-case-lowercase.svg b/assets/icons/radix/letter-case-lowercase.svg
new file mode 100644
index 0000000000000000000000000000000000000000..61aefb9aadd3c45a338e5c8048749d62c2c1bfe6
--- /dev/null
+++ b/assets/icons/radix/letter-case-lowercase.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/letter-case-toggle.svg b/assets/icons/radix/letter-case-toggle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a021a2b9225d8eda5657a713b94f7145757206a3
--- /dev/null
+++ b/assets/icons/radix/letter-case-toggle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/letter-case-uppercase.svg b/assets/icons/radix/letter-case-uppercase.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ccd2be04e7757db3050e7675f093288b6d9a5748
--- /dev/null
+++ b/assets/icons/radix/letter-case-uppercase.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/letter-spacing.svg b/assets/icons/radix/letter-spacing.svg
new file mode 100644
index 0000000000000000000000000000000000000000..073023e0f4df60364dede352b60fdc151e6f05d2
--- /dev/null
+++ b/assets/icons/radix/letter-spacing.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/lightning-bolt.svg b/assets/icons/radix/lightning-bolt.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7c35df9cfea2b54cfffa84161902126234ba3234
--- /dev/null
+++ b/assets/icons/radix/lightning-bolt.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/line-height.svg b/assets/icons/radix/line-height.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1c302d1ffc1f1b7e1abb1f4a7553b69be224aac2
--- /dev/null
+++ b/assets/icons/radix/line-height.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-1.svg b/assets/icons/radix/link-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d5682b113ee37a34a42a65897f501af0ee04ffe3
--- /dev/null
+++ b/assets/icons/radix/link-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-2.svg b/assets/icons/radix/link-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..be8370606e7fe33fd9eda9e440433236cc3f6d68
--- /dev/null
+++ b/assets/icons/radix/link-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-break-1.svg b/assets/icons/radix/link-break-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..05ae93e47a4f16ce18cbe2ca3a709b3abc62d15b
--- /dev/null
+++ b/assets/icons/radix/link-break-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-break-2.svg b/assets/icons/radix/link-break-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..78f28f98e815d7fdd822d4a8710d686ad314ccdd
--- /dev/null
+++ b/assets/icons/radix/link-break-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-none-1.svg b/assets/icons/radix/link-none-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6ea56a386fa133bf983a3a7f06b70bd12189e05d
--- /dev/null
+++ b/assets/icons/radix/link-none-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/link-none-2.svg b/assets/icons/radix/link-none-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0b19d940d109bca37ade399a36b8b10c2812faf8
--- /dev/null
+++ b/assets/icons/radix/link-none-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/linkedin-logo.svg b/assets/icons/radix/linkedin-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0f0138bdf6cade2297362c820831a995f7a4e02f
--- /dev/null
+++ b/assets/icons/radix/linkedin-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/list-bullet.svg b/assets/icons/radix/list-bullet.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2630b95ef029e231be2a854efa2cf4c50dbeeb95
--- /dev/null
+++ b/assets/icons/radix/list-bullet.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/lock-closed.svg b/assets/icons/radix/lock-closed.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3871b5d5ada8020c7d7f56510158bd89c4ab5ff2
--- /dev/null
+++ b/assets/icons/radix/lock-closed.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/lock-open-1.svg b/assets/icons/radix/lock-open-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8f6bfd5bbf82007be6d65ada0beb4914b450faf2
--- /dev/null
+++ b/assets/icons/radix/lock-open-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/lock-open-2.svg b/assets/icons/radix/lock-open-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ce69f67f2920b6890eb4446dd6b260484e68178d
--- /dev/null
+++ b/assets/icons/radix/lock-open-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/loop.svg b/assets/icons/radix/loop.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bfa90ed0841f6ca8d26c1eef72e00d893d5efe0c
--- /dev/null
+++ b/assets/icons/radix/loop.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/magic-wand.svg b/assets/icons/radix/magic-wand.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bbc9826aa54afbf202153a170e642bb64f235298
--- /dev/null
+++ b/assets/icons/radix/magic-wand.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/magnifying-glass.svg b/assets/icons/radix/magnifying-glass.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a3a89bfa5059192bdb481a043cdde6d7e42c2f24
--- /dev/null
+++ b/assets/icons/radix/magnifying-glass.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/margin.svg b/assets/icons/radix/margin.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1a513b37d6846849b260a409b9993d3c708bfe30
--- /dev/null
+++ b/assets/icons/radix/margin.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mask-off.svg b/assets/icons/radix/mask-off.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5f847668e8986d4ba9be5cba4b6ddab65e61f0d2
--- /dev/null
+++ b/assets/icons/radix/mask-off.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mask-on.svg b/assets/icons/radix/mask-on.svg
new file mode 100644
index 0000000000000000000000000000000000000000..684c1b934dce4e99b1485593bb8995576eae186b
--- /dev/null
+++ b/assets/icons/radix/mask-on.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mic-mute.svg b/assets/icons/radix/mic-mute.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fe5f8201cc4da5e2cf6a1b770c538d421994e1c4
--- /dev/null
+++ b/assets/icons/radix/mic-mute.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/mic.svg b/assets/icons/radix/mic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..01f4c9bf669ba253edaa43dc641fdb9a1b7c51d1
--- /dev/null
+++ b/assets/icons/radix/mic.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/minus-circled.svg b/assets/icons/radix/minus-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2c6df4cebf1ea279fdc43598fff062ea5db72cb7
--- /dev/null
+++ b/assets/icons/radix/minus-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/minus.svg b/assets/icons/radix/minus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2b396029795aa7b9bcfb2f9dbb703cb491bf88f2
--- /dev/null
+++ b/assets/icons/radix/minus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mix.svg b/assets/icons/radix/mix.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9412a018438b79130fbba167176860d2cef38106
--- /dev/null
+++ b/assets/icons/radix/mix.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mixer-horizontal.svg b/assets/icons/radix/mixer-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f29ba25548a32eae3979249cd915f074444a0f51
--- /dev/null
+++ b/assets/icons/radix/mixer-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mixer-vertical.svg b/assets/icons/radix/mixer-vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dc85d3a9e7a3c3a5ba9d016bb88368b2b35cdcaa
--- /dev/null
+++ b/assets/icons/radix/mixer-vertical.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/mobile.svg b/assets/icons/radix/mobile.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b62b6506ff4f7838e025ea98f93caac228fdd88e
--- /dev/null
+++ b/assets/icons/radix/mobile.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/modulz-logo.svg b/assets/icons/radix/modulz-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..754b229db6b03264c0258553b18d5eea2473a316
--- /dev/null
+++ b/assets/icons/radix/modulz-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/moon.svg b/assets/icons/radix/moon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1dac2ca2120eb3deebf39e9fdf8a353d14e0fb1e
--- /dev/null
+++ b/assets/icons/radix/moon.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/move.svg b/assets/icons/radix/move.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3d0a0e56c9063858f9d71c0cad7c43cdf448c84d
--- /dev/null
+++ b/assets/icons/radix/move.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/notion-logo.svg b/assets/icons/radix/notion-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c2df1526195d99956c0edb1e8c01a5ac641cbaca
--- /dev/null
+++ b/assets/icons/radix/notion-logo.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/opacity.svg b/assets/icons/radix/opacity.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a2d01bff82923948a67ac243df677fc3d7331706
--- /dev/null
+++ b/assets/icons/radix/opacity.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/open-in-new-window.svg b/assets/icons/radix/open-in-new-window.svg
new file mode 100644
index 0000000000000000000000000000000000000000..22baf82cff73662895c6aae20d426319b9ea32a4
--- /dev/null
+++ b/assets/icons/radix/open-in-new-window.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/icons/radix/outer-shadow.svg b/assets/icons/radix/outer-shadow.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b44e3d553c040d855204ac3d543cfa6539db7612
--- /dev/null
+++ b/assets/icons/radix/outer-shadow.svg
@@ -0,0 +1,43 @@
+
diff --git a/assets/icons/radix/overline.svg b/assets/icons/radix/overline.svg
new file mode 100644
index 0000000000000000000000000000000000000000..57262c76e6df8a60a11aa2dddde8a437824ef8e3
--- /dev/null
+++ b/assets/icons/radix/overline.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/padding.svg b/assets/icons/radix/padding.svg
new file mode 100644
index 0000000000000000000000000000000000000000..483a25a27ea1e7c94b21c91b15d929c5cd95ed81
--- /dev/null
+++ b/assets/icons/radix/padding.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/paper-plane.svg b/assets/icons/radix/paper-plane.svg
new file mode 100644
index 0000000000000000000000000000000000000000..37ad0703004b817ff2dd52dae5680dabdd5574db
--- /dev/null
+++ b/assets/icons/radix/paper-plane.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pause.svg b/assets/icons/radix/pause.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b399fb2f5a7ba00e088e9fc2ac10042452879e46
--- /dev/null
+++ b/assets/icons/radix/pause.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pencil-1.svg b/assets/icons/radix/pencil-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..decf0122ef482aab10c213cad07a008e492b2e86
--- /dev/null
+++ b/assets/icons/radix/pencil-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pencil-2.svg b/assets/icons/radix/pencil-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2559a393a9fc2368697619724887a7c7eb8b5a1e
--- /dev/null
+++ b/assets/icons/radix/pencil-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/person.svg b/assets/icons/radix/person.svg
new file mode 100644
index 0000000000000000000000000000000000000000..051abcc7033796d6ad5e65d2d0d5955b6bb51759
--- /dev/null
+++ b/assets/icons/radix/person.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pie-chart.svg b/assets/icons/radix/pie-chart.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bb58e4727465e6c2cebb84e6c7a38b884b9ef13c
--- /dev/null
+++ b/assets/icons/radix/pie-chart.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pilcrow.svg b/assets/icons/radix/pilcrow.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6996765fd60b2e1c09182156b2ba8e19b3cca5f5
--- /dev/null
+++ b/assets/icons/radix/pilcrow.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pin-bottom.svg b/assets/icons/radix/pin-bottom.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ad0842054f082e24c4ab145471c302d00cb9fea6
--- /dev/null
+++ b/assets/icons/radix/pin-bottom.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pin-left.svg b/assets/icons/radix/pin-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..eb89b2912f0735b57f655fe08a33d6efdb5340de
--- /dev/null
+++ b/assets/icons/radix/pin-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pin-right.svg b/assets/icons/radix/pin-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..89a98bae4ea00e8562392aa2dda764d1d6203f40
--- /dev/null
+++ b/assets/icons/radix/pin-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/pin-top.svg b/assets/icons/radix/pin-top.svg
new file mode 100644
index 0000000000000000000000000000000000000000..edfeb64d5d87b0df6c25509d2077054613c4f543
--- /dev/null
+++ b/assets/icons/radix/pin-top.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/play.svg b/assets/icons/radix/play.svg
new file mode 100644
index 0000000000000000000000000000000000000000..92af9e1ae7f125fd9f36e1b67f43b9c71aa54296
--- /dev/null
+++ b/assets/icons/radix/play.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/plus-circled.svg b/assets/icons/radix/plus-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..808ddc4c2ce157903747ff88672425d9c39d5f71
--- /dev/null
+++ b/assets/icons/radix/plus-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/plus.svg b/assets/icons/radix/plus.svg
new file mode 100644
index 0000000000000000000000000000000000000000..57ce90219bc6f72d92e55011f6dcb9f20ba320eb
--- /dev/null
+++ b/assets/icons/radix/plus.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/question-mark-circled.svg b/assets/icons/radix/question-mark-circled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..be99968787df16246e5fb2bbeee617b27393496f
--- /dev/null
+++ b/assets/icons/radix/question-mark-circled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/question-mark.svg b/assets/icons/radix/question-mark.svg
new file mode 100644
index 0000000000000000000000000000000000000000..577aae53496676a657164f0406c50e41566dae3a
--- /dev/null
+++ b/assets/icons/radix/question-mark.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/quote.svg b/assets/icons/radix/quote.svg
new file mode 100644
index 0000000000000000000000000000000000000000..50205479c300e789b302cb1dcd687aaf7f9353f8
--- /dev/null
+++ b/assets/icons/radix/quote.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/radiobutton.svg b/assets/icons/radix/radiobutton.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f0c3a60aee6f499a3dffd30d5d731612de3d90db
--- /dev/null
+++ b/assets/icons/radix/radiobutton.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/reader.svg b/assets/icons/radix/reader.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e893cfa68510377d91301e796366babcc2cbb7aa
--- /dev/null
+++ b/assets/icons/radix/reader.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/reload.svg b/assets/icons/radix/reload.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cf1dfb7fa20bd8233e8ea75c51061b11f73302f5
--- /dev/null
+++ b/assets/icons/radix/reload.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/reset.svg b/assets/icons/radix/reset.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f21a508514cac8c8da0626237726148ee8833953
--- /dev/null
+++ b/assets/icons/radix/reset.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/resume.svg b/assets/icons/radix/resume.svg
new file mode 100644
index 0000000000000000000000000000000000000000..79cdec2374c2e06a3f0afced560a27a9042cc63b
--- /dev/null
+++ b/assets/icons/radix/resume.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/rocket.svg b/assets/icons/radix/rocket.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2226aacb1a7e497f377fbbd607f125782b150f7e
--- /dev/null
+++ b/assets/icons/radix/rocket.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/rotate-counter-clockwise.svg b/assets/icons/radix/rotate-counter-clockwise.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c43c90b90ba001df326c83df80b7d25152782cc3
--- /dev/null
+++ b/assets/icons/radix/rotate-counter-clockwise.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/row-spacing.svg b/assets/icons/radix/row-spacing.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e155bd59479ceaf31dcde7155b0503aa6f305a34
--- /dev/null
+++ b/assets/icons/radix/row-spacing.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/rows.svg b/assets/icons/radix/rows.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fb4ca0f9e3acb960fdeba9d86c973736eda25573
--- /dev/null
+++ b/assets/icons/radix/rows.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/ruler-horizontal.svg b/assets/icons/radix/ruler-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..db6f1ef488b20f66fe89538461b72ba0b7827b54
--- /dev/null
+++ b/assets/icons/radix/ruler-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/ruler-square.svg b/assets/icons/radix/ruler-square.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7de70cc5dc1e852283f89a5048cc730e146ddd4a
--- /dev/null
+++ b/assets/icons/radix/ruler-square.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/scissors.svg b/assets/icons/radix/scissors.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2893b347123f0a29be96b52ee0886ba716f365a0
--- /dev/null
+++ b/assets/icons/radix/scissors.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/section.svg b/assets/icons/radix/section.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1e939e2b2f31f4eef53496154dc4e7c086b28162
--- /dev/null
+++ b/assets/icons/radix/section.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/sewing-pin-filled.svg b/assets/icons/radix/sewing-pin-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..97f6f1120d988746a9ad95d33e8d24b237bec58b
--- /dev/null
+++ b/assets/icons/radix/sewing-pin-filled.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/sewing-pin-solid.svg b/assets/icons/radix/sewing-pin-solid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..97f6f1120d988746a9ad95d33e8d24b237bec58b
--- /dev/null
+++ b/assets/icons/radix/sewing-pin-solid.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/sewing-pin.svg b/assets/icons/radix/sewing-pin.svg
new file mode 100644
index 0000000000000000000000000000000000000000..068dfd7bdfca25e8ac4834f7011e96b377a3ca49
--- /dev/null
+++ b/assets/icons/radix/sewing-pin.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/shadow-inner.svg b/assets/icons/radix/shadow-inner.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4d073bf35f87e99198fc44258c8af746ff95e0b6
--- /dev/null
+++ b/assets/icons/radix/shadow-inner.svg
@@ -0,0 +1,78 @@
+
diff --git a/assets/icons/radix/shadow-none.svg b/assets/icons/radix/shadow-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b02d3466adeb08e3ddbf4ecc3b6c554f1dd5872d
--- /dev/null
+++ b/assets/icons/radix/shadow-none.svg
@@ -0,0 +1,78 @@
+
diff --git a/assets/icons/radix/shadow-outer.svg b/assets/icons/radix/shadow-outer.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dc7ea840878699d22280f6edf481b7c8ea51fa64
--- /dev/null
+++ b/assets/icons/radix/shadow-outer.svg
@@ -0,0 +1,43 @@
+
diff --git a/assets/icons/radix/shadow.svg b/assets/icons/radix/shadow.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c991af6156cb38d143c574bcfb925364768c4f3f
--- /dev/null
+++ b/assets/icons/radix/shadow.svg
@@ -0,0 +1,78 @@
+
diff --git a/assets/icons/radix/share-1.svg b/assets/icons/radix/share-1.svg
new file mode 100644
index 0000000000000000000000000000000000000000..58328e4d1ee1091b8f909ecdfb22b836cb167a93
--- /dev/null
+++ b/assets/icons/radix/share-1.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/share-2.svg b/assets/icons/radix/share-2.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1302ea5fbe198800c08b2abc0cb79a2f4136d3b0
--- /dev/null
+++ b/assets/icons/radix/share-2.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/shuffle.svg b/assets/icons/radix/shuffle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8670e1a04898e130c357c933f7edac966e2cfac9
--- /dev/null
+++ b/assets/icons/radix/shuffle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/size.svg b/assets/icons/radix/size.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dece8c51820fb451e57bf6efd313a00ce6050e22
--- /dev/null
+++ b/assets/icons/radix/size.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/sketch-logo.svg b/assets/icons/radix/sketch-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6c54c4c8252e96ec9d762ffbbab596a72c163303
--- /dev/null
+++ b/assets/icons/radix/sketch-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/slash.svg b/assets/icons/radix/slash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aa7dac30c1af6717056c15f4abafe2b3a1bb09ef
--- /dev/null
+++ b/assets/icons/radix/slash.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/slider.svg b/assets/icons/radix/slider.svg
new file mode 100644
index 0000000000000000000000000000000000000000..66e0452bc0a0469ff6f7ff789f2db55a4fca4e17
--- /dev/null
+++ b/assets/icons/radix/slider.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/space-between-horizontally.svg b/assets/icons/radix/space-between-horizontally.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a71638d52b0c90597a696e4671ce17f1c342681f
--- /dev/null
+++ b/assets/icons/radix/space-between-horizontally.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/space-between-vertically.svg b/assets/icons/radix/space-between-vertically.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bae247222fac0ed744593dcc97befe6051483101
--- /dev/null
+++ b/assets/icons/radix/space-between-vertically.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/space-evenly-horizontally.svg b/assets/icons/radix/space-evenly-horizontally.svg
new file mode 100644
index 0000000000000000000000000000000000000000..70169492e4072dc561370d6185db255a229dd8e2
--- /dev/null
+++ b/assets/icons/radix/space-evenly-horizontally.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/space-evenly-vertically.svg b/assets/icons/radix/space-evenly-vertically.svg
new file mode 100644
index 0000000000000000000000000000000000000000..469b4c05d4eda8045d2534b0a5e8847d0b423851
--- /dev/null
+++ b/assets/icons/radix/space-evenly-vertically.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/speaker-loud.svg b/assets/icons/radix/speaker-loud.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68982ee5e92a85f193d80c6f7aa285722d1d78d8
--- /dev/null
+++ b/assets/icons/radix/speaker-loud.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/speaker-moderate.svg b/assets/icons/radix/speaker-moderate.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0f1d1b4210991ec8d8718bef86c9959bec264c58
--- /dev/null
+++ b/assets/icons/radix/speaker-moderate.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/speaker-off.svg b/assets/icons/radix/speaker-off.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f60c35de7f3f5bb7eecf405c6370391aed6f3ae3
--- /dev/null
+++ b/assets/icons/radix/speaker-off.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/speaker-quiet.svg b/assets/icons/radix/speaker-quiet.svg
new file mode 100644
index 0000000000000000000000000000000000000000..eb68cefcee916e168d25a58be9c4015fe131ecf4
--- /dev/null
+++ b/assets/icons/radix/speaker-quiet.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/square.svg b/assets/icons/radix/square.svg
new file mode 100644
index 0000000000000000000000000000000000000000..82843f51c3b7c98cade0ed914ca18095e3d385fe
--- /dev/null
+++ b/assets/icons/radix/square.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stack.svg b/assets/icons/radix/stack.svg
new file mode 100644
index 0000000000000000000000000000000000000000..92426ffb0d3aac123f647a9c3bcf07932de91407
--- /dev/null
+++ b/assets/icons/radix/stack.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/star-filled.svg b/assets/icons/radix/star-filled.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2b17b7f5792c663e533d3fbe8def8ed44f12b7ff
--- /dev/null
+++ b/assets/icons/radix/star-filled.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/radix/star.svg b/assets/icons/radix/star.svg
new file mode 100644
index 0000000000000000000000000000000000000000..23f09ad7b271cb11e9660901a5d9d819a40ec9a5
--- /dev/null
+++ b/assets/icons/radix/star.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stitches-logo.svg b/assets/icons/radix/stitches-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..319a1481f3e89c5c24535ecc03fffa89c83de737
--- /dev/null
+++ b/assets/icons/radix/stitches-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stop.svg b/assets/icons/radix/stop.svg
new file mode 100644
index 0000000000000000000000000000000000000000..57aac59cab28050f94d5cb93877e8d967f4661c5
--- /dev/null
+++ b/assets/icons/radix/stop.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stopwatch.svg b/assets/icons/radix/stopwatch.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ce5661e5cc9b983676fc97ae0d9c08e78878ee74
--- /dev/null
+++ b/assets/icons/radix/stopwatch.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stretch-horizontally.svg b/assets/icons/radix/stretch-horizontally.svg
new file mode 100644
index 0000000000000000000000000000000000000000..37977363b3046bc59bfd6eb74673a5a49d43d2f8
--- /dev/null
+++ b/assets/icons/radix/stretch-horizontally.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/stretch-vertically.svg b/assets/icons/radix/stretch-vertically.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c4b1fe79ce21f963ad70a17278be8bef7804e43c
--- /dev/null
+++ b/assets/icons/radix/stretch-vertically.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/strikethrough.svg b/assets/icons/radix/strikethrough.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b814ef420acc8a4a385eaf29d52a5a167171860f
--- /dev/null
+++ b/assets/icons/radix/strikethrough.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/sun.svg b/assets/icons/radix/sun.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1807a51b4c60c764a6af190dbd957b6c2ebd0d91
--- /dev/null
+++ b/assets/icons/radix/sun.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/switch.svg b/assets/icons/radix/switch.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6dea528ce9bd25a06962d5ecc64f1ca4b1c9d754
--- /dev/null
+++ b/assets/icons/radix/switch.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/symbol.svg b/assets/icons/radix/symbol.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b529b2b08b42a17027566a47d20f8ae93d61ae35
--- /dev/null
+++ b/assets/icons/radix/symbol.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/table.svg b/assets/icons/radix/table.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8ff059b847b30b73fc31577d88a9a5bc639e6371
--- /dev/null
+++ b/assets/icons/radix/table.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/target.svg b/assets/icons/radix/target.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d67989e01fb7b70c728fdcf85360ac41ac8f2ff5
--- /dev/null
+++ b/assets/icons/radix/target.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-bottom.svg b/assets/icons/radix/text-align-bottom.svg
new file mode 100644
index 0000000000000000000000000000000000000000..862a5aeb883e236e076caee3bec650d79b9b2cd4
--- /dev/null
+++ b/assets/icons/radix/text-align-bottom.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-center.svg b/assets/icons/radix/text-align-center.svg
new file mode 100644
index 0000000000000000000000000000000000000000..673cf8cd0aa97a1ffd39409152efd6fe5cc1ef12
--- /dev/null
+++ b/assets/icons/radix/text-align-center.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-justify.svg b/assets/icons/radix/text-align-justify.svg
new file mode 100644
index 0000000000000000000000000000000000000000..df877f95134803f7d07627ec1b22e6d076c6b595
--- /dev/null
+++ b/assets/icons/radix/text-align-justify.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-left.svg b/assets/icons/radix/text-align-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b7a64fbd439720429ebe73c82340619e3d950391
--- /dev/null
+++ b/assets/icons/radix/text-align-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-middle.svg b/assets/icons/radix/text-align-middle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e739d04efabdf1edada6c848c14c0e3ad3f62832
--- /dev/null
+++ b/assets/icons/radix/text-align-middle.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-right.svg b/assets/icons/radix/text-align-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e7609908ff9436a9e9c4b366ad54b891c9868b64
--- /dev/null
+++ b/assets/icons/radix/text-align-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-align-top.svg b/assets/icons/radix/text-align-top.svg
new file mode 100644
index 0000000000000000000000000000000000000000..21660fe7d307f5e78cf997778d0bc68f9a83f705
--- /dev/null
+++ b/assets/icons/radix/text-align-top.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text-none.svg b/assets/icons/radix/text-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2a87f9372a66fd9e3b56807d0adde8fbb29a568c
--- /dev/null
+++ b/assets/icons/radix/text-none.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/text.svg b/assets/icons/radix/text.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bd41d8ac191905eb40201c7779c247d86783bf67
--- /dev/null
+++ b/assets/icons/radix/text.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/thick-arrow-down.svg b/assets/icons/radix/thick-arrow-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..32923bec58192f66bcce7f067208103d768f5a74
--- /dev/null
+++ b/assets/icons/radix/thick-arrow-down.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/thick-arrow-left.svg b/assets/icons/radix/thick-arrow-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0cfd863903b3ae25d89ca93561d81ec245686913
--- /dev/null
+++ b/assets/icons/radix/thick-arrow-left.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/thick-arrow-right.svg b/assets/icons/radix/thick-arrow-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a0cb605693638380d37ad3b6ff09c07d5b7cf3c4
--- /dev/null
+++ b/assets/icons/radix/thick-arrow-right.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/thick-arrow-up.svg b/assets/icons/radix/thick-arrow-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68687be28da3d3500c2ca98113578f65b9465b44
--- /dev/null
+++ b/assets/icons/radix/thick-arrow-up.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/timer.svg b/assets/icons/radix/timer.svg
new file mode 100644
index 0000000000000000000000000000000000000000..20c52dff95ae423ef3decf9f88b6e13d7c42cbcc
--- /dev/null
+++ b/assets/icons/radix/timer.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/tokens.svg b/assets/icons/radix/tokens.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2bbbc82030a9ebe9b9871ec1cd18a572e688ef25
--- /dev/null
+++ b/assets/icons/radix/tokens.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/track-next.svg b/assets/icons/radix/track-next.svg
new file mode 100644
index 0000000000000000000000000000000000000000..24fd40e36f3d1110f34a4ffb2cc5397f9aa6766a
--- /dev/null
+++ b/assets/icons/radix/track-next.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/track-previous.svg b/assets/icons/radix/track-previous.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d99e7ab53f45d3e749b7d37d76829d8c083979cc
--- /dev/null
+++ b/assets/icons/radix/track-previous.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/transform.svg b/assets/icons/radix/transform.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e913ccc9a7a4297c47e82f978e5a4bda03d1f319
--- /dev/null
+++ b/assets/icons/radix/transform.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/transparency-grid.svg b/assets/icons/radix/transparency-grid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6559ef8c2b9e5ba003c6e3712f502a22416d6f04
--- /dev/null
+++ b/assets/icons/radix/transparency-grid.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/icons/radix/trash.svg b/assets/icons/radix/trash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..18780e492c9a91b117148e72fd4fc0739f671d1e
--- /dev/null
+++ b/assets/icons/radix/trash.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/triangle-down.svg b/assets/icons/radix/triangle-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ebfd8f2a1236e39910eafb25a13e6466caa016db
--- /dev/null
+++ b/assets/icons/radix/triangle-down.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/triangle-left.svg b/assets/icons/radix/triangle-left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0014139716308461f550febfc71a83ec3f6506b3
--- /dev/null
+++ b/assets/icons/radix/triangle-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/triangle-right.svg b/assets/icons/radix/triangle-right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aed1393b9c99cf654f3744bc92853c7b222725d4
--- /dev/null
+++ b/assets/icons/radix/triangle-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/triangle-up.svg b/assets/icons/radix/triangle-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5eb1b416d389bfcc405056f1e5da510cbe4aa272
--- /dev/null
+++ b/assets/icons/radix/triangle-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/radix/twitter-logo.svg b/assets/icons/radix/twitter-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7dcf2f58eb1d15dbe19a53626496a1ef7d87f975
--- /dev/null
+++ b/assets/icons/radix/twitter-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/underline.svg b/assets/icons/radix/underline.svg
new file mode 100644
index 0000000000000000000000000000000000000000..334468509777c7ab550ea690cdc76f8627478e74
--- /dev/null
+++ b/assets/icons/radix/underline.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/update.svg b/assets/icons/radix/update.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b529b2b08b42a17027566a47d20f8ae93d61ae35
--- /dev/null
+++ b/assets/icons/radix/update.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/upload.svg b/assets/icons/radix/upload.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a7f6bddb2e818210222895de24e072736eef14a2
--- /dev/null
+++ b/assets/icons/radix/upload.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/value-none.svg b/assets/icons/radix/value-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a86c08be1a10c961aeb5a61412b891ad3bc9929d
--- /dev/null
+++ b/assets/icons/radix/value-none.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/value.svg b/assets/icons/radix/value.svg
new file mode 100644
index 0000000000000000000000000000000000000000..59dd7d9373ccdd355d3c6dc581bdfb18e6624072
--- /dev/null
+++ b/assets/icons/radix/value.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/vercel-logo.svg b/assets/icons/radix/vercel-logo.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5466fd9f0ebd8ffa94382d899bb250d2cb405872
--- /dev/null
+++ b/assets/icons/radix/vercel-logo.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/video.svg b/assets/icons/radix/video.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e405396bef1c9898d024df78304034d0ad7d8212
--- /dev/null
+++ b/assets/icons/radix/video.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/view-grid.svg b/assets/icons/radix/view-grid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..04825a870bb77b3179e51e2b7fedd7a7197ba9e5
--- /dev/null
+++ b/assets/icons/radix/view-grid.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/view-horizontal.svg b/assets/icons/radix/view-horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2ca7336b99efb11f67addcc31aca81f43f7078ae
--- /dev/null
+++ b/assets/icons/radix/view-horizontal.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/view-none.svg b/assets/icons/radix/view-none.svg
new file mode 100644
index 0000000000000000000000000000000000000000..71b08a46d2917d9057d7331131ef6849f9335867
--- /dev/null
+++ b/assets/icons/radix/view-none.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/view-vertical.svg b/assets/icons/radix/view-vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0c8f8164b4016a6724945cff0fb76700c2bea724
--- /dev/null
+++ b/assets/icons/radix/view-vertical.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/width.svg b/assets/icons/radix/width.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3ae2b56e3dbd78152ed91966b6b3a2474fc7c1e4
--- /dev/null
+++ b/assets/icons/radix/width.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/zoom-in.svg b/assets/icons/radix/zoom-in.svg
new file mode 100644
index 0000000000000000000000000000000000000000..caac722ad07771ec72005752a124f1b86f080a70
--- /dev/null
+++ b/assets/icons/radix/zoom-in.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/icons/radix/zoom-out.svg b/assets/icons/radix/zoom-out.svg
new file mode 100644
index 0000000000000000000000000000000000000000..62046a9e0f1f51239c1587aef16317d325ebef07
--- /dev/null
+++ b/assets/icons/radix/zoom-out.svg
@@ -0,0 +1,8 @@
+
diff --git a/crates/call/src/participant.rs b/crates/call/src/participant.rs
index 4b9e7ba034fb23d118cb5963d335e5c16201d590..e7858869ce63906b75f9cd0cb117cf7b54283efd 100644
--- a/crates/call/src/participant.rs
+++ b/crates/call/src/participant.rs
@@ -3,6 +3,7 @@ use client::{proto, User};
use collections::HashMap;
use gpui::WeakModelHandle;
pub use live_kit_client::Frame;
+use live_kit_client::RemoteAudioTrack;
use project::Project;
use std::{fmt, sync::Arc};
@@ -42,7 +43,10 @@ pub struct RemoteParticipant {
pub peer_id: proto::PeerId,
pub projects: Vec,
pub location: ParticipantLocation,
- pub tracks: HashMap>,
+ pub muted: bool,
+ pub speaking: bool,
+ pub video_tracks: HashMap>,
+ pub audio_tracks: HashMap>,
}
#[derive(Clone)]
diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs
index 775342359f4af8c68ea1caa1bf25affb31c4ba8d..da298f9ca25757f91f394e217099eb236a275827 100644
--- a/crates/call/src/room.rs
+++ b/crates/call/src/room.rs
@@ -12,7 +12,10 @@ use fs::Fs;
use futures::{FutureExt, StreamExt};
use gpui::{AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task, WeakModelHandle};
use language::LanguageRegistry;
-use live_kit_client::{LocalTrackPublication, LocalVideoTrack, RemoteVideoTrackUpdate};
+use live_kit_client::{
+ LocalAudioTrack, LocalTrackPublication, LocalVideoTrack, RemoteAudioTrackUpdate,
+ RemoteVideoTrackUpdate,
+};
use postage::stream::Stream;
use project::Project;
use std::{future::Future, mem, pin::Pin, sync::Arc, time::Duration};
@@ -28,6 +31,9 @@ pub enum Event {
RemoteVideoTracksChanged {
participant_id: proto::PeerId,
},
+ RemoteAudioTracksChanged {
+ participant_id: proto::PeerId,
+ },
RemoteProjectShared {
owner: Arc,
project_id: u64,
@@ -112,9 +118,9 @@ impl Room {
}
});
- let mut track_changes = room.remote_video_track_updates();
- let _maintain_tracks = cx.spawn_weak(|this, mut cx| async move {
- while let Some(track_change) = track_changes.next().await {
+ let mut track_video_changes = room.remote_video_track_updates();
+ let _maintain_video_tracks = cx.spawn_weak(|this, mut cx| async move {
+ while let Some(track_change) = track_video_changes.next().await {
let this = if let Some(this) = this.upgrade(&cx) {
this
} else {
@@ -127,16 +133,41 @@ impl Room {
}
});
- cx.foreground()
- .spawn(room.connect(&connection_info.server_url, &connection_info.token))
- .detach_and_log_err(cx);
+ let mut track_audio_changes = room.remote_audio_track_updates();
+ let _maintain_audio_tracks = cx.spawn_weak(|this, mut cx| async move {
+ while let Some(track_change) = track_audio_changes.next().await {
+ let this = if let Some(this) = this.upgrade(&cx) {
+ this
+ } else {
+ break;
+ };
+
+ this.update(&mut cx, |this, cx| {
+ this.remote_audio_track_updated(track_change, cx).log_err()
+ });
+ }
+ });
+
+ let connect = room.connect(&connection_info.server_url, &connection_info.token);
+ cx.spawn(|this, mut cx| async move {
+ connect.await?;
+ this.update(&mut cx, |this, cx| this.share_microphone(cx))
+ .await?;
+
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
Some(LiveKitRoom {
room,
- screen_track: ScreenTrack::None,
+ screen_track: LocalTrack::None,
+ microphone_track: LocalTrack::None,
next_publish_id: 0,
+ muted_by_user: false,
+ deafened: false,
+ speaking: false,
_maintain_room,
- _maintain_tracks,
+ _maintain_tracks: [_maintain_video_tracks, _maintain_audio_tracks],
})
} else {
None
@@ -618,20 +649,32 @@ impl Room {
peer_id,
projects: participant.projects,
location,
- tracks: Default::default(),
+ muted: false,
+ speaking: false,
+ video_tracks: Default::default(),
+ audio_tracks: Default::default(),
},
);
if let Some(live_kit) = this.live_kit.as_ref() {
- let tracks =
+ let video_tracks =
live_kit.room.remote_video_tracks(&user.id.to_string());
- for track in tracks {
+ let audio_tracks =
+ live_kit.room.remote_audio_tracks(&user.id.to_string());
+ for track in video_tracks {
this.remote_video_track_updated(
RemoteVideoTrackUpdate::Subscribed(track),
cx,
)
.log_err();
}
+ for track in audio_tracks {
+ this.remote_audio_track_updated(
+ RemoteAudioTrackUpdate::Subscribed(track),
+ cx,
+ )
+ .log_err();
+ }
}
}
}
@@ -706,7 +749,7 @@ impl Room {
.remote_participants
.get_mut(&user_id)
.ok_or_else(|| anyhow!("subscribed to track by unknown participant"))?;
- participant.tracks.insert(
+ participant.video_tracks.insert(
track_id.clone(),
Arc::new(RemoteVideoTrack {
live_kit_track: track,
@@ -725,7 +768,7 @@ impl Room {
.remote_participants
.get_mut(&user_id)
.ok_or_else(|| anyhow!("unsubscribed from track by unknown participant"))?;
- participant.tracks.remove(&track_id);
+ participant.video_tracks.remove(&track_id);
cx.emit(Event::RemoteVideoTracksChanged {
participant_id: participant.peer_id,
});
@@ -736,6 +779,84 @@ impl Room {
Ok(())
}
+ fn remote_audio_track_updated(
+ &mut self,
+ change: RemoteAudioTrackUpdate,
+ cx: &mut ModelContext,
+ ) -> Result<()> {
+ match change {
+ RemoteAudioTrackUpdate::ActiveSpeakersChanged { speakers } => {
+ let mut speaker_ids = speakers
+ .into_iter()
+ .filter_map(|speaker_sid| speaker_sid.parse().ok())
+ .collect::>();
+ speaker_ids.sort_unstable();
+ for (sid, participant) in &mut self.remote_participants {
+ if let Ok(_) = speaker_ids.binary_search(sid) {
+ participant.speaking = true;
+ } else {
+ participant.speaking = false;
+ }
+ }
+ if let Some(id) = self.client.user_id() {
+ if let Some(room) = &mut self.live_kit {
+ if let Ok(_) = speaker_ids.binary_search(&id) {
+ room.speaking = true;
+ } else {
+ room.speaking = false;
+ }
+ }
+ }
+ cx.notify();
+ }
+ RemoteAudioTrackUpdate::MuteChanged { track_id, muted } => {
+ for participant in &mut self.remote_participants.values_mut() {
+ let mut found = false;
+ for track in participant.audio_tracks.values() {
+ if track.sid() == track_id {
+ found = true;
+ break;
+ }
+ }
+ if found {
+ participant.muted = muted;
+ break;
+ }
+ }
+ cx.notify();
+ }
+ RemoteAudioTrackUpdate::Subscribed(track) => {
+ let user_id = track.publisher_id().parse()?;
+ let track_id = track.sid().to_string();
+ let participant = self
+ .remote_participants
+ .get_mut(&user_id)
+ .ok_or_else(|| anyhow!("subscribed to track by unknown participant"))?;
+ participant.audio_tracks.insert(track_id.clone(), track);
+ cx.emit(Event::RemoteAudioTracksChanged {
+ participant_id: participant.peer_id,
+ });
+ }
+ RemoteAudioTrackUpdate::Unsubscribed {
+ publisher_id,
+ track_id,
+ } => {
+ let user_id = publisher_id.parse()?;
+ let participant = self
+ .remote_participants
+ .get_mut(&user_id)
+ .ok_or_else(|| anyhow!("unsubscribed from track by unknown participant"))?;
+ participant.audio_tracks.remove(&track_id);
+ cx.emit(Event::RemoteAudioTracksChanged {
+ participant_id: participant.peer_id,
+ });
+ }
+ }
+
+ cx.notify();
+ Ok(())
+ }
+
fn check_invariants(&self) {
#[cfg(any(test, feature = "test-support"))]
{
@@ -908,7 +1029,116 @@ impl Room {
pub fn is_screen_sharing(&self) -> bool {
self.live_kit.as_ref().map_or(false, |live_kit| {
- !matches!(live_kit.screen_track, ScreenTrack::None)
+ !matches!(live_kit.screen_track, LocalTrack::None)
+ })
+ }
+
+ pub fn is_sharing_mic(&self) -> bool {
+ self.live_kit.as_ref().map_or(false, |live_kit| {
+ !matches!(live_kit.microphone_track, LocalTrack::None)
+ })
+ }
+
+ pub fn is_muted(&self) -> bool {
+ self.live_kit
+ .as_ref()
+ .and_then(|live_kit| match &live_kit.microphone_track {
+ LocalTrack::None => None,
+ LocalTrack::Pending { muted, .. } => Some(*muted),
+ LocalTrack::Published { muted, .. } => Some(*muted),
+ })
+ .unwrap_or(false)
+ }
+
+ pub fn is_speaking(&self) -> bool {
+ self.live_kit
+ .as_ref()
+ .map_or(false, |live_kit| live_kit.speaking)
+ }
+
+ pub fn is_deafened(&self) -> Option {
+ self.live_kit.as_ref().map(|live_kit| live_kit.deafened)
+ }
+
+ pub fn share_microphone(&mut self, cx: &mut ModelContext) -> Task> {
+ if self.status.is_offline() {
+ return Task::ready(Err(anyhow!("room is offline")));
+ } else if self.is_sharing_mic() {
+ return Task::ready(Err(anyhow!("microphone was already shared")));
+ }
+
+ let publish_id = if let Some(live_kit) = self.live_kit.as_mut() {
+ let publish_id = post_inc(&mut live_kit.next_publish_id);
+ live_kit.microphone_track = LocalTrack::Pending {
+ publish_id,
+ muted: false,
+ };
+ cx.notify();
+ publish_id
+ } else {
+ return Task::ready(Err(anyhow!("live-kit was not initialized")));
+ };
+
+ cx.spawn_weak(|this, mut cx| async move {
+ let publish_track = async {
+ let track = LocalAudioTrack::create();
+ this.upgrade(&cx)
+ .ok_or_else(|| anyhow!("room was dropped"))?
+ .read_with(&cx, |this, _| {
+ this.live_kit
+ .as_ref()
+ .map(|live_kit| live_kit.room.publish_audio_track(&track))
+ })
+ .ok_or_else(|| anyhow!("live-kit was not initialized"))?
+ .await
+ };
+
+ let publication = publish_track.await;
+ this.upgrade(&cx)
+ .ok_or_else(|| anyhow!("room was dropped"))?
+ .update(&mut cx, |this, cx| {
+ let live_kit = this
+ .live_kit
+ .as_mut()
+ .ok_or_else(|| anyhow!("live-kit was not initialized"))?;
+
+ let (canceled, muted) = if let LocalTrack::Pending {
+ publish_id: cur_publish_id,
+ muted,
+ } = &live_kit.microphone_track
+ {
+ (*cur_publish_id != publish_id, *muted)
+ } else {
+ (true, false)
+ };
+
+ match publication {
+ Ok(publication) => {
+ if canceled {
+ live_kit.room.unpublish_track(publication);
+ } else {
+ if muted {
+ cx.background().spawn(publication.set_mute(muted)).detach();
+ }
+ live_kit.microphone_track = LocalTrack::Published {
+ track_publication: publication,
+ muted,
+ };
+ cx.notify();
+ }
+ Ok(())
+ }
+ Err(error) => {
+ if canceled {
+ Ok(())
+ } else {
+ live_kit.microphone_track = LocalTrack::None;
+ cx.notify();
+ Err(error)
+ }
+ }
+ }
+ })
})
}
@@ -921,7 +1151,10 @@ impl Room {
let (displays, publish_id) = if let Some(live_kit) = self.live_kit.as_mut() {
let publish_id = post_inc(&mut live_kit.next_publish_id);
- live_kit.screen_track = ScreenTrack::Pending { publish_id };
+ live_kit.screen_track = LocalTrack::Pending {
+ publish_id,
+ muted: false,
+ };
cx.notify();
(live_kit.room.display_sources(), publish_id)
} else {
@@ -955,13 +1188,14 @@ impl Room {
.as_mut()
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
- let canceled = if let ScreenTrack::Pending {
+ let (canceled, muted) = if let LocalTrack::Pending {
publish_id: cur_publish_id,
+ muted,
} = &live_kit.screen_track
{
- *cur_publish_id != publish_id
+ (*cur_publish_id != publish_id, *muted)
} else {
- true
+ (true, false)
};
match publication {
@@ -969,7 +1203,13 @@ impl Room {
if canceled {
live_kit.room.unpublish_track(publication);
} else {
- live_kit.screen_track = ScreenTrack::Published(publication);
+ if muted {
+ cx.background().spawn(publication.set_mute(muted)).detach();
+ }
+ live_kit.screen_track = LocalTrack::Published {
+ track_publication: publication,
+ muted,
+ };
cx.notify();
}
Ok(())
@@ -978,7 +1218,7 @@ impl Room {
if canceled {
Ok(())
} else {
- live_kit.screen_track = ScreenTrack::None;
+ live_kit.screen_track = LocalTrack::None;
cx.notify();
Err(error)
}
@@ -987,6 +1227,77 @@ impl Room {
})
})
}
+ fn set_mute(
+ live_kit: &mut LiveKitRoom,
+ should_mute: bool,
+ cx: &mut ModelContext,
+ ) -> Result>> {
+ if !should_mute {
+ // clear user muting state.
+ live_kit.muted_by_user = false;
+ }
+ match &mut live_kit.microphone_track {
+ LocalTrack::None => Err(anyhow!("microphone was not shared")),
+ LocalTrack::Pending { muted, .. } => {
+ *muted = should_mute;
+ cx.notify();
+ Ok(Task::Ready(Some(Ok(()))))
+ }
+ LocalTrack::Published {
+ track_publication,
+ muted,
+ } => {
+ *muted = should_mute;
+ cx.notify();
+ Ok(cx.background().spawn(track_publication.set_mute(*muted)))
+ }
+ }
+ }
+ pub fn toggle_mute(&mut self, cx: &mut ModelContext) -> Result>> {
+ let should_mute = !self.is_muted();
+ if let Some(live_kit) = self.live_kit.as_mut() {
+ let ret = Self::set_mute(live_kit, should_mute, cx);
+ live_kit.muted_by_user = should_mute;
+ ret
+ } else {
+ Err(anyhow!("LiveKit not started"))
+ }
+ }
+
+ pub fn toggle_deafen(&mut self, cx: &mut ModelContext) -> Result>> {
+ if let Some(live_kit) = self.live_kit.as_mut() {
+ (*live_kit).deafened = !live_kit.deafened;
+
+ let mut tasks = Vec::with_capacity(self.remote_participants.len());
+ // Context notification is sent within set_mute itself.
+ let mut mute_task = None;
+ // When deafening, mute user's mic as well.
+ // When undeafening, unmute user's mic unless it was manually muted prior to deafening.
+ if live_kit.deafened || !live_kit.muted_by_user {
+ mute_task = Some(Self::set_mute(live_kit, live_kit.deafened, cx)?);
+ };
+ for participant in self.remote_participants.values() {
+ for track in live_kit
+ .room
+ .remote_audio_track_publications(&participant.user.id.to_string())
+ {
+ tasks.push(cx.foreground().spawn(track.set_enabled(!live_kit.deafened)));
+ }
+ }
+
+ Ok(cx.foreground().spawn(async move {
+ if let Some(mute_task) = mute_task {
+ mute_task.await?;
+ }
+ for task in tasks {
+ task.await?;
+ }
+ Ok(())
+ }))
+ } else {
+ Err(anyhow!("LiveKit not started"))
+ }
+ }
pub fn unshare_screen(&mut self, cx: &mut ModelContext) -> Result<()> {
if self.status.is_offline() {
@@ -998,13 +1309,15 @@ impl Room {
.as_mut()
.ok_or_else(|| anyhow!("live-kit was not initialized"))?;
match mem::take(&mut live_kit.screen_track) {
- ScreenTrack::None => Err(anyhow!("screen was not shared")),
- ScreenTrack::Pending { .. } => {
+ LocalTrack::None => Err(anyhow!("screen was not shared")),
+ LocalTrack::Pending { .. } => {
cx.notify();
Ok(())
}
- ScreenTrack::Published(track) => {
- live_kit.room.unpublish_track(track);
+ LocalTrack::Published {
+ track_publication, ..
+ } => {
+ live_kit.room.unpublish_track(track_publication);
cx.notify();
Ok(())
}
@@ -1023,19 +1336,30 @@ impl Room {
struct LiveKitRoom {
room: Arc,
- screen_track: ScreenTrack,
+ screen_track: LocalTrack,
+ microphone_track: LocalTrack,
+ /// Tracks whether we're currently in a muted state due to auto-mute from deafening or manual mute performed by user.
+ muted_by_user: bool,
+ deafened: bool,
+ speaking: bool,
next_publish_id: usize,
_maintain_room: Task<()>,
- _maintain_tracks: Task<()>,
+ _maintain_tracks: [Task<()>; 2],
}
-enum ScreenTrack {
+enum LocalTrack {
None,
- Pending { publish_id: usize },
- Published(LocalTrackPublication),
+ Pending {
+ publish_id: usize,
+ muted: bool,
+ },
+ Published {
+ track_publication: LocalTrackPublication,
+ muted: bool,
+ },
}
-impl Default for ScreenTrack {
+impl Default for LocalTrack {
fn default() -> Self {
Self::None
}
diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs
index 2211e53263226c74c840be49a657004c172d4a97..3ddef9410427a199a029e8d16b7d0240527527c4 100644
--- a/crates/collab/src/tests/integration_tests.rs
+++ b/crates/collab/src/tests/integration_tests.rs
@@ -257,7 +257,7 @@ async fn test_basic_calls(
room_b.read_with(cx_b, |room, _| {
assert_eq!(
room.remote_participants()[&client_a.user_id().unwrap()]
- .tracks
+ .video_tracks
.len(),
1
);
@@ -274,7 +274,7 @@ async fn test_basic_calls(
room_c.read_with(cx_c, |room, _| {
assert_eq!(
room.remote_participants()[&client_a.user_id().unwrap()]
- .tracks
+ .video_tracks
.len(),
1
);
@@ -7014,7 +7014,7 @@ async fn test_join_call_after_screen_was_shared(
room.remote_participants()
.get(&client_a.user_id().unwrap())
.unwrap()
- .tracks
+ .video_tracks
.len(),
1
);
diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml
index 16cc6b52772e2772aab691f1e9e2b8dbf0e3b726..ee410ccba7a57e68af7601e2ea3fd0fc654f653d 100644
--- a/crates/collab_ui/Cargo.toml
+++ b/crates/collab_ui/Cargo.toml
@@ -37,8 +37,10 @@ picker = { path = "../picker" }
project = { path = "../project" }
settings = { path = "../settings" }
theme = { path = "../theme" }
+theme_selector = { path = "../theme_selector" }
util = { path = "../util" }
workspace = { path = "../workspace" }
+zed-actions = {path = "../zed-actions"}
anyhow.workspace = true
futures.workspace = true
diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs
index 04fc9650eb82f1177b0290463b04e2601be9640c..2ab89281660b5750eb4028ce7a2ed87ccc46851a 100644
--- a/crates/collab_ui/src/collab_titlebar_item.rs
+++ b/crates/collab_ui/src/collab_titlebar_item.rs
@@ -1,6 +1,7 @@
use crate::{
contact_notification::ContactNotification, contacts_popover, face_pile::FacePile,
- toggle_screen_sharing, ToggleScreenSharing,
+ toggle_deafen, toggle_mute, toggle_screen_sharing, LeaveCall, ToggleDeafen, ToggleMute,
+ ToggleScreenSharing,
};
use call::{ActiveCall, ParticipantLocation, Room};
use client::{proto::PeerId, Client, ContactEventKind, SignIn, SignOut, User, UserStore};
@@ -17,13 +18,13 @@ use gpui::{
AppContext, Entity, ImageData, LayoutContext, ModelHandle, SceneBuilder, Subscription, View,
ViewContext, ViewHandle, WeakViewHandle,
};
-use project::Project;
+use project::{Project, RepositoryEntry};
use std::{ops::Range, sync::Arc};
use theme::{AvatarStyle, Theme};
use util::ResultExt;
use workspace::{FollowNextCollaborator, Workspace};
-const MAX_TITLE_LENGTH: usize = 75;
+// const MAX_TITLE_LENGTH: usize = 75;
actions!(
collab,
@@ -78,27 +79,34 @@ impl View for CollabTitlebarItem {
let user = self.user_store.read(cx).current_user();
let peer_id = self.client.peer_id();
if let Some(((user, peer_id), room)) = user
+ .as_ref()
.zip(peer_id)
.zip(ActiveCall::global(cx).read(cx).room().cloned())
{
- left_container
- .add_children(self.render_in_call_share_unshare_button(&workspace, &theme, cx));
-
- right_container.add_children(self.render_collaborators(&workspace, &theme, &room, cx));
right_container
- .add_child(self.render_current_user(&workspace, &theme, &user, peer_id, cx));
+ .add_children(self.render_in_call_share_unshare_button(&workspace, &theme, cx));
+ right_container.add_child(self.render_leave_call(&theme, cx));
+ let muted = room.read(cx).is_muted();
+ let speaking = room.read(cx).is_speaking();
+ left_container.add_child(
+ self.render_current_user(&workspace, &theme, &user, peer_id, muted, speaking, cx),
+ );
+ left_container.add_children(self.render_collaborators(&workspace, &theme, &room, cx));
+ right_container.add_child(self.render_toggle_mute(&theme, &room, cx));
+ right_container.add_child(self.render_toggle_deafen(&theme, &room, cx));
right_container.add_child(self.render_toggle_screen_sharing_button(&theme, &room, cx));
}
let status = workspace.read(cx).client().status();
let status = &*status.borrow();
-
if matches!(status, client::Status::Connected { .. }) {
right_container.add_child(self.render_toggle_contacts_button(&theme, cx));
- right_container.add_child(self.render_user_menu_button(&theme, cx));
+ let avatar = user.as_ref().and_then(|user| user.avatar.clone());
+ right_container.add_child(self.render_user_menu_button(&theme, avatar, cx));
} else {
right_container.add_children(self.render_connection_status(status, cx));
right_container.add_child(self.render_sign_in_button(&theme, cx));
+ right_container.add_child(self.render_user_menu_button(&theme, None, cx));
}
Stack::new()
@@ -108,7 +116,6 @@ impl View for CollabTitlebarItem {
.with_child(
right_container.contained().with_background_color(
theme
- .workspace
.titlebar
.container
.background_color
@@ -163,7 +170,6 @@ impl CollabTitlebarItem {
}),
);
- let view_id = cx.view_id();
Self {
workspace: workspace.weak_handle(),
project,
@@ -171,6 +177,7 @@ impl CollabTitlebarItem {
client,
contacts_popover: None,
user_menu: cx.add_view(|cx| {
+ let view_id = cx.view_id();
let mut menu = ContextMenu::new(view_id, cx);
menu.set_position_mode(OverlayPositionMode::Local);
menu
@@ -185,55 +192,45 @@ impl CollabTitlebarItem {
theme: Arc,
cx: &ViewContext,
) -> AnyElement {
- let names_and_branches = project.visible_worktrees(cx).map(|worktree| {
+ let mut names_and_branches = project.visible_worktrees(cx).map(|worktree| {
let worktree = worktree.read(cx);
(worktree.root_name(), worktree.root_git_entry())
});
- fn push_str(buffer: &mut String, index: &mut usize, str: &str) {
- buffer.push_str(str);
- *index += str.chars().count();
- }
-
- let mut indices = Vec::new();
- let mut index = 0;
- let mut title = String::new();
- let mut names_and_branches = names_and_branches.peekable();
- while let Some((name, entry)) = names_and_branches.next() {
- let pre_index = index;
- push_str(&mut title, &mut index, name);
- indices.extend((pre_index..index).into_iter());
- if let Some(branch) = entry.and_then(|entry| entry.branch()) {
- push_str(&mut title, &mut index, "/");
- push_str(&mut title, &mut index, &branch);
- }
- if names_and_branches.peek().is_some() {
- push_str(&mut title, &mut index, ", ");
- if index >= MAX_TITLE_LENGTH {
- title.push_str(" …");
- break;
- }
- }
- }
-
- let text_style = theme.workspace.titlebar.title.clone();
- let item_spacing = theme.workspace.titlebar.item_spacing;
+ let (name, entry) = names_and_branches.next().unwrap_or(("", None));
+ let branch_prepended = entry
+ .as_ref()
+ .and_then(RepositoryEntry::branch)
+ .map(|branch| format!("/{branch}"));
+ let text_style = theme.titlebar.title.clone();
+ let item_spacing = theme.titlebar.item_spacing;
let mut highlight = text_style.clone();
- highlight.color = theme.workspace.titlebar.highlight_color;
+ highlight.color = theme.titlebar.highlight_color;
let style = LabelStyle {
text: text_style,
highlight_text: Some(highlight),
};
-
- Label::new(title, style)
- .with_highlights(indices)
- .contained()
- .with_margin_right(item_spacing)
- .aligned()
- .left()
- .into_any_named("title-with-git-information")
+ let mut ret = Flex::row().with_child(
+ Label::new(name.to_owned(), style.clone())
+ .with_highlights((0..name.len()).into_iter().collect())
+ .contained()
+ .aligned()
+ .left()
+ .into_any_named("title-project-name"),
+ );
+ if let Some(git_branch) = branch_prepended {
+ ret = ret.with_child(
+ Label::new(git_branch, style)
+ .contained()
+ .with_margin_right(item_spacing)
+ .aligned()
+ .left()
+ .into_any_named("title-project-branch"),
+ )
+ }
+ ret.into_any()
}
fn window_activation_changed(&mut self, active: bool, cx: &mut ViewContext) {
@@ -297,50 +294,29 @@ impl CollabTitlebarItem {
}
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext) {
- let theme = theme::current(cx).clone();
- let avatar_style = theme.workspace.titlebar.leader_avatar.clone();
- let item_style = theme
- .context_menu
- .item
- .inactive_state()
- .disabled_style()
- .clone();
self.user_menu.update(cx, |user_menu, cx| {
- let items = if let Some(user) = self.user_store.read(cx).current_user() {
+ let items = if let Some(_) = self.user_store.read(cx).current_user() {
vec![
- ContextMenuItem::Static(Box::new(move |_| {
- Flex::row()
- .with_children(user.avatar.clone().map(|avatar| {
- Self::render_face(
- avatar,
- avatar_style.clone(),
- Color::transparent_black(),
- )
- }))
- .with_child(Label::new(
- user.github_login.clone(),
- item_style.label.clone(),
- ))
- .contained()
- .with_style(item_style.container)
- .into_any()
- })),
- ContextMenuItem::action("Sign out", SignOut),
+ ContextMenuItem::action("Settings", zed_actions::OpenSettings),
+ ContextMenuItem::action("Theme", theme_selector::Toggle),
+ ContextMenuItem::separator(),
ContextMenuItem::action(
- "Send Feedback",
+ "Share Feedback",
feedback::feedback_editor::GiveFeedback,
),
+ ContextMenuItem::action("Sign out", SignOut),
]
} else {
vec![
- ContextMenuItem::action("Sign in", SignIn),
+ ContextMenuItem::action("Settings", zed_actions::OpenSettings),
+ ContextMenuItem::action("Theme", theme_selector::Toggle),
+ ContextMenuItem::separator(),
ContextMenuItem::action(
- "Send Feedback",
+ "Share Feedback",
feedback::feedback_editor::GiveFeedback,
),
]
};
-
user_menu.show(Default::default(), AnchorCorner::TopRight, items, cx);
});
}
@@ -350,7 +326,7 @@ impl CollabTitlebarItem {
theme: &Theme,
cx: &mut ViewContext,
) -> AnyElement {
- let titlebar = &theme.workspace.titlebar;
+ let titlebar = &theme.titlebar;
let badge = if self
.user_store
@@ -391,7 +367,7 @@ impl CollabTitlebarItem {
.toggle_contacts_button
.in_state(self.contacts_popover.is_some())
.style_for(state);
- Svg::new("icons/user_plus_16.svg")
+ Svg::new("icons/radix/person.svg")
.with_color(style.color)
.constrained()
.with_width(style.icon_width)
@@ -418,7 +394,6 @@ impl CollabTitlebarItem {
.with_children(self.render_contacts_popover_host(titlebar, cx))
.into_any()
}
-
fn render_toggle_screen_sharing_button(
&self,
theme: &Theme,
@@ -428,16 +403,21 @@ impl CollabTitlebarItem {
let icon;
let tooltip;
if room.read(cx).is_screen_sharing() {
- icon = "icons/enable_screen_sharing_12.svg";
+ icon = "icons/radix/desktop.svg";
tooltip = "Stop Sharing Screen"
} else {
- icon = "icons/disable_screen_sharing_12.svg";
+ icon = "icons/radix/desktop.svg";
tooltip = "Share Screen";
}
- let titlebar = &theme.workspace.titlebar;
+ let active = room.read(cx).is_screen_sharing();
+ let titlebar = &theme.titlebar;
MouseEventHandler::::new(0, cx, |state, _| {
- let style = titlebar.call_control.style_for(state);
+ let style = titlebar
+ .screen_share_button
+ .in_state(active)
+ .style_for(state);
+
Svg::new(icon)
.with_color(style.color)
.constrained()
@@ -463,7 +443,141 @@ impl CollabTitlebarItem {
.aligned()
.into_any()
}
+ fn render_toggle_mute(
+ &self,
+ theme: &Theme,
+ room: &ModelHandle,
+ cx: &mut ViewContext,
+ ) -> AnyElement {
+ let icon;
+ let tooltip;
+ let is_muted = room.read(cx).is_muted();
+ if is_muted {
+ icon = "icons/radix/mic-mute.svg";
+ tooltip = "Unmute microphone\nRight click for options";
+ } else {
+ icon = "icons/radix/mic.svg";
+ tooltip = "Mute microphone\nRight click for options";
+ }
+ let titlebar = &theme.titlebar;
+ MouseEventHandler::::new(0, cx, |state, _| {
+ let style = titlebar
+ .toggle_microphone_button
+ .in_state(is_muted)
+ .style_for(state);
+ let image = Svg::new(icon)
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ .contained()
+ .with_style(style.container);
+ if let Some(color) = style.container.background_color {
+ image.with_background_color(color)
+ } else {
+ image
+ }
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(MouseButton::Left, move |_, _, cx| {
+ toggle_mute(&Default::default(), cx)
+ })
+ .with_tooltip::(
+ 0,
+ tooltip.into(),
+ Some(Box::new(ToggleMute)),
+ theme.tooltip.clone(),
+ cx,
+ )
+ .aligned()
+ .into_any()
+ }
+ fn render_toggle_deafen(
+ &self,
+ theme: &Theme,
+ room: &ModelHandle,
+ cx: &mut ViewContext,
+ ) -> AnyElement {
+ let icon;
+ let tooltip;
+ let is_deafened = room.read(cx).is_deafened().unwrap_or(false);
+ if is_deafened {
+ icon = "icons/radix/speaker-off.svg";
+ tooltip = "Unmute speakers\nRight click for options";
+ } else {
+ icon = "icons/radix/speaker-loud.svg";
+ tooltip = "Mute speakers\nRight click for options";
+ }
+
+ let titlebar = &theme.titlebar;
+ MouseEventHandler::::new(0, cx, |state, _| {
+ let style = titlebar
+ .toggle_speakers_button
+ .in_state(is_deafened)
+ .style_for(state);
+ Svg::new(icon)
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ .contained()
+ .with_style(style.container)
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(MouseButton::Left, move |_, _, cx| {
+ toggle_deafen(&Default::default(), cx)
+ })
+ .with_tooltip::(
+ 0,
+ tooltip.into(),
+ Some(Box::new(ToggleDeafen)),
+ theme.tooltip.clone(),
+ cx,
+ )
+ .aligned()
+ .into_any()
+ }
+ fn render_leave_call(&self, theme: &Theme, cx: &mut ViewContext) -> AnyElement {
+ let icon = "icons/radix/exit.svg";
+ let tooltip = "Leave call";
+
+ let titlebar = &theme.titlebar;
+ MouseEventHandler::::new(0, cx, |state, _| {
+ let style = titlebar.leave_call_button.style_for(state);
+ Svg::new(icon)
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ .contained()
+ .with_style(style.container)
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(MouseButton::Left, move |_, _, cx| {
+ ActiveCall::global(cx)
+ .update(cx, |call, cx| call.hang_up(cx))
+ .detach_and_log_err(cx);
+ })
+ .with_tooltip::(
+ 0,
+ tooltip.into(),
+ Some(Box::new(LeaveCall)),
+ theme.tooltip.clone(),
+ cx,
+ )
+ .aligned()
+ .into_any()
+ }
fn render_in_call_share_unshare_button(
&self,
workspace: &ViewHandle,
@@ -476,14 +590,14 @@ impl CollabTitlebarItem {
}
let is_shared = project.read(cx).is_shared();
- let label = if is_shared { "Unshare" } else { "Share" };
+ let label = if is_shared { "Stop Sharing" } else { "Share" };
let tooltip = if is_shared {
- "Unshare project from call participants"
+ "Stop sharing project with call participants"
} else {
"Share project with call participants"
};
- let titlebar = &theme.workspace.titlebar;
+ let titlebar = &theme.titlebar;
enum ShareUnshare {}
Some(
@@ -514,7 +628,7 @@ impl CollabTitlebarItem {
)
.aligned()
.contained()
- .with_margin_left(theme.workspace.titlebar.item_spacing)
+ .with_margin_left(theme.titlebar.item_spacing)
.into_any(),
)
}
@@ -522,24 +636,51 @@ impl CollabTitlebarItem {
fn render_user_menu_button(
&self,
theme: &Theme,
+ avatar: Option>,
cx: &mut ViewContext,
) -> AnyElement {
- let titlebar = &theme.workspace.titlebar;
+ let tooltip = theme.tooltip.clone();
+ let user_menu_button_style = if avatar.is_some() {
+ &theme.titlebar.user_menu.user_menu_button_online
+ } else {
+ &theme.titlebar.user_menu.user_menu_button_offline
+ };
+ let avatar_style = &user_menu_button_style.avatar;
Stack::new()
.with_child(
MouseEventHandler::::new(0, cx, |state, _| {
- let style = titlebar.call_control.style_for(state);
- Svg::new("icons/ellipsis_14.svg")
- .with_color(style.color)
- .constrained()
- .with_width(style.icon_width)
+ let style = user_menu_button_style
+ .user_menu
+ .inactive_state()
+ .style_for(state);
+
+ let mut dropdown = Flex::row().align_children_center();
+
+ if let Some(avatar_img) = avatar {
+ dropdown = dropdown.with_child(Self::render_face(
+ avatar_img,
+ *avatar_style,
+ Color::transparent_black(),
+ None,
+ ));
+ };
+
+ dropdown
+ .with_child(
+ Svg::new("icons/caret_down_8.svg")
+ .with_color(user_menu_button_style.icon.color)
+ .constrained()
+ .with_width(user_menu_button_style.icon.width)
+ .contained()
+ .into_any(),
+ )
.aligned()
.constrained()
- .with_width(style.button_width)
- .with_height(style.button_width)
+ .with_height(style.width)
.contained()
.with_style(style.container)
+ .into_any()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| {
@@ -549,11 +690,10 @@ impl CollabTitlebarItem {
0,
"Toggle user menu".to_owned(),
Some(Box::new(ToggleUserMenu)),
- theme.tooltip.clone(),
+ tooltip,
cx,
)
- .contained()
- .with_margin_left(theme.workspace.titlebar.item_spacing),
+ .contained(),
)
.with_child(
ChildView::new(&self.user_menu, cx)
@@ -565,9 +705,9 @@ impl CollabTitlebarItem {
}
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext) -> AnyElement {
- let titlebar = &theme.workspace.titlebar;
+ let titlebar = &theme.titlebar;
MouseEventHandler::::new(0, cx, |state, _| {
- let style = titlebar.sign_in_prompt.inactive_state().style_for(state);
+ let style = titlebar.sign_in_button.inactive_state().style_for(state);
Label::new("Sign In", style.text.clone())
.contained()
.with_style(style.container)
@@ -629,11 +769,13 @@ impl CollabTitlebarItem {
replica_id,
participant.peer_id,
Some(participant.location),
+ participant.muted,
+ participant.speaking,
workspace,
theme,
cx,
))
- .with_margin_right(theme.workspace.titlebar.face_pile_spacing),
+ .with_margin_right(theme.titlebar.face_pile_spacing),
)
})
.collect()
@@ -645,19 +787,24 @@ impl CollabTitlebarItem {
theme: &Theme,
user: &Arc,
peer_id: PeerId,
+ muted: bool,
+ speaking: bool,
cx: &mut ViewContext,
) -> AnyElement {
let replica_id = workspace.read(cx).project().read(cx).replica_id();
+
Container::new(self.render_face_pile(
user,
Some(replica_id),
peer_id,
None,
+ muted,
+ speaking,
workspace,
theme,
cx,
))
- .with_margin_right(theme.workspace.titlebar.item_spacing)
+ .with_margin_right(theme.titlebar.item_spacing)
.into_any()
}
@@ -667,6 +814,8 @@ impl CollabTitlebarItem {
replica_id: Option,
peer_id: PeerId,
location: Option,
+ muted: bool,
+ speaking: bool,
workspace: &ViewHandle,
theme: &Theme,
cx: &mut ViewContext,
@@ -689,15 +838,23 @@ impl CollabTitlebarItem {
})
.unwrap_or(false);
- let leader_style = theme.workspace.titlebar.leader_avatar;
- let follower_style = theme.workspace.titlebar.follower_avatar;
+ let leader_style = theme.titlebar.leader_avatar;
+ let follower_style = theme.titlebar.follower_avatar;
+
+ let microphone_state = if muted {
+ Some(theme.titlebar.muted)
+ } else if speaking {
+ Some(theme.titlebar.speaking)
+ } else {
+ None
+ };
let mut background_color = theme
- .workspace
.titlebar
.container
.background_color
.unwrap_or_default();
+
if let Some(replica_id) = replica_id {
if followed_by_self {
let selection = theme.editor.replica_selection_style(replica_id).selection;
@@ -708,11 +865,12 @@ impl CollabTitlebarItem {
let mut content = Stack::new()
.with_children(user.avatar.as_ref().map(|avatar| {
- let face_pile = FacePile::new(theme.workspace.titlebar.follower_avatar_overlap)
+ let face_pile = FacePile::new(theme.titlebar.follower_avatar_overlap)
.with_child(Self::render_face(
avatar.clone(),
Self::location_style(workspace, location, leader_style, cx),
background_color,
+ microphone_state,
))
.with_children(
(|| {
@@ -744,6 +902,7 @@ impl CollabTitlebarItem {
avatar.clone(),
follower_style,
background_color,
+ None,
))
}))
})()
@@ -753,7 +912,7 @@ impl CollabTitlebarItem {
let mut container = face_pile
.contained()
- .with_style(theme.workspace.titlebar.leader_selection);
+ .with_style(theme.titlebar.leader_selection);
if let Some(replica_id) = replica_id {
if followed_by_self {
@@ -770,8 +929,8 @@ impl CollabTitlebarItem {
Some(
AvatarRibbon::new(color)
.constrained()
- .with_width(theme.workspace.titlebar.avatar_ribbon.width)
- .with_height(theme.workspace.titlebar.avatar_ribbon.height)
+ .with_width(theme.titlebar.avatar_ribbon.width)
+ .with_height(theme.titlebar.avatar_ribbon.height)
.aligned()
.bottom(),
)
@@ -862,12 +1021,13 @@ impl CollabTitlebarItem {
avatar: Arc,
avatar_style: AvatarStyle,
background_color: Color,
+ microphone_state: Option,
) -> AnyElement {
Image::from_data(avatar)
.with_style(avatar_style.image)
.aligned()
.contained()
- .with_background_color(background_color)
+ .with_background_color(microphone_state.unwrap_or(background_color))
.with_corner_radius(avatar_style.outer_corner_radius)
.constrained()
.with_width(avatar_style.outer_width)
@@ -891,22 +1051,22 @@ impl CollabTitlebarItem {
| client::Status::Reconnecting { .. }
| client::Status::ReconnectionError { .. } => Some(
Svg::new("icons/cloud_slash_12.svg")
- .with_color(theme.workspace.titlebar.offline_icon.color)
+ .with_color(theme.titlebar.offline_icon.color)
.constrained()
- .with_width(theme.workspace.titlebar.offline_icon.width)
+ .with_width(theme.titlebar.offline_icon.width)
.aligned()
.contained()
- .with_style(theme.workspace.titlebar.offline_icon.container)
+ .with_style(theme.titlebar.offline_icon.container)
.into_any(),
),
client::Status::UpgradeRequired => Some(
MouseEventHandler::::new(0, cx, |_, _| {
Label::new(
"Please update Zed to collaborate",
- theme.workspace.titlebar.outdated_warning.text.clone(),
+ theme.titlebar.outdated_warning.text.clone(),
)
.contained()
- .with_style(theme.workspace.titlebar.outdated_warning.container)
+ .with_style(theme.titlebar.outdated_warning.container)
.aligned()
})
.with_cursor_style(CursorStyle::PointingHand)
diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs
index c0734388b1512b2e9cac5014c460bf1a8c09650b..a809b9c7e6d54b2504aa1f4a95e7257396e930c4 100644
--- a/crates/collab_ui/src/collab_ui.rs
+++ b/crates/collab_ui/src/collab_ui.rs
@@ -9,13 +9,23 @@ mod notifications;
mod project_shared_notification;
mod sharing_status_indicator;
-use call::ActiveCall;
+use call::{ActiveCall, Room};
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleContactsMenu};
use gpui::{actions, AppContext, Task};
use std::sync::Arc;
+use util::ResultExt;
use workspace::AppState;
-actions!(collab, [ToggleScreenSharing]);
+actions!(
+ collab,
+ [
+ ToggleScreenSharing,
+ ToggleMute,
+ ToggleDeafen,
+ LeaveCall,
+ ShareMicrophone
+ ]
+);
pub fn init(app_state: &Arc, cx: &mut AppContext) {
collab_titlebar_item::init(cx);
@@ -27,6 +37,9 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) {
sharing_status_indicator::init(cx);
cx.add_global_action(toggle_screen_sharing);
+ cx.add_global_action(toggle_mute);
+ cx.add_global_action(toggle_deafen);
+ cx.add_global_action(share_microphone);
}
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
@@ -41,3 +54,26 @@ pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
toggle_screen_sharing.detach_and_log_err(cx);
}
}
+
+pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) {
+ if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+ room.update(cx, Room::toggle_mute)
+ .map(|task| task.detach_and_log_err(cx))
+ .log_err();
+ }
+}
+
+pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
+ if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+ room.update(cx, Room::toggle_deafen)
+ .map(|task| task.detach_and_log_err(cx))
+ .log_err();
+ }
+}
+
+pub fn share_microphone(_: &ShareMicrophone, cx: &mut AppContext) {
+ if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+ room.update(cx, Room::share_microphone)
+ .detach_and_log_err(cx)
+ }
+}
diff --git a/crates/collab_ui/src/contact_list.rs b/crates/collab_ui/src/contact_list.rs
index 0c8b27a1511e075aa734d62001392beb64da56b4..428f2156d116133d063710fed99c890e8ad30869 100644
--- a/crates/collab_ui/src/contact_list.rs
+++ b/crates/collab_ui/src/contact_list.rs
@@ -514,10 +514,10 @@ impl ContactList {
project_id: project.id,
worktree_root_names: project.worktree_root_names.clone(),
host_user_id: participant.user.id,
- is_last: projects.peek().is_none() && participant.tracks.is_empty(),
+ is_last: projects.peek().is_none() && participant.video_tracks.is_empty(),
});
}
- if !participant.tracks.is_empty() {
+ if !participant.video_tracks.is_empty() {
participant_entries.push(ContactEntry::ParticipantScreen {
peer_id: participant.peer_id,
is_last: true,
diff --git a/crates/gpui/src/executor.rs b/crates/gpui/src/executor.rs
index 365766fb9dd0b080642a4b1e344d985dd312d22c..712c8544884af838a6d5cccdc5f6555a77b8014f 100644
--- a/crates/gpui/src/executor.rs
+++ b/crates/gpui/src/executor.rs
@@ -7,6 +7,7 @@ use std::{
fmt::{self, Display},
marker::PhantomData,
mem,
+ panic::Location,
pin::Pin,
rc::Rc,
sync::Arc,
@@ -965,10 +966,12 @@ impl Task {
}
impl Task> {
+ #[track_caller]
pub fn detach_and_log_err(self, cx: &mut AppContext) {
+ let caller = Location::caller();
cx.spawn(|_| async move {
if let Err(err) = self.await {
- log::error!("{:#}", err);
+ log::error!("{}:{}: {:#}", caller.file(), caller.line(), err);
}
})
.detach();
diff --git a/crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift b/crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift
index 40c1319e8f9111dac6139e723699ba76fd8d6111..40d3641db23afcbac801b7f5f2daa15411c15f72 100644
--- a/crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift
+++ b/crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift
@@ -8,14 +8,18 @@ class LKRoomDelegate: RoomDelegate {
var onDidDisconnect: @convention(c) (UnsafeRawPointer) -> Void
var onDidSubscribeToRemoteAudioTrack: @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void
var onDidUnsubscribeFromRemoteAudioTrack: @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void
+ var onMuteChangedFromRemoteAudioTrack: @convention(c) (UnsafeRawPointer, CFString, Bool) -> Void
+ var onActiveSpeakersChanged: @convention(c) (UnsafeRawPointer, CFArray) -> Void
var onDidSubscribeToRemoteVideoTrack: @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void
var onDidUnsubscribeFromRemoteVideoTrack: @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void
-
+
init(
data: UnsafeRawPointer,
onDidDisconnect: @escaping @convention(c) (UnsafeRawPointer) -> Void,
onDidSubscribeToRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void,
onDidUnsubscribeFromRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void,
+ onMuteChangedFromRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, Bool) -> Void,
+ onActiveSpeakersChanged: @convention(c) (UnsafeRawPointer, CFArray) -> Void,
onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void,
onDidUnsubscribeFromRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void)
{
@@ -25,6 +29,8 @@ class LKRoomDelegate: RoomDelegate {
self.onDidUnsubscribeFromRemoteAudioTrack = onDidUnsubscribeFromRemoteAudioTrack
self.onDidSubscribeToRemoteVideoTrack = onDidSubscribeToRemoteVideoTrack
self.onDidUnsubscribeFromRemoteVideoTrack = onDidUnsubscribeFromRemoteVideoTrack
+ self.onMuteChangedFromRemoteAudioTrack = onMuteChangedFromRemoteAudioTrack
+ self.onActiveSpeakersChanged = onActiveSpeakersChanged
}
func room(_ room: Room, didUpdate connectionState: ConnectionState, oldValue: ConnectionState) {
@@ -40,6 +46,17 @@ class LKRoomDelegate: RoomDelegate {
self.onDidSubscribeToRemoteAudioTrack(self.data, participant.identity as CFString, track.sid! as CFString, Unmanaged.passUnretained(track).toOpaque())
}
}
+
+ func room(_ room: Room, participant: Participant, didUpdate publication: TrackPublication, muted: Bool) {
+ if publication.kind == .audio {
+ self.onMuteChangedFromRemoteAudioTrack(self.data, publication.sid as CFString, muted)
+ }
+ }
+
+ func room(_ room: Room, didUpdate speakers: [Participant]) {
+ guard let speaker_ids = speakers.compactMap({ $0.identity as CFString }) as CFArray? else { return }
+ self.onActiveSpeakersChanged(self.data, speaker_ids)
+ }
func room(_ room: Room, participant: RemoteParticipant, didUnsubscribe publication: RemoteTrackPublication, track: Track) {
if track.kind == .video {
@@ -89,6 +106,8 @@ public func LKRoomDelegateCreate(
onDidDisconnect: @escaping @convention(c) (UnsafeRawPointer) -> Void,
onDidSubscribeToRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void,
onDidUnsubscribeFromRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void,
+ onMuteChangedFromRemoteAudioTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, Bool) -> Void,
+ onActiveSpeakerChanged: @escaping @convention(c) (UnsafeRawPointer, CFArray) -> Void,
onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void,
onDidUnsubscribeFromRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void
) -> UnsafeMutableRawPointer {
@@ -97,6 +116,8 @@ public func LKRoomDelegateCreate(
onDidDisconnect: onDidDisconnect,
onDidSubscribeToRemoteAudioTrack: onDidSubscribeToRemoteAudioTrack,
onDidUnsubscribeFromRemoteAudioTrack: onDidUnsubscribeFromRemoteAudioTrack,
+ onMuteChangedFromRemoteAudioTrack: onMuteChangedFromRemoteAudioTrack,
+ onActiveSpeakersChanged: onActiveSpeakerChanged,
onDidSubscribeToRemoteVideoTrack: onDidSubscribeToRemoteVideoTrack,
onDidUnsubscribeFromRemoteVideoTrack: onDidUnsubscribeFromRemoteVideoTrack
)
@@ -169,6 +190,18 @@ public func LKRoomAudioTracksForRemoteParticipant(room: UnsafeRawPointer, partic
return nil;
}
+@_cdecl("LKRoomAudioTrackPublicationsForRemoteParticipant")
+public func LKRoomAudioTrackPublicationsForRemoteParticipant(room: UnsafeRawPointer, participantId: CFString) -> CFArray? {
+ let room = Unmanaged.fromOpaque(room).takeUnretainedValue()
+
+ for (_, participant) in room.remoteParticipants {
+ if participant.identity == participantId as String {
+ return participant.audioTracks.compactMap { $0 as? RemoteTrackPublication } as CFArray?
+ }
+ }
+
+ return nil;
+}
@_cdecl("LKRoomVideoTracksForRemoteParticipant")
public func LKRoomVideoTracksForRemoteParticipant(room: UnsafeRawPointer, participantId: CFString) -> CFArray? {
@@ -201,19 +234,6 @@ public func LKCreateScreenShareTrackForDisplay(display: UnsafeMutableRawPointer)
return Unmanaged.passRetained(track).toOpaque()
}
-@_cdecl("LKRemoteAudioTrackStart")
-public func LKRemoteAudioTrackStart(track: UnsafeRawPointer, onStart: @escaping @convention(c) (UnsafeRawPointer, Bool) -> Void, callbackData: UnsafeRawPointer) {
- let track = Unmanaged