diff --git a/README.md b/README.md
index 6f5c6de..224bc9a 100644
--- a/README.md
+++ b/README.md
@@ -61,19 +61,19 @@ cd Tela-icon-theme
-  |
-  |
-  |
+  |
+  |
+  |
-  |
-  |
-  |
+  |
+  |
+  |
-  |
-  |
-  |
+  |
+  |
+  |
diff --git a/assets/bluetooth.png b/assets/screenshots/bluetooth.png
similarity index 100%
rename from assets/bluetooth.png
rename to assets/screenshots/bluetooth.png
diff --git a/assets/cliphist.png b/assets/screenshots/cliphist.png
similarity index 100%
rename from assets/cliphist.png
rename to assets/screenshots/cliphist.png
diff --git a/assets/emoji.png b/assets/screenshots/emoji.png
similarity index 100%
rename from assets/emoji.png
rename to assets/screenshots/emoji.png
diff --git a/assets/home.png b/assets/screenshots/home.png
similarity index 100%
rename from assets/home.png
rename to assets/screenshots/home.png
diff --git a/assets/logo.svg b/assets/screenshots/logo.svg
similarity index 100%
rename from assets/logo.svg
rename to assets/screenshots/logo.svg
diff --git a/assets/notification.png b/assets/screenshots/notification.png
similarity index 100%
rename from assets/notification.png
rename to assets/screenshots/notification.png
diff --git a/assets/osd.png b/assets/screenshots/osd.png
similarity index 100%
rename from assets/osd.png
rename to assets/screenshots/osd.png
diff --git a/assets/powermenu.png b/assets/screenshots/powermenu.png
similarity index 100%
rename from assets/powermenu.png
rename to assets/screenshots/powermenu.png
diff --git a/assets/shrunner.png b/assets/screenshots/shrunner.png
similarity index 100%
rename from assets/shrunner.png
rename to assets/screenshots/shrunner.png
diff --git a/assets/todo.png b/assets/screenshots/todo.png
similarity index 100%
rename from assets/todo.png
rename to assets/screenshots/todo.png
diff --git a/assets/wallpaper.png b/assets/screenshots/wallpaper.png
similarity index 100%
rename from assets/wallpaper.png
rename to assets/screenshots/wallpaper.png
diff --git a/assets/wallpaper/example-1.png b/assets/wallpaper/example-1.png
new file mode 100644
index 0000000..137ceee
Binary files /dev/null and b/assets/wallpaper/example-1.png differ
diff --git a/assets/wallpaper/example-2.png b/assets/wallpaper/example-2.png
new file mode 100644
index 0000000..6d22cf9
Binary files /dev/null and b/assets/wallpaper/example-2.png differ
diff --git a/assets/wallpaper/example-3.jpg b/assets/wallpaper/example-3.jpg
new file mode 100755
index 0000000..5c2fd0d
Binary files /dev/null and b/assets/wallpaper/example-3.jpg differ
diff --git a/assets/wallpaper/example-4.jpeg b/assets/wallpaper/example-4.jpeg
new file mode 100644
index 0000000..7ca7ae6
Binary files /dev/null and b/assets/wallpaper/example-4.jpeg differ
diff --git a/assets/wallpaper/example-5.jpg b/assets/wallpaper/example-5.jpg
new file mode 100644
index 0000000..eced4ab
Binary files /dev/null and b/assets/wallpaper/example-5.jpg differ
diff --git a/config/assets/config.json b/config/assets/config.json
new file mode 100644
index 0000000..2f0a891
--- /dev/null
+++ b/config/assets/config.json
@@ -0,0 +1 @@
+{"prefix_restart": "SHIFT ALT", "suffix_restart": "T", "prefix_bluetooth": "ALT", "suffix_bluetooth": "B", "prefix_emoji": "SUPER", "suffix_emoji": "E", "prefix_cliphist": "SUPER", "suffix_cliphist": "V", "prefix_todo": "SUPER", "suffix_todo": "T", "prefix_sh": "SUPER", "suffix_sh": "S", "prefix_walls": "SUPER", "suffix_walls": "W", "prefix_screenshotregion": "SUPER", "suffix_screenshotregion": "Z", "prefix_screenshot": "", "suffix_screenshot": "Print", "prefix_screencast": "SUPER", "suffix_screencast": "R", "prefix_launcher": "SUPER", "suffix_launcher": "D", "prefix_power": "SUPER", "suffix_power": "X", "prefix_toggle": "SUPER", "suffix_toggle": "H", "prefix_randomwallpaper": "ALT SHIFT", "suffix_randomwallpaper": "W", "wallpapers_dir": "/home/sankalp/Pictures/wallpapers"}
\ No newline at end of file
diff --git a/config/assets/emoji.json b/config/assets/emoji.json
new file mode 100644
index 0000000..fa174ff
--- /dev/null
+++ b/config/assets/emoji.json
@@ -0,0 +1,15509 @@
+{
+ "๐": {
+ "name": "grinning face",
+ "slug": "grinning_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "grinning face with big eyes",
+ "slug": "grinning_face_with_big_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "grinning face with smiling eyes",
+ "slug": "grinning_face_with_smiling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "beaming face with smiling eyes",
+ "slug": "beaming_face_with_smiling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "grinning squinting face",
+ "slug": "grinning_squinting_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "grinning face with sweat",
+ "slug": "grinning_face_with_sweat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คฃ": {
+ "name": "rolling on the floor laughing",
+ "slug": "rolling_on_the_floor_laughing",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "face with tears of joy",
+ "slug": "face_with_tears_of_joy",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "slightly smiling face",
+ "slug": "slightly_smiling_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "upside-down face",
+ "slug": "upside_down_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซ ": {
+ "name": "melting face",
+ "slug": "melting_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "winking face",
+ "slug": "winking_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smiling face with smiling eyes",
+ "slug": "smiling_face_with_smiling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smiling face with halo",
+ "slug": "smiling_face_with_halo",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฐ": {
+ "name": "smiling face with hearts",
+ "slug": "smiling_face_with_hearts",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smiling face with heart-eyes",
+ "slug": "smiling_face_with_heart_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คฉ": {
+ "name": "star-struck",
+ "slug": "star_struck",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "face blowing a kiss",
+ "slug": "face_blowing_a_kiss",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kissing face",
+ "slug": "kissing_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โบ๏ธ": {
+ "name": "smiling face",
+ "slug": "smiling_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kissing face with closed eyes",
+ "slug": "kissing_face_with_closed_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kissing face with smiling eyes",
+ "slug": "kissing_face_with_smiling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฒ": {
+ "name": "smiling face with tear",
+ "slug": "smiling_face_with_tear",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "face savoring food",
+ "slug": "face_savoring_food",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "face with tongue",
+ "slug": "face_with_tongue",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "winking face with tongue",
+ "slug": "winking_face_with_tongue",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คช": {
+ "name": "zany face",
+ "slug": "zany_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "squinting face with tongue",
+ "slug": "squinting_face_with_tongue",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "money-mouth face",
+ "slug": "money_mouth_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "smiling face with open hands",
+ "slug": "smiling_face_with_open_hands",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐คญ": {
+ "name": "face with hand over mouth",
+ "slug": "face_with_hand_over_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ซข": {
+ "name": "face with open eyes and hand over mouth",
+ "slug": "face_with_open_eyes_and_hand_over_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ซฃ": {
+ "name": "face with peeking eye",
+ "slug": "face_with_peeking_eye",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐คซ": {
+ "name": "shushing face",
+ "slug": "shushing_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "thinking face",
+ "slug": "thinking_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซก": {
+ "name": "saluting face",
+ "slug": "saluting_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "zipper-mouth face",
+ "slug": "zipper_mouth_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐คจ": {
+ "name": "face with raised eyebrow",
+ "slug": "face_with_raised_eyebrow",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "neutral face",
+ "slug": "neutral_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "expressionless face",
+ "slug": "expressionless_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "face without mouth",
+ "slug": "face_without_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซฅ": {
+ "name": "dotted line face",
+ "slug": "dotted_line_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ถโ๐ซ๏ธ": {
+ "name": "face in clouds",
+ "slug": "face_in_clouds",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smirking face",
+ "slug": "smirking_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "unamused face",
+ "slug": "unamused_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "face with rolling eyes",
+ "slug": "face_with_rolling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "grimacing face",
+ "slug": "grimacing_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฎโ๐จ": {
+ "name": "face exhaling",
+ "slug": "face_exhaling",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": false
+ },
+ "๐คฅ": {
+ "name": "lying face",
+ "slug": "lying_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ซจ": {
+ "name": "shaking face",
+ "slug": "shaking_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐โโ๏ธ": {
+ "name": "head shaking horizontally",
+ "slug": "head_shaking_horizontally",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐โโ๏ธ": {
+ "name": "head shaking vertically",
+ "slug": "head_shaking_vertically",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "relieved face",
+ "slug": "relieved_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pensive face",
+ "slug": "pensive_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "sleepy face",
+ "slug": "sleepy_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คค": {
+ "name": "drooling face",
+ "slug": "drooling_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "sleeping face",
+ "slug": "sleeping_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "face with medical mask",
+ "slug": "face_with_medical_mask",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "face with thermometer",
+ "slug": "face_with_thermometer",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "face with head-bandage",
+ "slug": "face_with_head_bandage",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐คข": {
+ "name": "nauseated face",
+ "slug": "nauseated_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐คฎ": {
+ "name": "face vomiting",
+ "slug": "face_vomiting",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐คง": {
+ "name": "sneezing face",
+ "slug": "sneezing_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅต": {
+ "name": "hot face",
+ "slug": "hot_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅถ": {
+ "name": "cold face",
+ "slug": "cold_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅด": {
+ "name": "woozy face",
+ "slug": "woozy_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "face with crossed-out eyes",
+ "slug": "face_with_crossed_out_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ตโ๐ซ": {
+ "name": "face with spiral eyes",
+ "slug": "face_with_spiral_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": false
+ },
+ "๐คฏ": {
+ "name": "exploding head",
+ "slug": "exploding_head",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ค ": {
+ "name": "cowboy hat face",
+ "slug": "cowboy_hat_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅณ": {
+ "name": "partying face",
+ "slug": "partying_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅธ": {
+ "name": "disguised face",
+ "slug": "disguised_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smiling face with sunglasses",
+ "slug": "smiling_face_with_sunglasses",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "nerd face",
+ "slug": "nerd_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "face with monocle",
+ "slug": "face_with_monocle",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "confused face",
+ "slug": "confused_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซค": {
+ "name": "face with diagonal mouth",
+ "slug": "face_with_diagonal_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "worried face",
+ "slug": "worried_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "slightly frowning face",
+ "slug": "slightly_frowning_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โน๏ธ": {
+ "name": "frowning face",
+ "slug": "frowning_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "face with open mouth",
+ "slug": "face_with_open_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "hushed face",
+ "slug": "hushed_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "astonished face",
+ "slug": "astonished_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "flushed face",
+ "slug": "flushed_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅบ": {
+ "name": "pleading face",
+ "slug": "pleading_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅน": {
+ "name": "face holding back tears",
+ "slug": "face_holding_back_tears",
+ "group": "Smileys & Emotion",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "frowning face with open mouth",
+ "slug": "frowning_face_with_open_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "anguished face",
+ "slug": "anguished_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "fearful face",
+ "slug": "fearful_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "anxious face with sweat",
+ "slug": "anxious_face_with_sweat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "sad but relieved face",
+ "slug": "sad_but_relieved_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "crying face",
+ "slug": "crying_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "loudly crying face",
+ "slug": "loudly_crying_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "face screaming in fear",
+ "slug": "face_screaming_in_fear",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "confounded face",
+ "slug": "confounded_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "persevering face",
+ "slug": "persevering_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "disappointed face",
+ "slug": "disappointed_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "downcast face with sweat",
+ "slug": "downcast_face_with_sweat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "weary face",
+ "slug": "weary_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "tired face",
+ "slug": "tired_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅฑ": {
+ "name": "yawning face",
+ "slug": "yawning_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "face with steam from nose",
+ "slug": "face_with_steam_from_nose",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "enraged face",
+ "slug": "enraged_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "angry face",
+ "slug": "angry_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คฌ": {
+ "name": "face with symbols on mouth",
+ "slug": "face_with_symbols_on_mouth",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "smiling face with horns",
+ "slug": "smiling_face_with_horns",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "angry face with horns",
+ "slug": "angry_face_with_horns",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "skull",
+ "slug": "skull",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ ๏ธ": {
+ "name": "skull and crossbones",
+ "slug": "skull_and_crossbones",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "pile of poo",
+ "slug": "pile_of_poo",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คก": {
+ "name": "clown face",
+ "slug": "clown_face",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "ogre",
+ "slug": "ogre",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "goblin",
+ "slug": "goblin",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "ghost",
+ "slug": "ghost",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "alien",
+ "slug": "alien",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "alien monster",
+ "slug": "alien_monster",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "robot",
+ "slug": "robot",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "grinning cat",
+ "slug": "grinning_cat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "grinning cat with smiling eyes",
+ "slug": "grinning_cat_with_smiling_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "cat with tears of joy",
+ "slug": "cat_with_tears_of_joy",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "smiling cat with heart-eyes",
+ "slug": "smiling_cat_with_heart_eyes",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "cat with wry smile",
+ "slug": "cat_with_wry_smile",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "kissing cat",
+ "slug": "kissing_cat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "weary cat",
+ "slug": "weary_cat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "crying cat",
+ "slug": "crying_cat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "pouting cat",
+ "slug": "pouting_cat",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "see-no-evil monkey",
+ "slug": "see_no_evil_monkey",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "hear-no-evil monkey",
+ "slug": "hear_no_evil_monkey",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "speak-no-evil monkey",
+ "slug": "speak_no_evil_monkey",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "love letter",
+ "slug": "love_letter",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "heart with arrow",
+ "slug": "heart_with_arrow",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "heart with ribbon",
+ "slug": "heart_with_ribbon",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sparkling heart",
+ "slug": "sparkling_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "growing heart",
+ "slug": "growing_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "beating heart",
+ "slug": "beating_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "revolving hearts",
+ "slug": "revolving_hearts",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "two hearts",
+ "slug": "two_hearts",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "heart decoration",
+ "slug": "heart_decoration",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฃ๏ธ": {
+ "name": "heart exclamation",
+ "slug": "heart_exclamation",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "broken heart",
+ "slug": "broken_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โค๏ธโ๐ฅ": {
+ "name": "heart on fire",
+ "slug": "heart_on_fire",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": false
+ },
+ "โค๏ธโ๐ฉน": {
+ "name": "mending heart",
+ "slug": "mending_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": false
+ },
+ "โค๏ธ": {
+ "name": "red heart",
+ "slug": "red_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉท": {
+ "name": "pink heart",
+ "slug": "pink_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐งก": {
+ "name": "orange heart",
+ "slug": "orange_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "yellow heart",
+ "slug": "yellow_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "green heart",
+ "slug": "green_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "blue heart",
+ "slug": "blue_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉต": {
+ "name": "light blue heart",
+ "slug": "light_blue_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "purple heart",
+ "slug": "purple_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "brown heart",
+ "slug": "brown_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "black heart",
+ "slug": "black_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฉถ": {
+ "name": "grey heart",
+ "slug": "grey_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "white heart",
+ "slug": "white_heart",
+ "group": "Smileys & Emotion",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kiss mark",
+ "slug": "kiss_mark",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "hundred points",
+ "slug": "hundred_points",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "anger symbol",
+ "slug": "anger_symbol",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "collision",
+ "slug": "collision",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "dizzy",
+ "slug": "dizzy",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "sweat droplets",
+ "slug": "sweat_droplets",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "dashing away",
+ "slug": "dashing_away",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธ": {
+ "name": "hole",
+ "slug": "hole",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "speech balloon",
+ "slug": "speech_balloon",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธโ๐จ๏ธ": {
+ "name": "eye in speech bubble",
+ "slug": "eye_in_speech_bubble",
+ "group": "Smileys & Emotion",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๏ธ": {
+ "name": "left speech bubble",
+ "slug": "left_speech_bubble",
+ "group": "Smileys & Emotion",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ๏ธ": {
+ "name": "right anger bubble",
+ "slug": "right_anger_bubble",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "thought balloon",
+ "slug": "thought_balloon",
+ "group": "Smileys & Emotion",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "ZZZ",
+ "slug": "zzz",
+ "group": "Smileys & Emotion",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "waving hand",
+ "slug": "waving_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ค": {
+ "name": "raised back of hand",
+ "slug": "raised_back_of_hand",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐๏ธ": {
+ "name": "hand with fingers splayed",
+ "slug": "hand_with_fingers_splayed",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "โ": {
+ "name": "raised hand",
+ "slug": "raised_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "vulcan salute",
+ "slug": "vulcan_salute",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ซฑ": {
+ "name": "rightwards hand",
+ "slug": "rightwards_hand",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ซฒ": {
+ "name": "leftwards hand",
+ "slug": "leftwards_hand",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ซณ": {
+ "name": "palm down hand",
+ "slug": "palm_down_hand",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ซด": {
+ "name": "palm up hand",
+ "slug": "palm_up_hand",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ซท": {
+ "name": "leftwards pushing hand",
+ "slug": "leftwards_pushing_hand",
+ "group": "People & Body",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.0"
+ },
+ "๐ซธ": {
+ "name": "rightwards pushing hand",
+ "slug": "rightwards_pushing_hand",
+ "group": "People & Body",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.0"
+ },
+ "๐": {
+ "name": "OK hand",
+ "slug": "ok_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ค": {
+ "name": "pinched fingers",
+ "slug": "pinched_fingers",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ค": {
+ "name": "pinching hand",
+ "slug": "pinching_hand",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "โ๏ธ": {
+ "name": "victory hand",
+ "slug": "victory_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ค": {
+ "name": "crossed fingers",
+ "slug": "crossed_fingers",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ซฐ": {
+ "name": "hand with index finger and thumb crossed",
+ "slug": "hand_with_index_finger_and_thumb_crossed",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ค": {
+ "name": "love-you gesture",
+ "slug": "love_you_gesture",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ค": {
+ "name": "sign of the horns",
+ "slug": "sign_of_the_horns",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ค": {
+ "name": "call me hand",
+ "slug": "call_me_hand",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐": {
+ "name": "backhand index pointing left",
+ "slug": "backhand_index_pointing_left",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "backhand index pointing right",
+ "slug": "backhand_index_pointing_right",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "backhand index pointing up",
+ "slug": "backhand_index_pointing_up",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "middle finger",
+ "slug": "middle_finger",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "backhand index pointing down",
+ "slug": "backhand_index_pointing_down",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "โ๏ธ": {
+ "name": "index pointing up",
+ "slug": "index_pointing_up",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ซต": {
+ "name": "index pointing at the viewer",
+ "slug": "index_pointing_at_the_viewer",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐": {
+ "name": "thumbs up",
+ "slug": "thumbs_up",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "thumbs down",
+ "slug": "thumbs_down",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "โ": {
+ "name": "raised fist",
+ "slug": "raised_fist",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "oncoming fist",
+ "slug": "oncoming_fist",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ค": {
+ "name": "left-facing fist",
+ "slug": "left_facing_fist",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ค": {
+ "name": "right-facing fist",
+ "slug": "right_facing_fist",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐": {
+ "name": "clapping hands",
+ "slug": "clapping_hands",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "raising hands",
+ "slug": "raising_hands",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ซถ": {
+ "name": "heart hands",
+ "slug": "heart_hands",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐": {
+ "name": "open hands",
+ "slug": "open_hands",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐คฒ": {
+ "name": "palms up together",
+ "slug": "palms_up_together",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ค": {
+ "name": "handshake",
+ "slug": "handshake",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐": {
+ "name": "folded hands",
+ "slug": "folded_hands",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "โ๏ธ": {
+ "name": "writing hand",
+ "slug": "writing_hand",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐
": {
+ "name": "nail polish",
+ "slug": "nail_polish",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐คณ": {
+ "name": "selfie",
+ "slug": "selfie",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ช": {
+ "name": "flexed biceps",
+ "slug": "flexed_biceps",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฆพ": {
+ "name": "mechanical arm",
+ "slug": "mechanical_arm",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฟ": {
+ "name": "mechanical leg",
+ "slug": "mechanical_leg",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆต": {
+ "name": "leg",
+ "slug": "leg",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆถ": {
+ "name": "foot",
+ "slug": "foot",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐": {
+ "name": "ear",
+ "slug": "ear",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฆป": {
+ "name": "ear with hearing aid",
+ "slug": "ear_with_hearing_aid",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐": {
+ "name": "nose",
+ "slug": "nose",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง ": {
+ "name": "brain",
+ "slug": "brain",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "anatomical heart",
+ "slug": "anatomical_heart",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "lungs",
+ "slug": "lungs",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆท": {
+ "name": "tooth",
+ "slug": "tooth",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆด": {
+ "name": "bone",
+ "slug": "bone",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "eyes",
+ "slug": "eyes",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "eye",
+ "slug": "eye",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "tongue",
+ "slug": "tongue",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mouth",
+ "slug": "mouth",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซฆ": {
+ "name": "biting lip",
+ "slug": "biting_lip",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "baby",
+ "slug": "baby",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง": {
+ "name": "child",
+ "slug": "child",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ฆ": {
+ "name": "boy",
+ "slug": "boy",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง": {
+ "name": "girl",
+ "slug": "girl",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง": {
+ "name": "person",
+ "slug": "person",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ฑ": {
+ "name": "person blond hair",
+ "slug": "person_blond_hair",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐จ": {
+ "name": "man",
+ "slug": "man",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง": {
+ "name": "person beard",
+ "slug": "person_beard",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man beard",
+ "slug": "man_beard",
+ "group": "People & Body",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman beard",
+ "slug": "woman_beard",
+ "group": "People & Body",
+ "emoji_version": "13.1",
+ "unicode_version": "13.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐จโ๐ฆฐ": {
+ "name": "man red hair",
+ "slug": "man_red_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐จโ๐ฆฑ": {
+ "name": "man curly hair",
+ "slug": "man_curly_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐จโ๐ฆณ": {
+ "name": "man white hair",
+ "slug": "man_white_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐จโ๐ฆฒ": {
+ "name": "man bald",
+ "slug": "man_bald",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฉ": {
+ "name": "woman",
+ "slug": "woman",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฉโ๐ฆฐ": {
+ "name": "woman red hair",
+ "slug": "woman_red_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐งโ๐ฆฐ": {
+ "name": "person red hair",
+ "slug": "person_red_hair",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐ฉโ๐ฆฑ": {
+ "name": "woman curly hair",
+ "slug": "woman_curly_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐งโ๐ฆฑ": {
+ "name": "person curly hair",
+ "slug": "person_curly_hair",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐ฉโ๐ฆณ": {
+ "name": "woman white hair",
+ "slug": "woman_white_hair",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐งโ๐ฆณ": {
+ "name": "person white hair",
+ "slug": "person_white_hair",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐ฉโ๐ฆฒ": {
+ "name": "woman bald",
+ "slug": "woman_bald",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐งโ๐ฆฒ": {
+ "name": "person bald",
+ "slug": "person_bald",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐ฑโโ๏ธ": {
+ "name": "woman blond hair",
+ "slug": "woman_blond_hair",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฑโโ๏ธ": {
+ "name": "man blond hair",
+ "slug": "man_blond_hair",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ง": {
+ "name": "older person",
+ "slug": "older_person",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ด": {
+ "name": "old man",
+ "slug": "old_man",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ต": {
+ "name": "old woman",
+ "slug": "old_woman",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "person frowning",
+ "slug": "person_frowning",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man frowning",
+ "slug": "man_frowning",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman frowning",
+ "slug": "woman_frowning",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person pouting",
+ "slug": "person_pouting",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man pouting",
+ "slug": "man_pouting",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman pouting",
+ "slug": "woman_pouting",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐
": {
+ "name": "person gesturing NO",
+ "slug": "person_gesturing_no",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐
โโ๏ธ": {
+ "name": "man gesturing NO",
+ "slug": "man_gesturing_no",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐
โโ๏ธ": {
+ "name": "woman gesturing NO",
+ "slug": "woman_gesturing_no",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person gesturing OK",
+ "slug": "person_gesturing_ok",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man gesturing OK",
+ "slug": "man_gesturing_ok",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman gesturing OK",
+ "slug": "woman_gesturing_ok",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person tipping hand",
+ "slug": "person_tipping_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man tipping hand",
+ "slug": "man_tipping_hand",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman tipping hand",
+ "slug": "woman_tipping_hand",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person raising hand",
+ "slug": "person_raising_hand",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man raising hand",
+ "slug": "man_raising_hand",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman raising hand",
+ "slug": "woman_raising_hand",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ง": {
+ "name": "deaf person",
+ "slug": "deaf_person",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "deaf man",
+ "slug": "deaf_man",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "deaf woman",
+ "slug": "deaf_woman",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐": {
+ "name": "person bowing",
+ "slug": "person_bowing",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man bowing",
+ "slug": "man_bowing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman bowing",
+ "slug": "woman_bowing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คฆ": {
+ "name": "person facepalming",
+ "slug": "person_facepalming",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คฆโโ๏ธ": {
+ "name": "man facepalming",
+ "slug": "man_facepalming",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คฆโโ๏ธ": {
+ "name": "woman facepalming",
+ "slug": "woman_facepalming",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คท": {
+ "name": "person shrugging",
+ "slug": "person_shrugging",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คทโโ๏ธ": {
+ "name": "man shrugging",
+ "slug": "man_shrugging",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คทโโ๏ธ": {
+ "name": "woman shrugging",
+ "slug": "woman_shrugging",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "health worker",
+ "slug": "health_worker",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโโ๏ธ": {
+ "name": "man health worker",
+ "slug": "man_health_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโโ๏ธ": {
+ "name": "woman health worker",
+ "slug": "woman_health_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐": {
+ "name": "student",
+ "slug": "student",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐": {
+ "name": "man student",
+ "slug": "man_student",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐": {
+ "name": "woman student",
+ "slug": "woman_student",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ซ": {
+ "name": "teacher",
+ "slug": "teacher",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ซ": {
+ "name": "man teacher",
+ "slug": "man_teacher",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ซ": {
+ "name": "woman teacher",
+ "slug": "woman_teacher",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "judge",
+ "slug": "judge",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโโ๏ธ": {
+ "name": "man judge",
+ "slug": "man_judge",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโโ๏ธ": {
+ "name": "woman judge",
+ "slug": "woman_judge",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐พ": {
+ "name": "farmer",
+ "slug": "farmer",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐พ": {
+ "name": "man farmer",
+ "slug": "man_farmer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐พ": {
+ "name": "woman farmer",
+ "slug": "woman_farmer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ณ": {
+ "name": "cook",
+ "slug": "cook",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ณ": {
+ "name": "man cook",
+ "slug": "man_cook",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ณ": {
+ "name": "woman cook",
+ "slug": "woman_cook",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ง": {
+ "name": "mechanic",
+ "slug": "mechanic",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ง": {
+ "name": "man mechanic",
+ "slug": "man_mechanic",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ง": {
+ "name": "woman mechanic",
+ "slug": "woman_mechanic",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ญ": {
+ "name": "factory worker",
+ "slug": "factory_worker",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ญ": {
+ "name": "man factory worker",
+ "slug": "man_factory_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ญ": {
+ "name": "woman factory worker",
+ "slug": "woman_factory_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ผ": {
+ "name": "office worker",
+ "slug": "office_worker",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ผ": {
+ "name": "man office worker",
+ "slug": "man_office_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ผ": {
+ "name": "woman office worker",
+ "slug": "woman_office_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ฌ": {
+ "name": "scientist",
+ "slug": "scientist",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ฌ": {
+ "name": "man scientist",
+ "slug": "man_scientist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ฌ": {
+ "name": "woman scientist",
+ "slug": "woman_scientist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ป": {
+ "name": "technologist",
+ "slug": "technologist",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ป": {
+ "name": "man technologist",
+ "slug": "man_technologist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ป": {
+ "name": "woman technologist",
+ "slug": "woman_technologist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐ค": {
+ "name": "singer",
+ "slug": "singer",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐ค": {
+ "name": "man singer",
+ "slug": "man_singer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐ค": {
+ "name": "woman singer",
+ "slug": "woman_singer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐จ": {
+ "name": "artist",
+ "slug": "artist",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐จ": {
+ "name": "man artist",
+ "slug": "man_artist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐จ": {
+ "name": "woman artist",
+ "slug": "woman_artist",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "pilot",
+ "slug": "pilot",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโโ๏ธ": {
+ "name": "man pilot",
+ "slug": "man_pilot",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโโ๏ธ": {
+ "name": "woman pilot",
+ "slug": "woman_pilot",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐": {
+ "name": "astronaut",
+ "slug": "astronaut",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐": {
+ "name": "man astronaut",
+ "slug": "man_astronaut",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐": {
+ "name": "woman astronaut",
+ "slug": "woman_astronaut",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐": {
+ "name": "firefighter",
+ "slug": "firefighter",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐จโ๐": {
+ "name": "man firefighter",
+ "slug": "man_firefighter",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฉโ๐": {
+ "name": "woman firefighter",
+ "slug": "woman_firefighter",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฎ": {
+ "name": "police officer",
+ "slug": "police_officer",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฎโโ๏ธ": {
+ "name": "man police officer",
+ "slug": "man_police_officer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฎโโ๏ธ": {
+ "name": "woman police officer",
+ "slug": "woman_police_officer",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ต๏ธ": {
+ "name": "detective",
+ "slug": "detective",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "2.0"
+ },
+ "๐ต๏ธโโ๏ธ": {
+ "name": "man detective",
+ "slug": "man_detective",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ต๏ธโโ๏ธ": {
+ "name": "woman detective",
+ "slug": "woman_detective",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "guard",
+ "slug": "guard",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man guard",
+ "slug": "man_guard",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman guard",
+ "slug": "woman_guard",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฅท": {
+ "name": "ninja",
+ "slug": "ninja",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ท": {
+ "name": "construction worker",
+ "slug": "construction_worker",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ทโโ๏ธ": {
+ "name": "man construction worker",
+ "slug": "man_construction_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ทโโ๏ธ": {
+ "name": "woman construction worker",
+ "slug": "woman_construction_worker",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ซ
": {
+ "name": "person with crown",
+ "slug": "person_with_crown",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐คด": {
+ "name": "prince",
+ "slug": "prince",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ธ": {
+ "name": "princess",
+ "slug": "princess",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ณ": {
+ "name": "person wearing turban",
+ "slug": "person_wearing_turban",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ณโโ๏ธ": {
+ "name": "man wearing turban",
+ "slug": "man_wearing_turban",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ณโโ๏ธ": {
+ "name": "woman wearing turban",
+ "slug": "woman_wearing_turban",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฒ": {
+ "name": "person with skullcap",
+ "slug": "person_with_skullcap",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ง": {
+ "name": "woman with headscarf",
+ "slug": "woman_with_headscarf",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐คต": {
+ "name": "person in tuxedo",
+ "slug": "person_in_tuxedo",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คตโโ๏ธ": {
+ "name": "man in tuxedo",
+ "slug": "man_in_tuxedo",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐คตโโ๏ธ": {
+ "name": "woman in tuxedo",
+ "slug": "woman_in_tuxedo",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ฐ": {
+ "name": "person with veil",
+ "slug": "person_with_veil",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฐโโ๏ธ": {
+ "name": "man with veil",
+ "slug": "man_with_veil",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ฐโโ๏ธ": {
+ "name": "woman with veil",
+ "slug": "woman_with_veil",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐คฐ": {
+ "name": "pregnant woman",
+ "slug": "pregnant_woman",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ซ": {
+ "name": "pregnant man",
+ "slug": "pregnant_man",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐ซ": {
+ "name": "pregnant person",
+ "slug": "pregnant_person",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "14.0"
+ },
+ "๐คฑ": {
+ "name": "breast-feeding",
+ "slug": "breast_feeding",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ฉโ๐ผ": {
+ "name": "woman feeding baby",
+ "slug": "woman_feeding_baby",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐จโ๐ผ": {
+ "name": "man feeding baby",
+ "slug": "man_feeding_baby",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐งโ๐ผ": {
+ "name": "person feeding baby",
+ "slug": "person_feeding_baby",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ผ": {
+ "name": "baby angel",
+ "slug": "baby_angel",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐
": {
+ "name": "Santa Claus",
+ "slug": "santa_claus",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐คถ": {
+ "name": "Mrs. Claus",
+ "slug": "mrs_claus",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐งโ๐": {
+ "name": "mx claus",
+ "slug": "mx_claus",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.0"
+ },
+ "๐ฆธ": {
+ "name": "superhero",
+ "slug": "superhero",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆธโโ๏ธ": {
+ "name": "man superhero",
+ "slug": "man_superhero",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆธโโ๏ธ": {
+ "name": "woman superhero",
+ "slug": "woman_superhero",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆน": {
+ "name": "supervillain",
+ "slug": "supervillain",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆนโโ๏ธ": {
+ "name": "man supervillain",
+ "slug": "man_supervillain",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ฆนโโ๏ธ": {
+ "name": "woman supervillain",
+ "slug": "woman_supervillain",
+ "group": "People & Body",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "11.0"
+ },
+ "๐ง": {
+ "name": "mage",
+ "slug": "mage",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man mage",
+ "slug": "man_mage",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman mage",
+ "slug": "woman_mage",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "fairy",
+ "slug": "fairy",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man fairy",
+ "slug": "man_fairy",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman fairy",
+ "slug": "woman_fairy",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "vampire",
+ "slug": "vampire",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man vampire",
+ "slug": "man_vampire",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman vampire",
+ "slug": "woman_vampire",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "merperson",
+ "slug": "merperson",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "merman",
+ "slug": "merman",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "mermaid",
+ "slug": "mermaid",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "elf",
+ "slug": "elf",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man elf",
+ "slug": "man_elf",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman elf",
+ "slug": "woman_elf",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "genie",
+ "slug": "genie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งโโ๏ธ": {
+ "name": "man genie",
+ "slug": "man_genie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman genie",
+ "slug": "woman_genie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "zombie",
+ "slug": "zombie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งโโ๏ธ": {
+ "name": "man zombie",
+ "slug": "man_zombie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman zombie",
+ "slug": "woman_zombie",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "troll",
+ "slug": "troll",
+ "group": "People & Body",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "person getting massage",
+ "slug": "person_getting_massage",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man getting massage",
+ "slug": "man_getting_massage",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman getting massage",
+ "slug": "woman_getting_massage",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person getting haircut",
+ "slug": "person_getting_haircut",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man getting haircut",
+ "slug": "man_getting_haircut",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman getting haircut",
+ "slug": "woman_getting_haircut",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ถ": {
+ "name": "person walking",
+ "slug": "person_walking",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ถโโ๏ธ": {
+ "name": "man walking",
+ "slug": "man_walking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ถโโ๏ธ": {
+ "name": "woman walking",
+ "slug": "woman_walking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ถโโก๏ธ": {
+ "name": "person walking facing right",
+ "slug": "person_walking_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ถโโ๏ธโโก๏ธ": {
+ "name": "woman walking facing right",
+ "slug": "woman_walking_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ถโโ๏ธโโก๏ธ": {
+ "name": "man walking facing right",
+ "slug": "man_walking_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ง": {
+ "name": "person standing",
+ "slug": "person_standing",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man standing",
+ "slug": "man_standing",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman standing",
+ "slug": "woman_standing",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ง": {
+ "name": "person kneeling",
+ "slug": "person_kneeling",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man kneeling",
+ "slug": "man_kneeling",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman kneeling",
+ "slug": "woman_kneeling",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐งโโก๏ธ": {
+ "name": "person kneeling facing right",
+ "slug": "person_kneeling_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐งโโ๏ธโโก๏ธ": {
+ "name": "woman kneeling facing right",
+ "slug": "woman_kneeling_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐งโโ๏ธโโก๏ธ": {
+ "name": "man kneeling facing right",
+ "slug": "man_kneeling_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐งโ๐ฆฏ": {
+ "name": "person with white cane",
+ "slug": "person_with_white_cane",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐งโ๐ฆฏโโก๏ธ": {
+ "name": "person with white cane facing right",
+ "slug": "person_with_white_cane_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐จโ๐ฆฏ": {
+ "name": "man with white cane",
+ "slug": "man_with_white_cane",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐จโ๐ฆฏโโก๏ธ": {
+ "name": "man with white cane facing right",
+ "slug": "man_with_white_cane_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ฉโ๐ฆฏ": {
+ "name": "woman with white cane",
+ "slug": "woman_with_white_cane",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ฉโ๐ฆฏโโก๏ธ": {
+ "name": "woman with white cane facing right",
+ "slug": "woman_with_white_cane_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐งโ๐ฆผ": {
+ "name": "person in motorized wheelchair",
+ "slug": "person_in_motorized_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐งโ๐ฆผโโก๏ธ": {
+ "name": "person in motorized wheelchair facing right",
+ "slug": "person_in_motorized_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐จโ๐ฆผ": {
+ "name": "man in motorized wheelchair",
+ "slug": "man_in_motorized_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐จโ๐ฆผโโก๏ธ": {
+ "name": "man in motorized wheelchair facing right",
+ "slug": "man_in_motorized_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ฉโ๐ฆผ": {
+ "name": "woman in motorized wheelchair",
+ "slug": "woman_in_motorized_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ฉโ๐ฆผโโก๏ธ": {
+ "name": "woman in motorized wheelchair facing right",
+ "slug": "woman_in_motorized_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐งโ๐ฆฝ": {
+ "name": "person in manual wheelchair",
+ "slug": "person_in_manual_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.1",
+ "unicode_version": "12.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.1"
+ },
+ "๐งโ๐ฆฝโโก๏ธ": {
+ "name": "person in manual wheelchair facing right",
+ "slug": "person_in_manual_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐จโ๐ฆฝ": {
+ "name": "man in manual wheelchair",
+ "slug": "man_in_manual_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐จโ๐ฆฝโโก๏ธ": {
+ "name": "man in manual wheelchair facing right",
+ "slug": "man_in_manual_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐ฉโ๐ฆฝ": {
+ "name": "woman in manual wheelchair",
+ "slug": "woman_in_manual_wheelchair",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ฉโ๐ฆฝโโก๏ธ": {
+ "name": "woman in manual wheelchair facing right",
+ "slug": "woman_in_manual_wheelchair_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐": {
+ "name": "person running",
+ "slug": "person_running",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man running",
+ "slug": "man_running",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman running",
+ "slug": "woman_running",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโก๏ธ": {
+ "name": "person running facing right",
+ "slug": "person_running_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐โโ๏ธโโก๏ธ": {
+ "name": "woman running facing right",
+ "slug": "woman_running_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐โโ๏ธโโก๏ธ": {
+ "name": "man running facing right",
+ "slug": "man_running_facing_right",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "15.1"
+ },
+ "๐": {
+ "name": "woman dancing",
+ "slug": "woman_dancing",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐บ": {
+ "name": "man dancing",
+ "slug": "man_dancing",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐ด๏ธ": {
+ "name": "person in suit levitating",
+ "slug": "person_in_suit_levitating",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฏ": {
+ "name": "people with bunny ears",
+ "slug": "people_with_bunny_ears",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏโโ๏ธ": {
+ "name": "men with bunny ears",
+ "slug": "men_with_bunny_ears",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฏโโ๏ธ": {
+ "name": "women with bunny ears",
+ "slug": "women_with_bunny_ears",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "person in steamy room",
+ "slug": "person_in_steamy_room",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man in steamy room",
+ "slug": "man_in_steamy_room",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman in steamy room",
+ "slug": "woman_in_steamy_room",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐ง": {
+ "name": "person climbing",
+ "slug": "person_climbing",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man climbing",
+ "slug": "man_climbing",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman climbing",
+ "slug": "woman_climbing",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐คบ": {
+ "name": "person fencing",
+ "slug": "person_fencing",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "horse racing",
+ "slug": "horse_racing",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "โท๏ธ": {
+ "name": "skier",
+ "slug": "skier",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "snowboarder",
+ "slug": "snowboarder",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐๏ธ": {
+ "name": "person golfing",
+ "slug": "person_golfing",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐๏ธโโ๏ธ": {
+ "name": "man golfing",
+ "slug": "man_golfing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐๏ธโโ๏ธ": {
+ "name": "woman golfing",
+ "slug": "woman_golfing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person surfing",
+ "slug": "person_surfing",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man surfing",
+ "slug": "man_surfing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman surfing",
+ "slug": "woman_surfing",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฃ": {
+ "name": "person rowing boat",
+ "slug": "person_rowing_boat",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ฃโโ๏ธ": {
+ "name": "man rowing boat",
+ "slug": "man_rowing_boat",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ฃโโ๏ธ": {
+ "name": "woman rowing boat",
+ "slug": "woman_rowing_boat",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐": {
+ "name": "person swimming",
+ "slug": "person_swimming",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "man swimming",
+ "slug": "man_swimming",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐โโ๏ธ": {
+ "name": "woman swimming",
+ "slug": "woman_swimming",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "โน๏ธ": {
+ "name": "person bouncing ball",
+ "slug": "person_bouncing_ball",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "2.0"
+ },
+ "โน๏ธโโ๏ธ": {
+ "name": "man bouncing ball",
+ "slug": "man_bouncing_ball",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "โน๏ธโโ๏ธ": {
+ "name": "woman bouncing ball",
+ "slug": "woman_bouncing_ball",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐๏ธ": {
+ "name": "person lifting weights",
+ "slug": "person_lifting_weights",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "2.0"
+ },
+ "๐๏ธโโ๏ธ": {
+ "name": "man lifting weights",
+ "slug": "man_lifting_weights",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐๏ธโโ๏ธ": {
+ "name": "woman lifting weights",
+ "slug": "woman_lifting_weights",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ด": {
+ "name": "person biking",
+ "slug": "person_biking",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ดโโ๏ธ": {
+ "name": "man biking",
+ "slug": "man_biking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ดโโ๏ธ": {
+ "name": "woman biking",
+ "slug": "woman_biking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ต": {
+ "name": "person mountain biking",
+ "slug": "person_mountain_biking",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐ตโโ๏ธ": {
+ "name": "man mountain biking",
+ "slug": "man_mountain_biking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ตโโ๏ธ": {
+ "name": "woman mountain biking",
+ "slug": "woman_mountain_biking",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คธ": {
+ "name": "person cartwheeling",
+ "slug": "person_cartwheeling",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คธโโ๏ธ": {
+ "name": "man cartwheeling",
+ "slug": "man_cartwheeling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คธโโ๏ธ": {
+ "name": "woman cartwheeling",
+ "slug": "woman_cartwheeling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คผ": {
+ "name": "people wrestling",
+ "slug": "people_wrestling",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐คผโโ๏ธ": {
+ "name": "men wrestling",
+ "slug": "men_wrestling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐คผโโ๏ธ": {
+ "name": "women wrestling",
+ "slug": "women_wrestling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐คฝ": {
+ "name": "person playing water polo",
+ "slug": "person_playing_water_polo",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คฝโโ๏ธ": {
+ "name": "man playing water polo",
+ "slug": "man_playing_water_polo",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คฝโโ๏ธ": {
+ "name": "woman playing water polo",
+ "slug": "woman_playing_water_polo",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คพ": {
+ "name": "person playing handball",
+ "slug": "person_playing_handball",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คพโโ๏ธ": {
+ "name": "man playing handball",
+ "slug": "man_playing_handball",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คพโโ๏ธ": {
+ "name": "woman playing handball",
+ "slug": "woman_playing_handball",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คน": {
+ "name": "person juggling",
+ "slug": "person_juggling",
+ "group": "People & Body",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "3.0"
+ },
+ "๐คนโโ๏ธ": {
+ "name": "man juggling",
+ "slug": "man_juggling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐คนโโ๏ธ": {
+ "name": "woman juggling",
+ "slug": "woman_juggling",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐ง": {
+ "name": "person in lotus position",
+ "slug": "person_in_lotus_position",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "man in lotus position",
+ "slug": "man_in_lotus_position",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐งโโ๏ธ": {
+ "name": "woman in lotus position",
+ "slug": "woman_in_lotus_position",
+ "group": "People & Body",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "5.0"
+ },
+ "๐": {
+ "name": "person taking bath",
+ "slug": "person_taking_bath",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "1.0"
+ },
+ "๐": {
+ "name": "person in bed",
+ "slug": "person_in_bed",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "4.0"
+ },
+ "๐งโ๐คโ๐ง": {
+ "name": "people holding hands",
+ "slug": "people_holding_hands",
+ "group": "People & Body",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ญ": {
+ "name": "women holding hands",
+ "slug": "women_holding_hands",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ซ": {
+ "name": "woman and man holding hands",
+ "slug": "woman_and_man_holding_hands",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐ฌ": {
+ "name": "men holding hands",
+ "slug": "men_holding_hands",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "12.0"
+ },
+ "๐": {
+ "name": "kiss",
+ "slug": "kiss",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐ฉโโค๏ธโ๐โ๐จ": {
+ "name": "kiss woman, man",
+ "slug": "kiss_woman_man",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐จโโค๏ธโ๐โ๐จ": {
+ "name": "kiss man, man",
+ "slug": "kiss_man_man",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐ฉโโค๏ธโ๐โ๐ฉ": {
+ "name": "kiss woman, woman",
+ "slug": "kiss_woman_woman",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐": {
+ "name": "couple with heart",
+ "slug": "couple_with_heart",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐ฉโโค๏ธโ๐จ": {
+ "name": "couple with heart woman, man",
+ "slug": "couple_with_heart_woman_man",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐จโโค๏ธโ๐จ": {
+ "name": "couple with heart man, man",
+ "slug": "couple_with_heart_man_man",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐ฉโโค๏ธโ๐ฉ": {
+ "name": "couple with heart woman, woman",
+ "slug": "couple_with_heart_woman_woman",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": true,
+ "skin_tone_support_unicode_version": "13.1"
+ },
+ "๐จโ๐ฉโ๐ฆ": {
+ "name": "family man, woman, boy",
+ "slug": "family_man_woman_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฉโ๐ง": {
+ "name": "family man, woman, girl",
+ "slug": "family_man_woman_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฉโ๐งโ๐ฆ": {
+ "name": "family man, woman, girl, boy",
+ "slug": "family_man_woman_girl_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฉโ๐ฆโ๐ฆ": {
+ "name": "family man, woman, boy, boy",
+ "slug": "family_man_woman_boy_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฉโ๐งโ๐ง": {
+ "name": "family man, woman, girl, girl",
+ "slug": "family_man_woman_girl_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐จโ๐ฆ": {
+ "name": "family man, man, boy",
+ "slug": "family_man_man_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐จโ๐ง": {
+ "name": "family man, man, girl",
+ "slug": "family_man_man_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐จโ๐งโ๐ฆ": {
+ "name": "family man, man, girl, boy",
+ "slug": "family_man_man_girl_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐จโ๐ฆโ๐ฆ": {
+ "name": "family man, man, boy, boy",
+ "slug": "family_man_man_boy_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐จโ๐งโ๐ง": {
+ "name": "family man, man, girl, girl",
+ "slug": "family_man_man_girl_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฉโ๐ฆ": {
+ "name": "family woman, woman, boy",
+ "slug": "family_woman_woman_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฉโ๐ง": {
+ "name": "family woman, woman, girl",
+ "slug": "family_woman_woman_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฉโ๐งโ๐ฆ": {
+ "name": "family woman, woman, girl, boy",
+ "slug": "family_woman_woman_girl_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฉโ๐ฆโ๐ฆ": {
+ "name": "family woman, woman, boy, boy",
+ "slug": "family_woman_woman_boy_boy",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฉโ๐งโ๐ง": {
+ "name": "family woman, woman, girl, girl",
+ "slug": "family_woman_woman_girl_girl",
+ "group": "People & Body",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฆ": {
+ "name": "family man, boy",
+ "slug": "family_man_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ฆโ๐ฆ": {
+ "name": "family man, boy, boy",
+ "slug": "family_man_boy_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐ง": {
+ "name": "family man, girl",
+ "slug": "family_man_girl",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐งโ๐ฆ": {
+ "name": "family man, girl, boy",
+ "slug": "family_man_girl_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐จโ๐งโ๐ง": {
+ "name": "family man, girl, girl",
+ "slug": "family_man_girl_girl",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฆ": {
+ "name": "family woman, boy",
+ "slug": "family_woman_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ฆโ๐ฆ": {
+ "name": "family woman, boy, boy",
+ "slug": "family_woman_boy_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐ง": {
+ "name": "family woman, girl",
+ "slug": "family_woman_girl",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐งโ๐ฆ": {
+ "name": "family woman, girl, boy",
+ "slug": "family_woman_girl_boy",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฉโ๐งโ๐ง": {
+ "name": "family woman, girl, girl",
+ "slug": "family_woman_girl_girl",
+ "group": "People & Body",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ฃ๏ธ": {
+ "name": "speaking head",
+ "slug": "speaking_head",
+ "group": "People & Body",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "bust in silhouette",
+ "slug": "bust_in_silhouette",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "busts in silhouette",
+ "slug": "busts_in_silhouette",
+ "group": "People & Body",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "people hugging",
+ "slug": "people_hugging",
+ "group": "People & Body",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "family",
+ "slug": "family",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งโ๐งโ๐ง": {
+ "name": "family adult, adult, child",
+ "slug": "family_adult_adult_child",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐งโ๐งโ๐งโ๐ง": {
+ "name": "family adult, adult, child, child",
+ "slug": "family_adult_adult_child_child",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐งโ๐ง": {
+ "name": "family adult, child",
+ "slug": "family_adult_child",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐งโ๐งโ๐ง": {
+ "name": "family adult, child, child",
+ "slug": "family_adult_child_child",
+ "group": "People & Body",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "footprints",
+ "slug": "footprints",
+ "group": "People & Body",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "monkey face",
+ "slug": "monkey_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "monkey",
+ "slug": "monkey",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "gorilla",
+ "slug": "gorilla",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆง": {
+ "name": "orangutan",
+ "slug": "orangutan",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "dog face",
+ "slug": "dog_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "dog",
+ "slug": "dog",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฆฎ": {
+ "name": "guide dog",
+ "slug": "guide_dog",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐โ๐ฆบ": {
+ "name": "service dog",
+ "slug": "service_dog",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "poodle",
+ "slug": "poodle",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "wolf",
+ "slug": "wolf",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "fox",
+ "slug": "fox",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "raccoon",
+ "slug": "raccoon",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "cat face",
+ "slug": "cat_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cat",
+ "slug": "cat",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐โโฌ": {
+ "name": "black cat",
+ "slug": "black_cat",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "lion",
+ "slug": "lion",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "tiger face",
+ "slug": "tiger_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "tiger",
+ "slug": "tiger",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "leopard",
+ "slug": "leopard",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "horse face",
+ "slug": "horse_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "moose",
+ "slug": "moose",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "donkey",
+ "slug": "donkey",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "horse",
+ "slug": "horse",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "unicorn",
+ "slug": "unicorn",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "zebra",
+ "slug": "zebra",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "deer",
+ "slug": "deer",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฌ": {
+ "name": "bison",
+ "slug": "bison",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "cow face",
+ "slug": "cow_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ox",
+ "slug": "ox",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "water buffalo",
+ "slug": "water_buffalo",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cow",
+ "slug": "cow",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "pig face",
+ "slug": "pig_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pig",
+ "slug": "pig",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "boar",
+ "slug": "boar",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "pig nose",
+ "slug": "pig_nose",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ram",
+ "slug": "ram",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ewe",
+ "slug": "ewe",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "goat",
+ "slug": "goat",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "camel",
+ "slug": "camel",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "two-hump camel",
+ "slug": "two_hump_camel",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "llama",
+ "slug": "llama",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "giraffe",
+ "slug": "giraffe",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "elephant",
+ "slug": "elephant",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆฃ": {
+ "name": "mammoth",
+ "slug": "mammoth",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "rhinoceros",
+ "slug": "rhinoceros",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "hippopotamus",
+ "slug": "hippopotamus",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "mouse face",
+ "slug": "mouse_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mouse",
+ "slug": "mouse",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rat",
+ "slug": "rat",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "hamster",
+ "slug": "hamster",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "rabbit face",
+ "slug": "rabbit_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rabbit",
+ "slug": "rabbit",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ๏ธ": {
+ "name": "chipmunk",
+ "slug": "chipmunk",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฆซ": {
+ "name": "beaver",
+ "slug": "beaver",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "hedgehog",
+ "slug": "hedgehog",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "bat",
+ "slug": "bat",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "bear",
+ "slug": "bear",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ปโโ๏ธ": {
+ "name": "polar bear",
+ "slug": "polar_bear",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "koala",
+ "slug": "koala",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "panda",
+ "slug": "panda",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆฅ": {
+ "name": "sloth",
+ "slug": "sloth",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฆ": {
+ "name": "otter",
+ "slug": "otter",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆจ": {
+ "name": "skunk",
+ "slug": "skunk",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "kangaroo",
+ "slug": "kangaroo",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆก": {
+ "name": "badger",
+ "slug": "badger",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "paw prints",
+ "slug": "paw_prints",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "turkey",
+ "slug": "turkey",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "chicken",
+ "slug": "chicken",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rooster",
+ "slug": "rooster",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "hatching chick",
+ "slug": "hatching_chick",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "baby chick",
+ "slug": "baby_chick",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "front-facing baby chick",
+ "slug": "front_facing_baby_chick",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "bird",
+ "slug": "bird",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "penguin",
+ "slug": "penguin",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "dove",
+ "slug": "dove",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฆ
": {
+ "name": "eagle",
+ "slug": "eagle",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "duck",
+ "slug": "duck",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆข": {
+ "name": "swan",
+ "slug": "swan",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "owl",
+ "slug": "owl",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆค": {
+ "name": "dodo",
+ "slug": "dodo",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ชถ": {
+ "name": "feather",
+ "slug": "feather",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฉ": {
+ "name": "flamingo",
+ "slug": "flamingo",
+ "group": "Animals & Nature",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "peacock",
+ "slug": "peacock",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "parrot",
+ "slug": "parrot",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชฝ": {
+ "name": "wing",
+ "slug": "wing",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ฆโโฌ": {
+ "name": "black bird",
+ "slug": "black_bird",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ชฟ": {
+ "name": "goose",
+ "slug": "goose",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ฆโ๐ฅ": {
+ "name": "phoenix",
+ "slug": "phoenix",
+ "group": "Animals & Nature",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "frog",
+ "slug": "frog",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "crocodile",
+ "slug": "crocodile",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "turtle",
+ "slug": "turtle",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "lizard",
+ "slug": "lizard",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "snake",
+ "slug": "snake",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "dragon face",
+ "slug": "dragon_face",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "dragon",
+ "slug": "dragon",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "sauropod",
+ "slug": "sauropod",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "T-Rex",
+ "slug": "t_rex",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "spouting whale",
+ "slug": "spouting_whale",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "whale",
+ "slug": "whale",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "dolphin",
+ "slug": "dolphin",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆญ": {
+ "name": "seal",
+ "slug": "seal",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "fish",
+ "slug": "fish",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "tropical fish",
+ "slug": "tropical_fish",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "blowfish",
+ "slug": "blowfish",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "shark",
+ "slug": "shark",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "octopus",
+ "slug": "octopus",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "spiral shell",
+ "slug": "spiral_shell",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชธ": {
+ "name": "coral",
+ "slug": "coral",
+ "group": "Animals & Nature",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ชผ": {
+ "name": "jellyfish",
+ "slug": "jellyfish",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "snail",
+ "slug": "snail",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "butterfly",
+ "slug": "butterfly",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bug",
+ "slug": "bug",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ant",
+ "slug": "ant",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "honeybee",
+ "slug": "honeybee",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชฒ": {
+ "name": "beetle",
+ "slug": "beetle",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "lady beetle",
+ "slug": "lady_beetle",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "cricket",
+ "slug": "cricket",
+ "group": "Animals & Nature",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ชณ": {
+ "name": "cockroach",
+ "slug": "cockroach",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ท๏ธ": {
+ "name": "spider",
+ "slug": "spider",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ธ๏ธ": {
+ "name": "spider web",
+ "slug": "spider_web",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "scorpion",
+ "slug": "scorpion",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "mosquito",
+ "slug": "mosquito",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชฐ": {
+ "name": "fly",
+ "slug": "fly",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ชฑ": {
+ "name": "worm",
+ "slug": "worm",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ ": {
+ "name": "microbe",
+ "slug": "microbe",
+ "group": "Animals & Nature",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bouquet",
+ "slug": "bouquet",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "cherry blossom",
+ "slug": "cherry_blossom",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "white flower",
+ "slug": "white_flower",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชท": {
+ "name": "lotus",
+ "slug": "lotus",
+ "group": "Animals & Nature",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ต๏ธ": {
+ "name": "rosette",
+ "slug": "rosette",
+ "group": "Animals & Nature",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "rose",
+ "slug": "rose",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "wilted flower",
+ "slug": "wilted_flower",
+ "group": "Animals & Nature",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "hibiscus",
+ "slug": "hibiscus",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "sunflower",
+ "slug": "sunflower",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "blossom",
+ "slug": "blossom",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "tulip",
+ "slug": "tulip",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชป": {
+ "name": "hyacinth",
+ "slug": "hyacinth",
+ "group": "Animals & Nature",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "seedling",
+ "slug": "seedling",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชด": {
+ "name": "potted plant",
+ "slug": "potted_plant",
+ "group": "Animals & Nature",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "evergreen tree",
+ "slug": "evergreen_tree",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "deciduous tree",
+ "slug": "deciduous_tree",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "palm tree",
+ "slug": "palm_tree",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "cactus",
+ "slug": "cactus",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "sheaf of rice",
+ "slug": "sheaf_of_rice",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "herb",
+ "slug": "herb",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "shamrock",
+ "slug": "shamrock",
+ "group": "Animals & Nature",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "four leaf clover",
+ "slug": "four_leaf_clover",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "maple leaf",
+ "slug": "maple_leaf",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "fallen leaf",
+ "slug": "fallen_leaf",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "leaf fluttering in wind",
+ "slug": "leaf_fluttering_in_wind",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชน": {
+ "name": "empty nest",
+ "slug": "empty_nest",
+ "group": "Animals & Nature",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ชบ": {
+ "name": "nest with eggs",
+ "slug": "nest_with_eggs",
+ "group": "Animals & Nature",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mushroom",
+ "slug": "mushroom",
+ "group": "Animals & Nature",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "grapes",
+ "slug": "grapes",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "melon",
+ "slug": "melon",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "watermelon",
+ "slug": "watermelon",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tangerine",
+ "slug": "tangerine",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "lemon",
+ "slug": "lemon",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐โ๐ฉ": {
+ "name": "lime",
+ "slug": "lime",
+ "group": "Food & Drink",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "banana",
+ "slug": "banana",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pineapple",
+ "slug": "pineapple",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅญ": {
+ "name": "mango",
+ "slug": "mango",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "red apple",
+ "slug": "red_apple",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "green apple",
+ "slug": "green_apple",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pear",
+ "slug": "pear",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "peach",
+ "slug": "peach",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cherries",
+ "slug": "cherries",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "strawberry",
+ "slug": "strawberry",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "blueberries",
+ "slug": "blueberries",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "kiwi fruit",
+ "slug": "kiwi_fruit",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "tomato",
+ "slug": "tomato",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "olive",
+ "slug": "olive",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฅ": {
+ "name": "coconut",
+ "slug": "coconut",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "avocado",
+ "slug": "avocado",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "eggplant",
+ "slug": "eggplant",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "potato",
+ "slug": "potato",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "carrot",
+ "slug": "carrot",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "ear of corn",
+ "slug": "ear_of_corn",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ๏ธ": {
+ "name": "hot pepper",
+ "slug": "hot_pepper",
+ "group": "Food & Drink",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "bell pepper",
+ "slug": "bell_pepper",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "cucumber",
+ "slug": "cucumber",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฌ": {
+ "name": "leafy green",
+ "slug": "leafy_green",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฆ": {
+ "name": "broccoli",
+ "slug": "broccoli",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "garlic",
+ "slug": "garlic",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง
": {
+ "name": "onion",
+ "slug": "onion",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "peanuts",
+ "slug": "peanuts",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "beans",
+ "slug": "beans",
+ "group": "Food & Drink",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "chestnut",
+ "slug": "chestnut",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "ginger root",
+ "slug": "ginger_root",
+ "group": "Food & Drink",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "pea pod",
+ "slug": "pea_pod",
+ "group": "Food & Drink",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐โ๐ซ": {
+ "name": "brown mushroom",
+ "slug": "brown_mushroom",
+ "group": "Food & Drink",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bread",
+ "slug": "bread",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "croissant",
+ "slug": "croissant",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "baguette bread",
+ "slug": "baguette_bread",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "flatbread",
+ "slug": "flatbread",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅจ": {
+ "name": "pretzel",
+ "slug": "pretzel",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฏ": {
+ "name": "bagel",
+ "slug": "bagel",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "pancakes",
+ "slug": "pancakes",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "waffle",
+ "slug": "waffle",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "cheese wedge",
+ "slug": "cheese_wedge",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "meat on bone",
+ "slug": "meat_on_bone",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "poultry leg",
+ "slug": "poultry_leg",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅฉ": {
+ "name": "cut of meat",
+ "slug": "cut_of_meat",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "bacon",
+ "slug": "bacon",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "hamburger",
+ "slug": "hamburger",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "french fries",
+ "slug": "french_fries",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pizza",
+ "slug": "pizza",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "hot dog",
+ "slug": "hot_dog",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅช": {
+ "name": "sandwich",
+ "slug": "sandwich",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "taco",
+ "slug": "taco",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "burrito",
+ "slug": "burrito",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "tamale",
+ "slug": "tamale",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "stuffed flatbread",
+ "slug": "stuffed_flatbread",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "falafel",
+ "slug": "falafel",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "egg",
+ "slug": "egg",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "cooking",
+ "slug": "cooking",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "shallow pan of food",
+ "slug": "shallow_pan_of_food",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "pot of food",
+ "slug": "pot_of_food",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "fondue",
+ "slug": "fondue",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฃ": {
+ "name": "bowl with spoon",
+ "slug": "bowl_with_spoon",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "green salad",
+ "slug": "green_salad",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "popcorn",
+ "slug": "popcorn",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "butter",
+ "slug": "butter",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "salt",
+ "slug": "salt",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅซ": {
+ "name": "canned food",
+ "slug": "canned_food",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "bento box",
+ "slug": "bento_box",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rice cracker",
+ "slug": "rice_cracker",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rice ball",
+ "slug": "rice_ball",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cooked rice",
+ "slug": "cooked_rice",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "curry rice",
+ "slug": "curry_rice",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "steaming bowl",
+ "slug": "steaming_bowl",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "spaghetti",
+ "slug": "spaghetti",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "roasted sweet potato",
+ "slug": "roasted_sweet_potato",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "oden",
+ "slug": "oden",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "sushi",
+ "slug": "sushi",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "fried shrimp",
+ "slug": "fried_shrimp",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "fish cake with swirl",
+ "slug": "fish_cake_with_swirl",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅฎ": {
+ "name": "moon cake",
+ "slug": "moon_cake",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "dango",
+ "slug": "dango",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "dumpling",
+ "slug": "dumpling",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ ": {
+ "name": "fortune cookie",
+ "slug": "fortune_cookie",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅก": {
+ "name": "takeout box",
+ "slug": "takeout_box",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "crab",
+ "slug": "crab",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "lobster",
+ "slug": "lobster",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "shrimp",
+ "slug": "shrimp",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "squid",
+ "slug": "squid",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆช": {
+ "name": "oyster",
+ "slug": "oyster",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "soft ice cream",
+ "slug": "soft_ice_cream",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "shaved ice",
+ "slug": "shaved_ice",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "ice cream",
+ "slug": "ice_cream",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "doughnut",
+ "slug": "doughnut",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "cookie",
+ "slug": "cookie",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "birthday cake",
+ "slug": "birthday_cake",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "shortcake",
+ "slug": "shortcake",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "cupcake",
+ "slug": "cupcake",
+ "group": "Food & Drink",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅง": {
+ "name": "pie",
+ "slug": "pie",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "chocolate bar",
+ "slug": "chocolate_bar",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "candy",
+ "slug": "candy",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "lollipop",
+ "slug": "lollipop",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "custard",
+ "slug": "custard",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "honey pot",
+ "slug": "honey_pot",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "baby bottle",
+ "slug": "baby_bottle",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "glass of milk",
+ "slug": "glass_of_milk",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "hot beverage",
+ "slug": "hot_beverage",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "teapot",
+ "slug": "teapot",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "teacup without handle",
+ "slug": "teacup_without_handle",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "sake",
+ "slug": "sake",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "bottle with popping cork",
+ "slug": "bottle_with_popping_cork",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "wine glass",
+ "slug": "wine_glass",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "cocktail glass",
+ "slug": "cocktail_glass",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "tropical drink",
+ "slug": "tropical_drink",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "beer mug",
+ "slug": "beer_mug",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "clinking beer mugs",
+ "slug": "clinking_beer_mugs",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "clinking glasses",
+ "slug": "clinking_glasses",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "tumbler glass",
+ "slug": "tumbler_glass",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "pouring liquid",
+ "slug": "pouring_liquid",
+ "group": "Food & Drink",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ฅค": {
+ "name": "cup with straw",
+ "slug": "cup_with_straw",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "bubble tea",
+ "slug": "bubble_tea",
+ "group": "Food & Drink",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "beverage box",
+ "slug": "beverage_box",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "mate",
+ "slug": "mate",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "ice",
+ "slug": "ice",
+ "group": "Food & Drink",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฅข": {
+ "name": "chopsticks",
+ "slug": "chopsticks",
+ "group": "Food & Drink",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฝ๏ธ": {
+ "name": "fork and knife with plate",
+ "slug": "fork_and_knife_with_plate",
+ "group": "Food & Drink",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "fork and knife",
+ "slug": "fork_and_knife",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "spoon",
+ "slug": "spoon",
+ "group": "Food & Drink",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "kitchen knife",
+ "slug": "kitchen_knife",
+ "group": "Food & Drink",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "jar",
+ "slug": "jar",
+ "group": "Food & Drink",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "amphora",
+ "slug": "amphora",
+ "group": "Food & Drink",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "globe showing Europe-Africa",
+ "slug": "globe_showing_europe_africa",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "globe showing Americas",
+ "slug": "globe_showing_americas",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "globe showing Asia-Australia",
+ "slug": "globe_showing_asia_australia",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "globe with meridians",
+ "slug": "globe_with_meridians",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐บ๏ธ": {
+ "name": "world map",
+ "slug": "world_map",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "map of Japan",
+ "slug": "map_of_japan",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งญ": {
+ "name": "compass",
+ "slug": "compass",
+ "group": "Travel & Places",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "snow-capped mountain",
+ "slug": "snow_capped_mountain",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฐ๏ธ": {
+ "name": "mountain",
+ "slug": "mountain",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "volcano",
+ "slug": "volcano",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "mount fuji",
+ "slug": "mount_fuji",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "camping",
+ "slug": "camping",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "beach with umbrella",
+ "slug": "beach_with_umbrella",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "desert",
+ "slug": "desert",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "desert island",
+ "slug": "desert_island",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "national park",
+ "slug": "national_park",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "stadium",
+ "slug": "stadium",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "classical building",
+ "slug": "classical_building",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "building construction",
+ "slug": "building_construction",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐งฑ": {
+ "name": "brick",
+ "slug": "brick",
+ "group": "Travel & Places",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชจ": {
+ "name": "rock",
+ "slug": "rock",
+ "group": "Travel & Places",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ชต": {
+ "name": "wood",
+ "slug": "wood",
+ "group": "Travel & Places",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "hut",
+ "slug": "hut",
+ "group": "Travel & Places",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "houses",
+ "slug": "houses",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "derelict house",
+ "slug": "derelict_house",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "house",
+ "slug": "house",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "house with garden",
+ "slug": "house_with_garden",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "office building",
+ "slug": "office_building",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "Japanese post office",
+ "slug": "japanese_post_office",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "post office",
+ "slug": "post_office",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "hospital",
+ "slug": "hospital",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "bank",
+ "slug": "bank",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "hotel",
+ "slug": "hotel",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "love hotel",
+ "slug": "love_hotel",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "convenience store",
+ "slug": "convenience_store",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "school",
+ "slug": "school",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "department store",
+ "slug": "department_store",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "factory",
+ "slug": "factory",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "Japanese castle",
+ "slug": "japanese_castle",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "castle",
+ "slug": "castle",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "wedding",
+ "slug": "wedding",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "Tokyo tower",
+ "slug": "tokyo_tower",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "Statue of Liberty",
+ "slug": "statue_of_liberty",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โช": {
+ "name": "church",
+ "slug": "church",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mosque",
+ "slug": "mosque",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "hindu temple",
+ "slug": "hindu_temple",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "synagogue",
+ "slug": "synagogue",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฉ๏ธ": {
+ "name": "shinto shrine",
+ "slug": "shinto_shrine",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kaaba",
+ "slug": "kaaba",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฒ": {
+ "name": "fountain",
+ "slug": "fountain",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โบ": {
+ "name": "tent",
+ "slug": "tent",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "foggy",
+ "slug": "foggy",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "night with stars",
+ "slug": "night_with_stars",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "cityscape",
+ "slug": "cityscape",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sunrise over mountains",
+ "slug": "sunrise_over_mountains",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "sunrise",
+ "slug": "sunrise",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cityscape at dusk",
+ "slug": "cityscape_at_dusk",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sunset",
+ "slug": "sunset",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bridge at night",
+ "slug": "bridge_at_night",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โจ๏ธ": {
+ "name": "hot springs",
+ "slug": "hot_springs",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "carousel horse",
+ "slug": "carousel_horse",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "playground slide",
+ "slug": "playground_slide",
+ "group": "Travel & Places",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "ferris wheel",
+ "slug": "ferris_wheel",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "roller coaster",
+ "slug": "roller_coaster",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "barber pole",
+ "slug": "barber_pole",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "circus tent",
+ "slug": "circus_tent",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "locomotive",
+ "slug": "locomotive",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "railway car",
+ "slug": "railway_car",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "high-speed train",
+ "slug": "high_speed_train",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "bullet train",
+ "slug": "bullet_train",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "train",
+ "slug": "train",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "metro",
+ "slug": "metro",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "light rail",
+ "slug": "light_rail",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "station",
+ "slug": "station",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tram",
+ "slug": "tram",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "monorail",
+ "slug": "monorail",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mountain railway",
+ "slug": "mountain_railway",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tram car",
+ "slug": "tram_car",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bus",
+ "slug": "bus",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "oncoming bus",
+ "slug": "oncoming_bus",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "trolleybus",
+ "slug": "trolleybus",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "minibus",
+ "slug": "minibus",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ambulance",
+ "slug": "ambulance",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "fire engine",
+ "slug": "fire_engine",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "police car",
+ "slug": "police_car",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "oncoming police car",
+ "slug": "oncoming_police_car",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "taxi",
+ "slug": "taxi",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "oncoming taxi",
+ "slug": "oncoming_taxi",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "automobile",
+ "slug": "automobile",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "oncoming automobile",
+ "slug": "oncoming_automobile",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sport utility vehicle",
+ "slug": "sport_utility_vehicle",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "pickup truck",
+ "slug": "pickup_truck",
+ "group": "Travel & Places",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "delivery truck",
+ "slug": "delivery_truck",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "articulated lorry",
+ "slug": "articulated_lorry",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tractor",
+ "slug": "tractor",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "racing car",
+ "slug": "racing_car",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "motorcycle",
+ "slug": "motorcycle",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "motor scooter",
+ "slug": "motor_scooter",
+ "group": "Travel & Places",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฝ": {
+ "name": "manual wheelchair",
+ "slug": "manual_wheelchair",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆผ": {
+ "name": "motorized wheelchair",
+ "slug": "motorized_wheelchair",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "auto rickshaw",
+ "slug": "auto_rickshaw",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "bicycle",
+ "slug": "bicycle",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "kick scooter",
+ "slug": "kick_scooter",
+ "group": "Travel & Places",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "skateboard",
+ "slug": "skateboard",
+ "group": "Travel & Places",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "roller skate",
+ "slug": "roller_skate",
+ "group": "Travel & Places",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bus stop",
+ "slug": "bus_stop",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ๏ธ": {
+ "name": "motorway",
+ "slug": "motorway",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ค๏ธ": {
+ "name": "railway track",
+ "slug": "railway_track",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ข๏ธ": {
+ "name": "oil drum",
+ "slug": "oil_drum",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฝ": {
+ "name": "fuel pump",
+ "slug": "fuel_pump",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "wheel",
+ "slug": "wheel",
+ "group": "Travel & Places",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "police car light",
+ "slug": "police_car_light",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "horizontal traffic light",
+ "slug": "horizontal_traffic_light",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "vertical traffic light",
+ "slug": "vertical_traffic_light",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "stop sign",
+ "slug": "stop_sign",
+ "group": "Travel & Places",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "construction",
+ "slug": "construction",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "anchor",
+ "slug": "anchor",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ring buoy",
+ "slug": "ring_buoy",
+ "group": "Travel & Places",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "โต": {
+ "name": "sailboat",
+ "slug": "sailboat",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "canoe",
+ "slug": "canoe",
+ "group": "Travel & Places",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "speedboat",
+ "slug": "speedboat",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธ": {
+ "name": "passenger ship",
+ "slug": "passenger_ship",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โด๏ธ": {
+ "name": "ferry",
+ "slug": "ferry",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฅ๏ธ": {
+ "name": "motor boat",
+ "slug": "motor_boat",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "ship",
+ "slug": "ship",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "airplane",
+ "slug": "airplane",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ๏ธ": {
+ "name": "small airplane",
+ "slug": "small_airplane",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "airplane departure",
+ "slug": "airplane_departure",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "airplane arrival",
+ "slug": "airplane_arrival",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "parachute",
+ "slug": "parachute",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "seat",
+ "slug": "seat",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "helicopter",
+ "slug": "helicopter",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "suspension railway",
+ "slug": "suspension_railway",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "mountain cableway",
+ "slug": "mountain_cableway",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "aerial tramway",
+ "slug": "aerial_tramway",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๏ธ": {
+ "name": "satellite",
+ "slug": "satellite",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rocket",
+ "slug": "rocket",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "flying saucer",
+ "slug": "flying_saucer",
+ "group": "Travel & Places",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "bellhop bell",
+ "slug": "bellhop_bell",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐งณ": {
+ "name": "luggage",
+ "slug": "luggage",
+ "group": "Travel & Places",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "hourglass done",
+ "slug": "hourglass_done",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โณ": {
+ "name": "hourglass not done",
+ "slug": "hourglass_not_done",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "watch",
+ "slug": "watch",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฐ": {
+ "name": "alarm clock",
+ "slug": "alarm_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฑ๏ธ": {
+ "name": "stopwatch",
+ "slug": "stopwatch",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฒ๏ธ": {
+ "name": "timer clock",
+ "slug": "timer_clock",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๏ธ": {
+ "name": "mantelpiece clock",
+ "slug": "mantelpiece_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "twelve oโclock",
+ "slug": "twelve_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "twelve-thirty",
+ "slug": "twelve_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "one oโclock",
+ "slug": "one_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "one-thirty",
+ "slug": "one_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "two oโclock",
+ "slug": "two_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "two-thirty",
+ "slug": "two_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "three oโclock",
+ "slug": "three_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "three-thirty",
+ "slug": "three_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "four oโclock",
+ "slug": "four_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "four-thirty",
+ "slug": "four_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "five oโclock",
+ "slug": "five_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "five-thirty",
+ "slug": "five_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "six oโclock",
+ "slug": "six_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "six-thirty",
+ "slug": "six_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "seven oโclock",
+ "slug": "seven_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "seven-thirty",
+ "slug": "seven_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "eight oโclock",
+ "slug": "eight_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "eight-thirty",
+ "slug": "eight_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "nine oโclock",
+ "slug": "nine_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "nine-thirty",
+ "slug": "nine_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ten oโclock",
+ "slug": "ten_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "ten-thirty",
+ "slug": "ten_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "eleven oโclock",
+ "slug": "eleven_o_clock",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "eleven-thirty",
+ "slug": "eleven_thirty",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "new moon",
+ "slug": "new_moon",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "waxing crescent moon",
+ "slug": "waxing_crescent_moon",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "first quarter moon",
+ "slug": "first_quarter_moon",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "waxing gibbous moon",
+ "slug": "waxing_gibbous_moon",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "full moon",
+ "slug": "full_moon",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "waning gibbous moon",
+ "slug": "waning_gibbous_moon",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "last quarter moon",
+ "slug": "last_quarter_moon",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "waning crescent moon",
+ "slug": "waning_crescent_moon",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "crescent moon",
+ "slug": "crescent_moon",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "new moon face",
+ "slug": "new_moon_face",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "first quarter moon face",
+ "slug": "first_quarter_moon_face",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "last quarter moon face",
+ "slug": "last_quarter_moon_face",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ก๏ธ": {
+ "name": "thermometer",
+ "slug": "thermometer",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "sun",
+ "slug": "sun",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "full moon face",
+ "slug": "full_moon_face",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sun with face",
+ "slug": "sun_with_face",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "ringed planet",
+ "slug": "ringed_planet",
+ "group": "Travel & Places",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "โญ": {
+ "name": "star",
+ "slug": "star",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "glowing star",
+ "slug": "glowing_star",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "shooting star",
+ "slug": "shooting_star",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "milky way",
+ "slug": "milky_way",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "cloud",
+ "slug": "cloud",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ
": {
+ "name": "sun behind cloud",
+ "slug": "sun_behind_cloud",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "cloud with lightning and rain",
+ "slug": "cloud_with_lightning_and_rain",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ค๏ธ": {
+ "name": "sun behind small cloud",
+ "slug": "sun_behind_small_cloud",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฅ๏ธ": {
+ "name": "sun behind large cloud",
+ "slug": "sun_behind_large_cloud",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฆ๏ธ": {
+ "name": "sun behind rain cloud",
+ "slug": "sun_behind_rain_cloud",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ง๏ธ": {
+ "name": "cloud with rain",
+ "slug": "cloud_with_rain",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐จ๏ธ": {
+ "name": "cloud with snow",
+ "slug": "cloud_with_snow",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฉ๏ธ": {
+ "name": "cloud with lightning",
+ "slug": "cloud_with_lightning",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ช๏ธ": {
+ "name": "tornado",
+ "slug": "tornado",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ซ๏ธ": {
+ "name": "fog",
+ "slug": "fog",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฌ๏ธ": {
+ "name": "wind face",
+ "slug": "wind_face",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cyclone",
+ "slug": "cyclone",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rainbow",
+ "slug": "rainbow",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "closed umbrella",
+ "slug": "closed_umbrella",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "umbrella",
+ "slug": "umbrella",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "umbrella with rain drops",
+ "slug": "umbrella_with_rain_drops",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฑ๏ธ": {
+ "name": "umbrella on ground",
+ "slug": "umbrella_on_ground",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โก": {
+ "name": "high voltage",
+ "slug": "high_voltage",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "snowflake",
+ "slug": "snowflake",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "snowman",
+ "slug": "snowman",
+ "group": "Travel & Places",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "snowman without snow",
+ "slug": "snowman_without_snow",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "comet",
+ "slug": "comet",
+ "group": "Travel & Places",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "fire",
+ "slug": "fire",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "droplet",
+ "slug": "droplet",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "water wave",
+ "slug": "water_wave",
+ "group": "Travel & Places",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "jack-o-lantern",
+ "slug": "jack_o_lantern",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Christmas tree",
+ "slug": "christmas_tree",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "fireworks",
+ "slug": "fireworks",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "sparkler",
+ "slug": "sparkler",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งจ": {
+ "name": "firecracker",
+ "slug": "firecracker",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "โจ": {
+ "name": "sparkles",
+ "slug": "sparkles",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "balloon",
+ "slug": "balloon",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "party popper",
+ "slug": "party_popper",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "confetti ball",
+ "slug": "confetti_ball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tanabata tree",
+ "slug": "tanabata_tree",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pine decoration",
+ "slug": "pine_decoration",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Japanese dolls",
+ "slug": "japanese_dolls",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "carp streamer",
+ "slug": "carp_streamer",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "wind chime",
+ "slug": "wind_chime",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "moon viewing ceremony",
+ "slug": "moon_viewing_ceremony",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งง": {
+ "name": "red envelope",
+ "slug": "red_envelope",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ribbon",
+ "slug": "ribbon",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "wrapped gift",
+ "slug": "wrapped_gift",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "reminder ribbon",
+ "slug": "reminder_ribbon",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "admission tickets",
+ "slug": "admission_tickets",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "ticket",
+ "slug": "ticket",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "military medal",
+ "slug": "military_medal",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "trophy",
+ "slug": "trophy",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "sports medal",
+ "slug": "sports_medal",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "1st place medal",
+ "slug": "1st_place_medal",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "2nd place medal",
+ "slug": "2nd_place_medal",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "3rd place medal",
+ "slug": "3rd_place_medal",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "โฝ": {
+ "name": "soccer ball",
+ "slug": "soccer_ball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โพ": {
+ "name": "baseball",
+ "slug": "baseball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "softball",
+ "slug": "softball",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "basketball",
+ "slug": "basketball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "volleyball",
+ "slug": "volleyball",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "american football",
+ "slug": "american_football",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "rugby football",
+ "slug": "rugby_football",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "tennis",
+ "slug": "tennis",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "flying disc",
+ "slug": "flying_disc",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "bowling",
+ "slug": "bowling",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "cricket game",
+ "slug": "cricket_game",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "field hockey",
+ "slug": "field_hockey",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ice hockey",
+ "slug": "ice_hockey",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "lacrosse",
+ "slug": "lacrosse",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ping pong",
+ "slug": "ping_pong",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "badminton",
+ "slug": "badminton",
+ "group": "Activities",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "boxing glove",
+ "slug": "boxing_glove",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "martial arts uniform",
+ "slug": "martial_arts_uniform",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ
": {
+ "name": "goal net",
+ "slug": "goal_net",
+ "group": "Activities",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "โณ": {
+ "name": "flag in hole",
+ "slug": "flag_in_hole",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โธ๏ธ": {
+ "name": "ice skate",
+ "slug": "ice_skate",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "fishing pole",
+ "slug": "fishing_pole",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐คฟ": {
+ "name": "diving mask",
+ "slug": "diving_mask",
+ "group": "Activities",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "running shirt",
+ "slug": "running_shirt",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "skis",
+ "slug": "skis",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "sled",
+ "slug": "sled",
+ "group": "Activities",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "curling stone",
+ "slug": "curling_stone",
+ "group": "Activities",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "bullseye",
+ "slug": "bullseye",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "yo-yo",
+ "slug": "yo_yo",
+ "group": "Activities",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "kite",
+ "slug": "kite",
+ "group": "Activities",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "water pistol",
+ "slug": "water_pistol",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "pool 8 ball",
+ "slug": "pool_8_ball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "crystal ball",
+ "slug": "crystal_ball",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "magic wand",
+ "slug": "magic_wand",
+ "group": "Activities",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "video game",
+ "slug": "video_game",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น๏ธ": {
+ "name": "joystick",
+ "slug": "joystick",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "slot machine",
+ "slug": "slot_machine",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "game die",
+ "slug": "game_die",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งฉ": {
+ "name": "puzzle piece",
+ "slug": "puzzle_piece",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งธ": {
+ "name": "teddy bear",
+ "slug": "teddy_bear",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ช
": {
+ "name": "piรฑata",
+ "slug": "pinata",
+ "group": "Activities",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ชฉ": {
+ "name": "mirror ball",
+ "slug": "mirror_ball",
+ "group": "Activities",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "nesting dolls",
+ "slug": "nesting_dolls",
+ "group": "Activities",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "โ ๏ธ": {
+ "name": "spade suit",
+ "slug": "spade_suit",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฅ๏ธ": {
+ "name": "heart suit",
+ "slug": "heart_suit",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฆ๏ธ": {
+ "name": "diamond suit",
+ "slug": "diamond_suit",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฃ๏ธ": {
+ "name": "club suit",
+ "slug": "club_suit",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "chess pawn",
+ "slug": "chess_pawn",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "joker",
+ "slug": "joker",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "mahjong red dragon",
+ "slug": "mahjong_red_dragon",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "flower playing cards",
+ "slug": "flower_playing_cards",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "performing arts",
+ "slug": "performing_arts",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ๏ธ": {
+ "name": "framed picture",
+ "slug": "framed_picture",
+ "group": "Activities",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "artist palette",
+ "slug": "artist_palette",
+ "group": "Activities",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งต": {
+ "name": "thread",
+ "slug": "thread",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชก": {
+ "name": "sewing needle",
+ "slug": "sewing_needle",
+ "group": "Activities",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐งถ": {
+ "name": "yarn",
+ "slug": "yarn",
+ "group": "Activities",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชข": {
+ "name": "knot",
+ "slug": "knot",
+ "group": "Activities",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "glasses",
+ "slug": "glasses",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ๏ธ": {
+ "name": "sunglasses",
+ "slug": "sunglasses",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฅฝ": {
+ "name": "goggles",
+ "slug": "goggles",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅผ": {
+ "name": "lab coat",
+ "slug": "lab_coat",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆบ": {
+ "name": "safety vest",
+ "slug": "safety_vest",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "necktie",
+ "slug": "necktie",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "t-shirt",
+ "slug": "t_shirt",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "jeans",
+ "slug": "jeans",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งฃ": {
+ "name": "scarf",
+ "slug": "scarf",
+ "group": "Objects",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งค": {
+ "name": "gloves",
+ "slug": "gloves",
+ "group": "Objects",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งฅ": {
+ "name": "coat",
+ "slug": "coat",
+ "group": "Objects",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐งฆ": {
+ "name": "socks",
+ "slug": "socks",
+ "group": "Objects",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "dress",
+ "slug": "dress",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "kimono",
+ "slug": "kimono",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅป": {
+ "name": "sari",
+ "slug": "sari",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉฑ": {
+ "name": "one-piece swimsuit",
+ "slug": "one_piece_swimsuit",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉฒ": {
+ "name": "briefs",
+ "slug": "briefs",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉณ": {
+ "name": "shorts",
+ "slug": "shorts",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bikini",
+ "slug": "bikini",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "womanโs clothes",
+ "slug": "woman_s_clothes",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชญ": {
+ "name": "folding hand fan",
+ "slug": "folding_hand_fan",
+ "group": "Objects",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "purse",
+ "slug": "purse",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "handbag",
+ "slug": "handbag",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "clutch bag",
+ "slug": "clutch_bag",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "shopping bags",
+ "slug": "shopping_bags",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "backpack",
+ "slug": "backpack",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉด": {
+ "name": "thong sandal",
+ "slug": "thong_sandal",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "manโs shoe",
+ "slug": "man_s_shoe",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "running shoe",
+ "slug": "running_shoe",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅพ": {
+ "name": "hiking boot",
+ "slug": "hiking_boot",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅฟ": {
+ "name": "flat shoe",
+ "slug": "flat_shoe",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "high-heeled shoe",
+ "slug": "high_heeled_shoe",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "womanโs sandal",
+ "slug": "woman_s_sandal",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉฐ": {
+ "name": "ballet shoes",
+ "slug": "ballet_shoes",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "womanโs boot",
+ "slug": "woman_s_boot",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชฎ": {
+ "name": "hair pick",
+ "slug": "hair_pick",
+ "group": "Objects",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "crown",
+ "slug": "crown",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "womanโs hat",
+ "slug": "woman_s_hat",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "top hat",
+ "slug": "top_hat",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "graduation cap",
+ "slug": "graduation_cap",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งข": {
+ "name": "billed cap",
+ "slug": "billed_cap",
+ "group": "Objects",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "military helmet",
+ "slug": "military_helmet",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "rescue workerโs helmet",
+ "slug": "rescue_worker_s_helmet",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "prayer beads",
+ "slug": "prayer_beads",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "lipstick",
+ "slug": "lipstick",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ring",
+ "slug": "ring",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "gem stone",
+ "slug": "gem_stone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "muted speaker",
+ "slug": "muted_speaker",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "speaker low volume",
+ "slug": "speaker_low_volume",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "speaker medium volume",
+ "slug": "speaker_medium_volume",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "speaker high volume",
+ "slug": "speaker_high_volume",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "loudspeaker",
+ "slug": "loudspeaker",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "megaphone",
+ "slug": "megaphone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "postal horn",
+ "slug": "postal_horn",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bell",
+ "slug": "bell",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bell with slash",
+ "slug": "bell_with_slash",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "musical score",
+ "slug": "musical_score",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "musical note",
+ "slug": "musical_note",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "musical notes",
+ "slug": "musical_notes",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "studio microphone",
+ "slug": "studio_microphone",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "level slider",
+ "slug": "level_slider",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "control knobs",
+ "slug": "control_knobs",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "microphone",
+ "slug": "microphone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "headphone",
+ "slug": "headphone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "radio",
+ "slug": "radio",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "saxophone",
+ "slug": "saxophone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "accordion",
+ "slug": "accordion",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "guitar",
+ "slug": "guitar",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "musical keyboard",
+ "slug": "musical_keyboard",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "trumpet",
+ "slug": "trumpet",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "violin",
+ "slug": "violin",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "banjo",
+ "slug": "banjo",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "drum",
+ "slug": "drum",
+ "group": "Objects",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "long drum",
+ "slug": "long_drum",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "maracas",
+ "slug": "maracas",
+ "group": "Objects",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "flute",
+ "slug": "flute",
+ "group": "Objects",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "mobile phone",
+ "slug": "mobile_phone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "mobile phone with arrow",
+ "slug": "mobile_phone_with_arrow",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "telephone",
+ "slug": "telephone",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "telephone receiver",
+ "slug": "telephone_receiver",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pager",
+ "slug": "pager",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "fax machine",
+ "slug": "fax_machine",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "battery",
+ "slug": "battery",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชซ": {
+ "name": "low battery",
+ "slug": "low_battery",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "electric plug",
+ "slug": "electric_plug",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "laptop",
+ "slug": "laptop",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ๏ธ": {
+ "name": "desktop computer",
+ "slug": "desktop_computer",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐จ๏ธ": {
+ "name": "printer",
+ "slug": "printer",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โจ๏ธ": {
+ "name": "keyboard",
+ "slug": "keyboard",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๏ธ": {
+ "name": "computer mouse",
+ "slug": "computer_mouse",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฒ๏ธ": {
+ "name": "trackball",
+ "slug": "trackball",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "computer disk",
+ "slug": "computer_disk",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "floppy disk",
+ "slug": "floppy_disk",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "optical disk",
+ "slug": "optical_disk",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "dvd",
+ "slug": "dvd",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งฎ": {
+ "name": "abacus",
+ "slug": "abacus",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "movie camera",
+ "slug": "movie_camera",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "film frames",
+ "slug": "film_frames",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฝ๏ธ": {
+ "name": "film projector",
+ "slug": "film_projector",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "clapper board",
+ "slug": "clapper_board",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "television",
+ "slug": "television",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "camera",
+ "slug": "camera",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "camera with flash",
+ "slug": "camera_with_flash",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "video camera",
+ "slug": "video_camera",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "videocassette",
+ "slug": "videocassette",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "magnifying glass tilted left",
+ "slug": "magnifying_glass_tilted_left",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "magnifying glass tilted right",
+ "slug": "magnifying_glass_tilted_right",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ๏ธ": {
+ "name": "candle",
+ "slug": "candle",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "light bulb",
+ "slug": "light_bulb",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "flashlight",
+ "slug": "flashlight",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "red paper lantern",
+ "slug": "red_paper_lantern",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "diya lamp",
+ "slug": "diya_lamp",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "notebook with decorative cover",
+ "slug": "notebook_with_decorative_cover",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "closed book",
+ "slug": "closed_book",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "open book",
+ "slug": "open_book",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "green book",
+ "slug": "green_book",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "blue book",
+ "slug": "blue_book",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "orange book",
+ "slug": "orange_book",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "books",
+ "slug": "books",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "notebook",
+ "slug": "notebook",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ledger",
+ "slug": "ledger",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "page with curl",
+ "slug": "page_with_curl",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "scroll",
+ "slug": "scroll",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "page facing up",
+ "slug": "page_facing_up",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "newspaper",
+ "slug": "newspaper",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "rolled-up newspaper",
+ "slug": "rolled_up_newspaper",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bookmark tabs",
+ "slug": "bookmark_tabs",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bookmark",
+ "slug": "bookmark",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท๏ธ": {
+ "name": "label",
+ "slug": "label",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "money bag",
+ "slug": "money_bag",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "coin",
+ "slug": "coin",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "yen banknote",
+ "slug": "yen_banknote",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "dollar banknote",
+ "slug": "dollar_banknote",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "euro banknote",
+ "slug": "euro_banknote",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "pound banknote",
+ "slug": "pound_banknote",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "money with wings",
+ "slug": "money_with_wings",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "credit card",
+ "slug": "credit_card",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐งพ": {
+ "name": "receipt",
+ "slug": "receipt",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "chart increasing with yen",
+ "slug": "chart_increasing_with_yen",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "envelope",
+ "slug": "envelope",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "e-mail",
+ "slug": "e_mail",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "incoming envelope",
+ "slug": "incoming_envelope",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "envelope with arrow",
+ "slug": "envelope_with_arrow",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "outbox tray",
+ "slug": "outbox_tray",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "inbox tray",
+ "slug": "inbox_tray",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "package",
+ "slug": "package",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "closed mailbox with raised flag",
+ "slug": "closed_mailbox_with_raised_flag",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "closed mailbox with lowered flag",
+ "slug": "closed_mailbox_with_lowered_flag",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "open mailbox with raised flag",
+ "slug": "open_mailbox_with_raised_flag",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "open mailbox with lowered flag",
+ "slug": "open_mailbox_with_lowered_flag",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "postbox",
+ "slug": "postbox",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธ": {
+ "name": "ballot box with ballot",
+ "slug": "ballot_box_with_ballot",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "pencil",
+ "slug": "pencil",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "black nib",
+ "slug": "black_nib",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "fountain pen",
+ "slug": "fountain_pen",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "pen",
+ "slug": "pen",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "paintbrush",
+ "slug": "paintbrush",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "crayon",
+ "slug": "crayon",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "memo",
+ "slug": "memo",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "briefcase",
+ "slug": "briefcase",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "file folder",
+ "slug": "file_folder",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "open file folder",
+ "slug": "open_file_folder",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "card index dividers",
+ "slug": "card_index_dividers",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "calendar",
+ "slug": "calendar",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "tear-off calendar",
+ "slug": "tear_off_calendar",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "spiral notepad",
+ "slug": "spiral_notepad",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "spiral calendar",
+ "slug": "spiral_calendar",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "card index",
+ "slug": "card_index",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "chart increasing",
+ "slug": "chart_increasing",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "chart decreasing",
+ "slug": "chart_decreasing",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bar chart",
+ "slug": "bar_chart",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "clipboard",
+ "slug": "clipboard",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pushpin",
+ "slug": "pushpin",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "round pushpin",
+ "slug": "round_pushpin",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "paperclip",
+ "slug": "paperclip",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "linked paperclips",
+ "slug": "linked_paperclips",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "straight ruler",
+ "slug": "straight_ruler",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "triangular ruler",
+ "slug": "triangular_ruler",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "scissors",
+ "slug": "scissors",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "card file box",
+ "slug": "card_file_box",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "file cabinet",
+ "slug": "file_cabinet",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "wastebasket",
+ "slug": "wastebasket",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "locked",
+ "slug": "locked",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "unlocked",
+ "slug": "unlocked",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "locked with pen",
+ "slug": "locked_with_pen",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "locked with key",
+ "slug": "locked_with_key",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "key",
+ "slug": "key",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "old key",
+ "slug": "old_key",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "hammer",
+ "slug": "hammer",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "axe",
+ "slug": "axe",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "pick",
+ "slug": "pick",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "hammer and pick",
+ "slug": "hammer_and_pick",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ ๏ธ": {
+ "name": "hammer and wrench",
+ "slug": "hammer_and_wrench",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ก๏ธ": {
+ "name": "dagger",
+ "slug": "dagger",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "crossed swords",
+ "slug": "crossed_swords",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "bomb",
+ "slug": "bomb",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "boomerang",
+ "slug": "boomerang",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "bow and arrow",
+ "slug": "bow_and_arrow",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ก๏ธ": {
+ "name": "shield",
+ "slug": "shield",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "carpentry saw",
+ "slug": "carpentry_saw",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "wrench",
+ "slug": "wrench",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "screwdriver",
+ "slug": "screwdriver",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "nut and bolt",
+ "slug": "nut_and_bolt",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "gear",
+ "slug": "gear",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "clamp",
+ "slug": "clamp",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "balance scale",
+ "slug": "balance_scale",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆฏ": {
+ "name": "white cane",
+ "slug": "white_cane",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "link",
+ "slug": "link",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธโ๐ฅ": {
+ "name": "broken chain",
+ "slug": "broken_chain",
+ "group": "Objects",
+ "emoji_version": "15.1",
+ "unicode_version": "15.1",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "chains",
+ "slug": "chains",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "hook",
+ "slug": "hook",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐งฐ": {
+ "name": "toolbox",
+ "slug": "toolbox",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งฒ": {
+ "name": "magnet",
+ "slug": "magnet",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "ladder",
+ "slug": "ladder",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "alembic",
+ "slug": "alembic",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐งช": {
+ "name": "test tube",
+ "slug": "test_tube",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งซ": {
+ "name": "petri dish",
+ "slug": "petri_dish",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งฌ": {
+ "name": "dna",
+ "slug": "dna",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "microscope",
+ "slug": "microscope",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "telescope",
+ "slug": "telescope",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "satellite antenna",
+ "slug": "satellite_antenna",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "syringe",
+ "slug": "syringe",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉธ": {
+ "name": "drop of blood",
+ "slug": "drop_of_blood",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "pill",
+ "slug": "pill",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉน": {
+ "name": "adhesive bandage",
+ "slug": "adhesive_bandage",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉผ": {
+ "name": "crutch",
+ "slug": "crutch",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ฉบ": {
+ "name": "stethoscope",
+ "slug": "stethoscope",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉป": {
+ "name": "x-ray",
+ "slug": "x_ray",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "door",
+ "slug": "door",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "elevator",
+ "slug": "elevator",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "mirror",
+ "slug": "mirror",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "window",
+ "slug": "window",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "bed",
+ "slug": "bed",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "couch and lamp",
+ "slug": "couch_and_lamp",
+ "group": "Objects",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "chair",
+ "slug": "chair",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "toilet",
+ "slug": "toilet",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช ": {
+ "name": "plunger",
+ "slug": "plunger",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "shower",
+ "slug": "shower",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bathtub",
+ "slug": "bathtub",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ชค": {
+ "name": "mouse trap",
+ "slug": "mouse_trap",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "razor",
+ "slug": "razor",
+ "group": "Objects",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐งด": {
+ "name": "lotion bottle",
+ "slug": "lotion_bottle",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งท": {
+ "name": "safety pin",
+ "slug": "safety_pin",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งน": {
+ "name": "broom",
+ "slug": "broom",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งบ": {
+ "name": "basket",
+ "slug": "basket",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งป": {
+ "name": "roll of paper",
+ "slug": "roll_of_paper",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชฃ": {
+ "name": "bucket",
+ "slug": "bucket",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐งผ": {
+ "name": "soap",
+ "slug": "soap",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ซง": {
+ "name": "bubbles",
+ "slug": "bubbles",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ชฅ": {
+ "name": "toothbrush",
+ "slug": "toothbrush",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐งฝ": {
+ "name": "sponge",
+ "slug": "sponge",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐งฏ": {
+ "name": "fire extinguisher",
+ "slug": "fire_extinguisher",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "shopping cart",
+ "slug": "shopping_cart",
+ "group": "Objects",
+ "emoji_version": "3.0",
+ "unicode_version": "3.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ": {
+ "name": "cigarette",
+ "slug": "cigarette",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฐ๏ธ": {
+ "name": "coffin",
+ "slug": "coffin",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ชฆ": {
+ "name": "headstone",
+ "slug": "headstone",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "โฑ๏ธ": {
+ "name": "funeral urn",
+ "slug": "funeral_urn",
+ "group": "Objects",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐งฟ": {
+ "name": "nazar amulet",
+ "slug": "nazar_amulet",
+ "group": "Objects",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ชฌ": {
+ "name": "hamsa",
+ "slug": "hamsa",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ": {
+ "name": "moai",
+ "slug": "moai",
+ "group": "Objects",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชง": {
+ "name": "placard",
+ "slug": "placard",
+ "group": "Objects",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ชช": {
+ "name": "identification card",
+ "slug": "identification_card",
+ "group": "Objects",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "ATM sign",
+ "slug": "atm_sign",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฎ": {
+ "name": "litter in bin sign",
+ "slug": "litter_in_bin_sign",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "potable water",
+ "slug": "potable_water",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฟ": {
+ "name": "wheelchair symbol",
+ "slug": "wheelchair_symbol",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "menโs room",
+ "slug": "men_s_room",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "womenโs room",
+ "slug": "women_s_room",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "restroom",
+ "slug": "restroom",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "baby symbol",
+ "slug": "baby_symbol",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐พ": {
+ "name": "water closet",
+ "slug": "water_closet",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "passport control",
+ "slug": "passport_control",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "customs",
+ "slug": "customs",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "baggage claim",
+ "slug": "baggage_claim",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "left luggage",
+ "slug": "left_luggage",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โ ๏ธ": {
+ "name": "warning",
+ "slug": "warning",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "children crossing",
+ "slug": "children_crossing",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "no entry",
+ "slug": "no_entry",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "prohibited",
+ "slug": "prohibited",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "no bicycles",
+ "slug": "no_bicycles",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ญ": {
+ "name": "no smoking",
+ "slug": "no_smoking",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "no littering",
+ "slug": "no_littering",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "non-potable water",
+ "slug": "non_potable_water",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "no pedestrians",
+ "slug": "no_pedestrians",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "no mobile phones",
+ "slug": "no_mobile_phones",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "no one under eighteen",
+ "slug": "no_one_under_eighteen",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โข๏ธ": {
+ "name": "radioactive",
+ "slug": "radioactive",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฃ๏ธ": {
+ "name": "biohazard",
+ "slug": "biohazard",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โฌ๏ธ": {
+ "name": "up arrow",
+ "slug": "up_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "up-right arrow",
+ "slug": "up_right_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โก๏ธ": {
+ "name": "right arrow",
+ "slug": "right_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "down-right arrow",
+ "slug": "down_right_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฌ๏ธ": {
+ "name": "down arrow",
+ "slug": "down_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "down-left arrow",
+ "slug": "down_left_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฌ
๏ธ": {
+ "name": "left arrow",
+ "slug": "left_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "up-left arrow",
+ "slug": "up_left_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "up-down arrow",
+ "slug": "up_down_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "left-right arrow",
+ "slug": "left_right_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฉ๏ธ": {
+ "name": "right arrow curving left",
+ "slug": "right_arrow_curving_left",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โช๏ธ": {
+ "name": "left arrow curving right",
+ "slug": "left_arrow_curving_right",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โคด๏ธ": {
+ "name": "right arrow curving up",
+ "slug": "right_arrow_curving_up",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โคต๏ธ": {
+ "name": "right arrow curving down",
+ "slug": "right_arrow_curving_down",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "clockwise vertical arrows",
+ "slug": "clockwise_vertical_arrows",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "counterclockwise arrows button",
+ "slug": "counterclockwise_arrows_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "BACK arrow",
+ "slug": "back_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "END arrow",
+ "slug": "end_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ON! arrow",
+ "slug": "on_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "SOON arrow",
+ "slug": "soon_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "TOP arrow",
+ "slug": "top_arrow",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "place of worship",
+ "slug": "place_of_worship",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "atom symbol",
+ "slug": "atom_symbol",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "om",
+ "slug": "om",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โก๏ธ": {
+ "name": "star of David",
+ "slug": "star_of_david",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โธ๏ธ": {
+ "name": "wheel of dharma",
+ "slug": "wheel_of_dharma",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฏ๏ธ": {
+ "name": "yin yang",
+ "slug": "yin_yang",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "latin cross",
+ "slug": "latin_cross",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฆ๏ธ": {
+ "name": "orthodox cross",
+ "slug": "orthodox_cross",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โช๏ธ": {
+ "name": "star and crescent",
+ "slug": "star_and_crescent",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฎ๏ธ": {
+ "name": "peace symbol",
+ "slug": "peace_symbol",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "menorah",
+ "slug": "menorah",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "dotted six-pointed star",
+ "slug": "dotted_six_pointed_star",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ชฏ": {
+ "name": "khanda",
+ "slug": "khanda",
+ "group": "Symbols",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Aries",
+ "slug": "aries",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Taurus",
+ "slug": "taurus",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Gemini",
+ "slug": "gemini",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Cancer",
+ "slug": "cancer",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Leo",
+ "slug": "leo",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Virgo",
+ "slug": "virgo",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Libra",
+ "slug": "libra",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Scorpio",
+ "slug": "scorpio",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Sagittarius",
+ "slug": "sagittarius",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Capricorn",
+ "slug": "capricorn",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Aquarius",
+ "slug": "aquarius",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Pisces",
+ "slug": "pisces",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "Ophiuchus",
+ "slug": "ophiuchus",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "shuffle tracks button",
+ "slug": "shuffle_tracks_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "repeat button",
+ "slug": "repeat_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "repeat single button",
+ "slug": "repeat_single_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โถ๏ธ": {
+ "name": "play button",
+ "slug": "play_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฉ": {
+ "name": "fast-forward button",
+ "slug": "fast_forward_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โญ๏ธ": {
+ "name": "next track button",
+ "slug": "next_track_button",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โฏ๏ธ": {
+ "name": "play or pause button",
+ "slug": "play_or_pause_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "reverse button",
+ "slug": "reverse_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โช": {
+ "name": "fast reverse button",
+ "slug": "fast_reverse_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฎ๏ธ": {
+ "name": "last track button",
+ "slug": "last_track_button",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ผ": {
+ "name": "upwards button",
+ "slug": "upwards_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โซ": {
+ "name": "fast up button",
+ "slug": "fast_up_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฝ": {
+ "name": "downwards button",
+ "slug": "downwards_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฌ": {
+ "name": "fast down button",
+ "slug": "fast_down_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โธ๏ธ": {
+ "name": "pause button",
+ "slug": "pause_button",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โน๏ธ": {
+ "name": "stop button",
+ "slug": "stop_button",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โบ๏ธ": {
+ "name": "record button",
+ "slug": "record_button",
+ "group": "Symbols",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "eject button",
+ "slug": "eject_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "cinema",
+ "slug": "cinema",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
": {
+ "name": "dim button",
+ "slug": "dim_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "bright button",
+ "slug": "bright_button",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "antenna bars",
+ "slug": "antenna_bars",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "wireless",
+ "slug": "wireless",
+ "group": "Symbols",
+ "emoji_version": "15.0",
+ "unicode_version": "15.0",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "vibration mode",
+ "slug": "vibration_mode",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "mobile phone off",
+ "slug": "mobile_phone_off",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "female sign",
+ "slug": "female_sign",
+ "group": "Symbols",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "male sign",
+ "slug": "male_sign",
+ "group": "Symbols",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "โง๏ธ": {
+ "name": "transgender symbol",
+ "slug": "transgender_symbol",
+ "group": "Symbols",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "multiply",
+ "slug": "multiply",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "plus",
+ "slug": "plus",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "minus",
+ "slug": "minus",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "divide",
+ "slug": "divide",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "heavy equals sign",
+ "slug": "heavy_equals_sign",
+ "group": "Symbols",
+ "emoji_version": "14.0",
+ "unicode_version": "14.0",
+ "skin_tone_support": false
+ },
+ "โพ๏ธ": {
+ "name": "infinity",
+ "slug": "infinity",
+ "group": "Symbols",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "โผ๏ธ": {
+ "name": "double exclamation mark",
+ "slug": "double_exclamation_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "exclamation question mark",
+ "slug": "exclamation_question_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "red question mark",
+ "slug": "red_question_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "white question mark",
+ "slug": "white_question_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "white exclamation mark",
+ "slug": "white_exclamation_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "red exclamation mark",
+ "slug": "red_exclamation_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "ใฐ๏ธ": {
+ "name": "wavy dash",
+ "slug": "wavy_dash",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "currency exchange",
+ "slug": "currency_exchange",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "heavy dollar sign",
+ "slug": "heavy_dollar_sign",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "medical symbol",
+ "slug": "medical_symbol",
+ "group": "Symbols",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "โป๏ธ": {
+ "name": "recycling symbol",
+ "slug": "recycling_symbol",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "fleur-de-lis",
+ "slug": "fleur_de_lis",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ": {
+ "name": "trident emblem",
+ "slug": "trident_emblem",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "name badge",
+ "slug": "name_badge",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ": {
+ "name": "Japanese symbol for beginner",
+ "slug": "japanese_symbol_for_beginner",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โญ": {
+ "name": "hollow red circle",
+ "slug": "hollow_red_circle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ
": {
+ "name": "check mark button",
+ "slug": "check_mark_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "check box with check",
+ "slug": "check_box_with_check",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "check mark",
+ "slug": "check_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "cross mark",
+ "slug": "cross_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ": {
+ "name": "cross mark button",
+ "slug": "cross_mark_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฐ": {
+ "name": "curly loop",
+ "slug": "curly_loop",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฟ": {
+ "name": "double curly loop",
+ "slug": "double_curly_loop",
+ "group": "Symbols",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "ใฝ๏ธ": {
+ "name": "part alternation mark",
+ "slug": "part_alternation_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โณ๏ธ": {
+ "name": "eight-spoked asterisk",
+ "slug": "eight_spoked_asterisk",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โด๏ธ": {
+ "name": "eight-pointed star",
+ "slug": "eight_pointed_star",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "sparkle",
+ "slug": "sparkle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "ยฉ๏ธ": {
+ "name": "copyright",
+ "slug": "copyright",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "ยฎ๏ธ": {
+ "name": "registered",
+ "slug": "registered",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โข๏ธ": {
+ "name": "trade mark",
+ "slug": "trade_mark",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "#๏ธโฃ": {
+ "name": "keycap #",
+ "slug": "keycap_number_sign",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "*๏ธโฃ": {
+ "name": "keycap *",
+ "slug": "keycap_asterisk",
+ "group": "Symbols",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "0๏ธโฃ": {
+ "name": "keycap 0",
+ "slug": "keycap_0",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "1๏ธโฃ": {
+ "name": "keycap 1",
+ "slug": "keycap_1",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "2๏ธโฃ": {
+ "name": "keycap 2",
+ "slug": "keycap_2",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "3๏ธโฃ": {
+ "name": "keycap 3",
+ "slug": "keycap_3",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "4๏ธโฃ": {
+ "name": "keycap 4",
+ "slug": "keycap_4",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "5๏ธโฃ": {
+ "name": "keycap 5",
+ "slug": "keycap_5",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "6๏ธโฃ": {
+ "name": "keycap 6",
+ "slug": "keycap_6",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "7๏ธโฃ": {
+ "name": "keycap 7",
+ "slug": "keycap_7",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "8๏ธโฃ": {
+ "name": "keycap 8",
+ "slug": "keycap_8",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "9๏ธโฃ": {
+ "name": "keycap 9",
+ "slug": "keycap_9",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "keycap 10",
+ "slug": "keycap_10",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "input latin uppercase",
+ "slug": "input_latin_uppercase",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "input latin lowercase",
+ "slug": "input_latin_lowercase",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "input numbers",
+ "slug": "input_numbers",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "input symbols",
+ "slug": "input_symbols",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "input latin letters",
+ "slug": "input_latin_letters",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
ฐ๏ธ": {
+ "name": "A button (blood type)",
+ "slug": "a_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "AB button (blood type)",
+ "slug": "ab_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
ฑ๏ธ": {
+ "name": "B button (blood type)",
+ "slug": "b_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "CL button",
+ "slug": "cl_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "COOL button",
+ "slug": "cool_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "FREE button",
+ "slug": "free_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โน๏ธ": {
+ "name": "information",
+ "slug": "information",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "ID button",
+ "slug": "id_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โ๏ธ": {
+ "name": "circled M",
+ "slug": "circled_m",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "NEW button",
+ "slug": "new_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "NG button",
+ "slug": "ng_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
พ๏ธ": {
+ "name": "O button (blood type)",
+ "slug": "o_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "OK button",
+ "slug": "ok_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐
ฟ๏ธ": {
+ "name": "P button",
+ "slug": "p_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "SOS button",
+ "slug": "sos_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "UP! button",
+ "slug": "up_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "VS button",
+ "slug": "vs_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Japanese โhereโ button",
+ "slug": "japanese_here_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐๏ธ": {
+ "name": "Japanese โservice chargeโ button",
+ "slug": "japanese_service_charge_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท๏ธ": {
+ "name": "Japanese โmonthly amountโ button",
+ "slug": "japanese_monthly_amount_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "Japanese โnot free of chargeโ button",
+ "slug": "japanese_not_free_of_charge_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ": {
+ "name": "Japanese โreservedโ button",
+ "slug": "japanese_reserved_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Japanese โbargainโ button",
+ "slug": "japanese_bargain_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "Japanese โdiscountโ button",
+ "slug": "japanese_discount_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Japanese โfree of chargeโ button",
+ "slug": "japanese_free_of_charge_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "Japanese โprohibitedโ button",
+ "slug": "japanese_prohibited_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "Japanese โacceptableโ button",
+ "slug": "japanese_acceptable_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "Japanese โapplicationโ button",
+ "slug": "japanese_application_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "Japanese โpassing gradeโ button",
+ "slug": "japanese_passing_grade_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "Japanese โvacancyโ button",
+ "slug": "japanese_vacancy_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "ใ๏ธ": {
+ "name": "Japanese โcongratulationsโ button",
+ "slug": "japanese_congratulations_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "ใ๏ธ": {
+ "name": "Japanese โsecretโ button",
+ "slug": "japanese_secret_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "Japanese โopen for businessโ button",
+ "slug": "japanese_open_for_business_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "Japanese โno vacancyโ button",
+ "slug": "japanese_no_vacancy_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "red circle",
+ "slug": "red_circle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "orange circle",
+ "slug": "orange_circle",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ก": {
+ "name": "yellow circle",
+ "slug": "yellow_circle",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ข": {
+ "name": "green circle",
+ "slug": "green_circle",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ต": {
+ "name": "blue circle",
+ "slug": "blue_circle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฃ": {
+ "name": "purple circle",
+ "slug": "purple_circle",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ค": {
+ "name": "brown circle",
+ "slug": "brown_circle",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "โซ": {
+ "name": "black circle",
+ "slug": "black_circle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โช": {
+ "name": "white circle",
+ "slug": "white_circle",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฅ": {
+ "name": "red square",
+ "slug": "red_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ง": {
+ "name": "orange square",
+ "slug": "orange_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐จ": {
+ "name": "yellow square",
+ "slug": "yellow_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "green square",
+ "slug": "green_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ": {
+ "name": "blue square",
+ "slug": "blue_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ช": {
+ "name": "purple square",
+ "slug": "purple_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "๐ซ": {
+ "name": "brown square",
+ "slug": "brown_square",
+ "group": "Symbols",
+ "emoji_version": "12.0",
+ "unicode_version": "12.0",
+ "skin_tone_support": false
+ },
+ "โฌ": {
+ "name": "black large square",
+ "slug": "black_large_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฌ": {
+ "name": "white large square",
+ "slug": "white_large_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โผ๏ธ": {
+ "name": "black medium square",
+ "slug": "black_medium_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โป๏ธ": {
+ "name": "white medium square",
+ "slug": "white_medium_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โพ": {
+ "name": "black medium-small square",
+ "slug": "black_medium_small_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โฝ": {
+ "name": "white medium-small square",
+ "slug": "white_medium_small_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โช๏ธ": {
+ "name": "black small square",
+ "slug": "black_small_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "โซ๏ธ": {
+ "name": "white small square",
+ "slug": "white_small_square",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ถ": {
+ "name": "large orange diamond",
+ "slug": "large_orange_diamond",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท": {
+ "name": "large blue diamond",
+ "slug": "large_blue_diamond",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ธ": {
+ "name": "small orange diamond",
+ "slug": "small_orange_diamond",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐น": {
+ "name": "small blue diamond",
+ "slug": "small_blue_diamond",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ": {
+ "name": "red triangle pointed up",
+ "slug": "red_triangle_pointed_up",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ป": {
+ "name": "red triangle pointed down",
+ "slug": "red_triangle_pointed_down",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ ": {
+ "name": "diamond with a dot",
+ "slug": "diamond_with_a_dot",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "radio button",
+ "slug": "radio_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ณ": {
+ "name": "white square button",
+ "slug": "white_square_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฒ": {
+ "name": "black square button",
+ "slug": "black_square_button",
+ "group": "Symbols",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "chequered flag",
+ "slug": "chequered_flag",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ": {
+ "name": "triangular flag",
+ "slug": "triangular_flag",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐": {
+ "name": "crossed flags",
+ "slug": "crossed_flags",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ด": {
+ "name": "black flag",
+ "slug": "black_flag",
+ "group": "Flags",
+ "emoji_version": "1.0",
+ "unicode_version": "1.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธ": {
+ "name": "white flag",
+ "slug": "white_flag",
+ "group": "Flags",
+ "emoji_version": "0.7",
+ "unicode_version": "0.7",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธโ๐": {
+ "name": "rainbow flag",
+ "slug": "rainbow_flag",
+ "group": "Flags",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๏ธโโง๏ธ": {
+ "name": "transgender flag",
+ "slug": "transgender_flag",
+ "group": "Flags",
+ "emoji_version": "13.0",
+ "unicode_version": "13.0",
+ "skin_tone_support": false
+ },
+ "๐ดโโ ๏ธ": {
+ "name": "pirate flag",
+ "slug": "pirate_flag",
+ "group": "Flags",
+ "emoji_version": "11.0",
+ "unicode_version": "11.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐จ": {
+ "name": "flag Ascension Island",
+ "slug": "flag_ascension_island",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฉ": {
+ "name": "flag Andorra",
+ "slug": "flag_andorra",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ช": {
+ "name": "flag United Arab Emirates",
+ "slug": "flag_united_arab_emirates",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ซ": {
+ "name": "flag Afghanistan",
+ "slug": "flag_afghanistan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฌ": {
+ "name": "flag Antigua & Barbuda",
+ "slug": "flag_antigua_barbuda",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฎ": {
+ "name": "flag Anguilla",
+ "slug": "flag_anguilla",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฑ": {
+ "name": "flag Albania",
+ "slug": "flag_albania",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฒ": {
+ "name": "flag Armenia",
+ "slug": "flag_armenia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ด": {
+ "name": "flag Angola",
+ "slug": "flag_angola",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ถ": {
+ "name": "flag Antarctica",
+ "slug": "flag_antarctica",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ท": {
+ "name": "flag Argentina",
+ "slug": "flag_argentina",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ธ": {
+ "name": "flag American Samoa",
+ "slug": "flag_american_samoa",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐น": {
+ "name": "flag Austria",
+ "slug": "flag_austria",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐บ": {
+ "name": "flag Australia",
+ "slug": "flag_australia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ผ": {
+ "name": "flag Aruba",
+ "slug": "flag_aruba",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฝ": {
+ "name": "flag ร
land Islands",
+ "slug": "flag_aland_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฆ๐ฟ": {
+ "name": "flag Azerbaijan",
+ "slug": "flag_azerbaijan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฆ": {
+ "name": "flag Bosnia & Herzegovina",
+ "slug": "flag_bosnia_herzegovina",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ง": {
+ "name": "flag Barbados",
+ "slug": "flag_barbados",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฉ": {
+ "name": "flag Bangladesh",
+ "slug": "flag_bangladesh",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ช": {
+ "name": "flag Belgium",
+ "slug": "flag_belgium",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ซ": {
+ "name": "flag Burkina Faso",
+ "slug": "flag_burkina_faso",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฌ": {
+ "name": "flag Bulgaria",
+ "slug": "flag_bulgaria",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ญ": {
+ "name": "flag Bahrain",
+ "slug": "flag_bahrain",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฎ": {
+ "name": "flag Burundi",
+ "slug": "flag_burundi",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฏ": {
+ "name": "flag Benin",
+ "slug": "flag_benin",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฑ": {
+ "name": "flag St. Barthรฉlemy",
+ "slug": "flag_st_barthelemy",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฒ": {
+ "name": "flag Bermuda",
+ "slug": "flag_bermuda",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ณ": {
+ "name": "flag Brunei",
+ "slug": "flag_brunei",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ด": {
+ "name": "flag Bolivia",
+ "slug": "flag_bolivia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ถ": {
+ "name": "flag Caribbean Netherlands",
+ "slug": "flag_caribbean_netherlands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ท": {
+ "name": "flag Brazil",
+ "slug": "flag_brazil",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ธ": {
+ "name": "flag Bahamas",
+ "slug": "flag_bahamas",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐น": {
+ "name": "flag Bhutan",
+ "slug": "flag_bhutan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ป": {
+ "name": "flag Bouvet Island",
+ "slug": "flag_bouvet_island",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ผ": {
+ "name": "flag Botswana",
+ "slug": "flag_botswana",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐พ": {
+ "name": "flag Belarus",
+ "slug": "flag_belarus",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ง๐ฟ": {
+ "name": "flag Belize",
+ "slug": "flag_belize",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฆ": {
+ "name": "flag Canada",
+ "slug": "flag_canada",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐จ": {
+ "name": "flag Cocos (Keeling) Islands",
+ "slug": "flag_cocos_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฉ": {
+ "name": "flag Congo - Kinshasa",
+ "slug": "flag_congo_kinshasa",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ซ": {
+ "name": "flag Central African Republic",
+ "slug": "flag_central_african_republic",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฌ": {
+ "name": "flag Congo - Brazzaville",
+ "slug": "flag_congo_brazzaville",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ญ": {
+ "name": "flag Switzerland",
+ "slug": "flag_switzerland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฎ": {
+ "name": "flag Cรดte dโIvoire",
+ "slug": "flag_cote_d_ivoire",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฐ": {
+ "name": "flag Cook Islands",
+ "slug": "flag_cook_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฑ": {
+ "name": "flag Chile",
+ "slug": "flag_chile",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฒ": {
+ "name": "flag Cameroon",
+ "slug": "flag_cameroon",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ณ": {
+ "name": "flag China",
+ "slug": "flag_china",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐จ๐ด": {
+ "name": "flag Colombia",
+ "slug": "flag_colombia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ต": {
+ "name": "flag Clipperton Island",
+ "slug": "flag_clipperton_island",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ท": {
+ "name": "flag Costa Rica",
+ "slug": "flag_costa_rica",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐บ": {
+ "name": "flag Cuba",
+ "slug": "flag_cuba",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ป": {
+ "name": "flag Cape Verde",
+ "slug": "flag_cape_verde",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ผ": {
+ "name": "flag Curaรงao",
+ "slug": "flag_curacao",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฝ": {
+ "name": "flag Christmas Island",
+ "slug": "flag_christmas_island",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐พ": {
+ "name": "flag Cyprus",
+ "slug": "flag_cyprus",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐จ๐ฟ": {
+ "name": "flag Czechia",
+ "slug": "flag_czechia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ช": {
+ "name": "flag Germany",
+ "slug": "flag_germany",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ฌ": {
+ "name": "flag Diego Garcia",
+ "slug": "flag_diego_garcia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ฏ": {
+ "name": "flag Djibouti",
+ "slug": "flag_djibouti",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ฐ": {
+ "name": "flag Denmark",
+ "slug": "flag_denmark",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ฒ": {
+ "name": "flag Dominica",
+ "slug": "flag_dominica",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ด": {
+ "name": "flag Dominican Republic",
+ "slug": "flag_dominican_republic",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฉ๐ฟ": {
+ "name": "flag Algeria",
+ "slug": "flag_algeria",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ฆ": {
+ "name": "flag Ceuta & Melilla",
+ "slug": "flag_ceuta_melilla",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐จ": {
+ "name": "flag Ecuador",
+ "slug": "flag_ecuador",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ช": {
+ "name": "flag Estonia",
+ "slug": "flag_estonia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ฌ": {
+ "name": "flag Egypt",
+ "slug": "flag_egypt",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ญ": {
+ "name": "flag Western Sahara",
+ "slug": "flag_western_sahara",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ท": {
+ "name": "flag Eritrea",
+ "slug": "flag_eritrea",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐ธ": {
+ "name": "flag Spain",
+ "slug": "flag_spain",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ช๐น": {
+ "name": "flag Ethiopia",
+ "slug": "flag_ethiopia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ช๐บ": {
+ "name": "flag European Union",
+ "slug": "flag_european_union",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ฎ": {
+ "name": "flag Finland",
+ "slug": "flag_finland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ฏ": {
+ "name": "flag Fiji",
+ "slug": "flag_fiji",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ฐ": {
+ "name": "flag Falkland Islands",
+ "slug": "flag_falkland_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ฒ": {
+ "name": "flag Micronesia",
+ "slug": "flag_micronesia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ด": {
+ "name": "flag Faroe Islands",
+ "slug": "flag_faroe_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ซ๐ท": {
+ "name": "flag France",
+ "slug": "flag_france",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฆ": {
+ "name": "flag Gabon",
+ "slug": "flag_gabon",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ง": {
+ "name": "flag United Kingdom",
+ "slug": "flag_united_kingdom",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฉ": {
+ "name": "flag Grenada",
+ "slug": "flag_grenada",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ช": {
+ "name": "flag Georgia",
+ "slug": "flag_georgia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ซ": {
+ "name": "flag French Guiana",
+ "slug": "flag_french_guiana",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฌ": {
+ "name": "flag Guernsey",
+ "slug": "flag_guernsey",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ญ": {
+ "name": "flag Ghana",
+ "slug": "flag_ghana",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฎ": {
+ "name": "flag Gibraltar",
+ "slug": "flag_gibraltar",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฑ": {
+ "name": "flag Greenland",
+ "slug": "flag_greenland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ฒ": {
+ "name": "flag Gambia",
+ "slug": "flag_gambia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ณ": {
+ "name": "flag Guinea",
+ "slug": "flag_guinea",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ต": {
+ "name": "flag Guadeloupe",
+ "slug": "flag_guadeloupe",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ถ": {
+ "name": "flag Equatorial Guinea",
+ "slug": "flag_equatorial_guinea",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ท": {
+ "name": "flag Greece",
+ "slug": "flag_greece",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ธ": {
+ "name": "flag South Georgia & South Sandwich Islands",
+ "slug": "flag_south_georgia_south_sandwich_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐น": {
+ "name": "flag Guatemala",
+ "slug": "flag_guatemala",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐บ": {
+ "name": "flag Guam",
+ "slug": "flag_guam",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐ผ": {
+ "name": "flag Guinea-Bissau",
+ "slug": "flag_guinea_bissau",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฌ๐พ": {
+ "name": "flag Guyana",
+ "slug": "flag_guyana",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐ฐ": {
+ "name": "flag Hong Kong SAR China",
+ "slug": "flag_hong_kong_sar_china",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐ฒ": {
+ "name": "flag Heard & McDonald Islands",
+ "slug": "flag_heard_mcdonald_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐ณ": {
+ "name": "flag Honduras",
+ "slug": "flag_honduras",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐ท": {
+ "name": "flag Croatia",
+ "slug": "flag_croatia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐น": {
+ "name": "flag Haiti",
+ "slug": "flag_haiti",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ญ๐บ": {
+ "name": "flag Hungary",
+ "slug": "flag_hungary",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐จ": {
+ "name": "flag Canary Islands",
+ "slug": "flag_canary_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ฉ": {
+ "name": "flag Indonesia",
+ "slug": "flag_indonesia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ช": {
+ "name": "flag Ireland",
+ "slug": "flag_ireland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ฑ": {
+ "name": "flag Israel",
+ "slug": "flag_israel",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ฒ": {
+ "name": "flag Isle of Man",
+ "slug": "flag_isle_of_man",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ณ": {
+ "name": "flag India",
+ "slug": "flag_india",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ด": {
+ "name": "flag British Indian Ocean Territory",
+ "slug": "flag_british_indian_ocean_territory",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ถ": {
+ "name": "flag Iraq",
+ "slug": "flag_iraq",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ท": {
+ "name": "flag Iran",
+ "slug": "flag_iran",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐ธ": {
+ "name": "flag Iceland",
+ "slug": "flag_iceland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฎ๐น": {
+ "name": "flag Italy",
+ "slug": "flag_italy",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฏ๐ช": {
+ "name": "flag Jersey",
+ "slug": "flag_jersey",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ๐ฒ": {
+ "name": "flag Jamaica",
+ "slug": "flag_jamaica",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ๐ด": {
+ "name": "flag Jordan",
+ "slug": "flag_jordan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฏ๐ต": {
+ "name": "flag Japan",
+ "slug": "flag_japan",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ช": {
+ "name": "flag Kenya",
+ "slug": "flag_kenya",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ฌ": {
+ "name": "flag Kyrgyzstan",
+ "slug": "flag_kyrgyzstan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ญ": {
+ "name": "flag Cambodia",
+ "slug": "flag_cambodia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ฎ": {
+ "name": "flag Kiribati",
+ "slug": "flag_kiribati",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ฒ": {
+ "name": "flag Comoros",
+ "slug": "flag_comoros",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ณ": {
+ "name": "flag St. Kitts & Nevis",
+ "slug": "flag_st_kitts_nevis",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ต": {
+ "name": "flag North Korea",
+ "slug": "flag_north_korea",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ท": {
+ "name": "flag South Korea",
+ "slug": "flag_south_korea",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ผ": {
+ "name": "flag Kuwait",
+ "slug": "flag_kuwait",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐พ": {
+ "name": "flag Cayman Islands",
+ "slug": "flag_cayman_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฐ๐ฟ": {
+ "name": "flag Kazakhstan",
+ "slug": "flag_kazakhstan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ฆ": {
+ "name": "flag Laos",
+ "slug": "flag_laos",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ง": {
+ "name": "flag Lebanon",
+ "slug": "flag_lebanon",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐จ": {
+ "name": "flag St. Lucia",
+ "slug": "flag_st_lucia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ฎ": {
+ "name": "flag Liechtenstein",
+ "slug": "flag_liechtenstein",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ฐ": {
+ "name": "flag Sri Lanka",
+ "slug": "flag_sri_lanka",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ท": {
+ "name": "flag Liberia",
+ "slug": "flag_liberia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ธ": {
+ "name": "flag Lesotho",
+ "slug": "flag_lesotho",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐น": {
+ "name": "flag Lithuania",
+ "slug": "flag_lithuania",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐บ": {
+ "name": "flag Luxembourg",
+ "slug": "flag_luxembourg",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐ป": {
+ "name": "flag Latvia",
+ "slug": "flag_latvia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฑ๐พ": {
+ "name": "flag Libya",
+ "slug": "flag_libya",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฆ": {
+ "name": "flag Morocco",
+ "slug": "flag_morocco",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐จ": {
+ "name": "flag Monaco",
+ "slug": "flag_monaco",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฉ": {
+ "name": "flag Moldova",
+ "slug": "flag_moldova",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ช": {
+ "name": "flag Montenegro",
+ "slug": "flag_montenegro",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ซ": {
+ "name": "flag St. Martin",
+ "slug": "flag_st_martin",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฌ": {
+ "name": "flag Madagascar",
+ "slug": "flag_madagascar",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ญ": {
+ "name": "flag Marshall Islands",
+ "slug": "flag_marshall_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฐ": {
+ "name": "flag North Macedonia",
+ "slug": "flag_north_macedonia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฑ": {
+ "name": "flag Mali",
+ "slug": "flag_mali",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฒ": {
+ "name": "flag Myanmar (Burma)",
+ "slug": "flag_myanmar",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ณ": {
+ "name": "flag Mongolia",
+ "slug": "flag_mongolia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ด": {
+ "name": "flag Macao SAR China",
+ "slug": "flag_macao_sar_china",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ต": {
+ "name": "flag Northern Mariana Islands",
+ "slug": "flag_northern_mariana_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ถ": {
+ "name": "flag Martinique",
+ "slug": "flag_martinique",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ท": {
+ "name": "flag Mauritania",
+ "slug": "flag_mauritania",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ธ": {
+ "name": "flag Montserrat",
+ "slug": "flag_montserrat",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐น": {
+ "name": "flag Malta",
+ "slug": "flag_malta",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐บ": {
+ "name": "flag Mauritius",
+ "slug": "flag_mauritius",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ป": {
+ "name": "flag Maldives",
+ "slug": "flag_maldives",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ผ": {
+ "name": "flag Malawi",
+ "slug": "flag_malawi",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฝ": {
+ "name": "flag Mexico",
+ "slug": "flag_mexico",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐พ": {
+ "name": "flag Malaysia",
+ "slug": "flag_malaysia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฒ๐ฟ": {
+ "name": "flag Mozambique",
+ "slug": "flag_mozambique",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ฆ": {
+ "name": "flag Namibia",
+ "slug": "flag_namibia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐จ": {
+ "name": "flag New Caledonia",
+ "slug": "flag_new_caledonia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ช": {
+ "name": "flag Niger",
+ "slug": "flag_niger",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ซ": {
+ "name": "flag Norfolk Island",
+ "slug": "flag_norfolk_island",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ฌ": {
+ "name": "flag Nigeria",
+ "slug": "flag_nigeria",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ฎ": {
+ "name": "flag Nicaragua",
+ "slug": "flag_nicaragua",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ฑ": {
+ "name": "flag Netherlands",
+ "slug": "flag_netherlands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ด": {
+ "name": "flag Norway",
+ "slug": "flag_norway",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ต": {
+ "name": "flag Nepal",
+ "slug": "flag_nepal",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ท": {
+ "name": "flag Nauru",
+ "slug": "flag_nauru",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐บ": {
+ "name": "flag Niue",
+ "slug": "flag_niue",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ณ๐ฟ": {
+ "name": "flag New Zealand",
+ "slug": "flag_new_zealand",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ด๐ฒ": {
+ "name": "flag Oman",
+ "slug": "flag_oman",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ฆ": {
+ "name": "flag Panama",
+ "slug": "flag_panama",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ช": {
+ "name": "flag Peru",
+ "slug": "flag_peru",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ซ": {
+ "name": "flag French Polynesia",
+ "slug": "flag_french_polynesia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ฌ": {
+ "name": "flag Papua New Guinea",
+ "slug": "flag_papua_new_guinea",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ญ": {
+ "name": "flag Philippines",
+ "slug": "flag_philippines",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ฐ": {
+ "name": "flag Pakistan",
+ "slug": "flag_pakistan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ฑ": {
+ "name": "flag Poland",
+ "slug": "flag_poland",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ฒ": {
+ "name": "flag St. Pierre & Miquelon",
+ "slug": "flag_st_pierre_miquelon",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ณ": {
+ "name": "flag Pitcairn Islands",
+ "slug": "flag_pitcairn_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ท": {
+ "name": "flag Puerto Rico",
+ "slug": "flag_puerto_rico",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ธ": {
+ "name": "flag Palestinian Territories",
+ "slug": "flag_palestinian_territories",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐น": {
+ "name": "flag Portugal",
+ "slug": "flag_portugal",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐ผ": {
+ "name": "flag Palau",
+ "slug": "flag_palau",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ต๐พ": {
+ "name": "flag Paraguay",
+ "slug": "flag_paraguay",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ถ๐ฆ": {
+ "name": "flag Qatar",
+ "slug": "flag_qatar",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ท๐ช": {
+ "name": "flag Rรฉunion",
+ "slug": "flag_reunion",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ท๐ด": {
+ "name": "flag Romania",
+ "slug": "flag_romania",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ท๐ธ": {
+ "name": "flag Serbia",
+ "slug": "flag_serbia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ท๐บ": {
+ "name": "flag Russia",
+ "slug": "flag_russia",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐ท๐ผ": {
+ "name": "flag Rwanda",
+ "slug": "flag_rwanda",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฆ": {
+ "name": "flag Saudi Arabia",
+ "slug": "flag_saudi_arabia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ง": {
+ "name": "flag Solomon Islands",
+ "slug": "flag_solomon_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐จ": {
+ "name": "flag Seychelles",
+ "slug": "flag_seychelles",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฉ": {
+ "name": "flag Sudan",
+ "slug": "flag_sudan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ช": {
+ "name": "flag Sweden",
+ "slug": "flag_sweden",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฌ": {
+ "name": "flag Singapore",
+ "slug": "flag_singapore",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ญ": {
+ "name": "flag St. Helena",
+ "slug": "flag_st_helena",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฎ": {
+ "name": "flag Slovenia",
+ "slug": "flag_slovenia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฏ": {
+ "name": "flag Svalbard & Jan Mayen",
+ "slug": "flag_svalbard_jan_mayen",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฐ": {
+ "name": "flag Slovakia",
+ "slug": "flag_slovakia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฑ": {
+ "name": "flag Sierra Leone",
+ "slug": "flag_sierra_leone",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฒ": {
+ "name": "flag San Marino",
+ "slug": "flag_san_marino",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ณ": {
+ "name": "flag Senegal",
+ "slug": "flag_senegal",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ด": {
+ "name": "flag Somalia",
+ "slug": "flag_somalia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ท": {
+ "name": "flag Suriname",
+ "slug": "flag_suriname",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ธ": {
+ "name": "flag South Sudan",
+ "slug": "flag_south_sudan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐น": {
+ "name": "flag Sรฃo Tomรฉ & Prรญncipe",
+ "slug": "flag_sao_tome_principe",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ป": {
+ "name": "flag El Salvador",
+ "slug": "flag_el_salvador",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฝ": {
+ "name": "flag Sint Maarten",
+ "slug": "flag_sint_maarten",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐พ": {
+ "name": "flag Syria",
+ "slug": "flag_syria",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ธ๐ฟ": {
+ "name": "flag Eswatini",
+ "slug": "flag_eswatini",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฆ": {
+ "name": "flag Tristan da Cunha",
+ "slug": "flag_tristan_da_cunha",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐จ": {
+ "name": "flag Turks & Caicos Islands",
+ "slug": "flag_turks_caicos_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฉ": {
+ "name": "flag Chad",
+ "slug": "flag_chad",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ซ": {
+ "name": "flag French Southern Territories",
+ "slug": "flag_french_southern_territories",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฌ": {
+ "name": "flag Togo",
+ "slug": "flag_togo",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ญ": {
+ "name": "flag Thailand",
+ "slug": "flag_thailand",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฏ": {
+ "name": "flag Tajikistan",
+ "slug": "flag_tajikistan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฐ": {
+ "name": "flag Tokelau",
+ "slug": "flag_tokelau",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฑ": {
+ "name": "flag Timor-Leste",
+ "slug": "flag_timor_leste",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฒ": {
+ "name": "flag Turkmenistan",
+ "slug": "flag_turkmenistan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ณ": {
+ "name": "flag Tunisia",
+ "slug": "flag_tunisia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ด": {
+ "name": "flag Tonga",
+ "slug": "flag_tonga",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ท": {
+ "name": "flag Tรผrkiye",
+ "slug": "flag_turkiye",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐น": {
+ "name": "flag Trinidad & Tobago",
+ "slug": "flag_trinidad_tobago",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ป": {
+ "name": "flag Tuvalu",
+ "slug": "flag_tuvalu",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ผ": {
+ "name": "flag Taiwan",
+ "slug": "flag_taiwan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐น๐ฟ": {
+ "name": "flag Tanzania",
+ "slug": "flag_tanzania",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ฆ": {
+ "name": "flag Ukraine",
+ "slug": "flag_ukraine",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ฌ": {
+ "name": "flag Uganda",
+ "slug": "flag_uganda",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ฒ": {
+ "name": "flag U.S. Outlying Islands",
+ "slug": "flag_u_s_outlying_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ณ": {
+ "name": "flag United Nations",
+ "slug": "flag_united_nations",
+ "group": "Flags",
+ "emoji_version": "4.0",
+ "unicode_version": "4.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ธ": {
+ "name": "flag United States",
+ "slug": "flag_united_states",
+ "group": "Flags",
+ "emoji_version": "0.6",
+ "unicode_version": "0.6",
+ "skin_tone_support": false
+ },
+ "๐บ๐พ": {
+ "name": "flag Uruguay",
+ "slug": "flag_uruguay",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐บ๐ฟ": {
+ "name": "flag Uzbekistan",
+ "slug": "flag_uzbekistan",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐ฆ": {
+ "name": "flag Vatican City",
+ "slug": "flag_vatican_city",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐จ": {
+ "name": "flag St. Vincent & Grenadines",
+ "slug": "flag_st_vincent_grenadines",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐ช": {
+ "name": "flag Venezuela",
+ "slug": "flag_venezuela",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐ฌ": {
+ "name": "flag British Virgin Islands",
+ "slug": "flag_british_virgin_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐ฎ": {
+ "name": "flag U.S. Virgin Islands",
+ "slug": "flag_u_s_virgin_islands",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐ณ": {
+ "name": "flag Vietnam",
+ "slug": "flag_vietnam",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ป๐บ": {
+ "name": "flag Vanuatu",
+ "slug": "flag_vanuatu",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ผ๐ซ": {
+ "name": "flag Wallis & Futuna",
+ "slug": "flag_wallis_futuna",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ผ๐ธ": {
+ "name": "flag Samoa",
+ "slug": "flag_samoa",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฝ๐ฐ": {
+ "name": "flag Kosovo",
+ "slug": "flag_kosovo",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐พ๐ช": {
+ "name": "flag Yemen",
+ "slug": "flag_yemen",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐พ๐น": {
+ "name": "flag Mayotte",
+ "slug": "flag_mayotte",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ๐ฆ": {
+ "name": "flag South Africa",
+ "slug": "flag_south_africa",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ๐ฒ": {
+ "name": "flag Zambia",
+ "slug": "flag_zambia",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ฟ๐ผ": {
+ "name": "flag Zimbabwe",
+ "slug": "flag_zimbabwe",
+ "group": "Flags",
+ "emoji_version": "2.0",
+ "unicode_version": "2.0",
+ "skin_tone_support": false
+ },
+ "๐ด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ": {
+ "name": "flag England",
+ "slug": "flag_england",
+ "group": "Flags",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ": {
+ "name": "flag Scotland",
+ "slug": "flag_scotland",
+ "group": "Flags",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ },
+ "๐ด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ": {
+ "name": "flag Wales",
+ "slug": "flag_wales",
+ "group": "Flags",
+ "emoji_version": "5.0",
+ "unicode_version": "5.0",
+ "skin_tone_support": false
+ }
+}
diff --git a/config/assets/launcher.json b/config/assets/launcher.json
new file mode 100644
index 0000000..673251d
--- /dev/null
+++ b/config/assets/launcher.json
@@ -0,0 +1,11 @@
+{
+ "commands": {
+ ":wp": "launcher.open(\"wallpapers\")",
+ ":em": "launcher.open(\"emoji\")",
+ ":ch": "launcher.open(\"cliphist\")",
+ ":td": "launcher.open(\"todo\")",
+ ":bt": "launcher.open(\"bluetooth\")",
+ ":sh": "launcher.open(\"sh\")",
+ ":pw": "launcher.open(\"power\")"
+ }
+}
diff --git a/config/assets/settings.json b/config/assets/settings.json
new file mode 100644
index 0000000..65e8d2b
--- /dev/null
+++ b/config/assets/settings.json
@@ -0,0 +1,5 @@
+{
+ "color-scheme": "dark",
+ "custom-color": "none",
+ "generation-scheme": "tonalSpot"
+}
diff --git a/config/config.py b/config/config.py
new file mode 100644
index 0000000..0f2c399
--- /dev/null
+++ b/config/config.py
@@ -0,0 +1,422 @@
+import os
+import json
+import shutil
+import gi
+import subprocess
+from concurrent.futures import ThreadPoolExecutor
+
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+
+# Constants
+SOURCE_STRING = """
+# Modus
+source = ~/Modus/config/hypr/modus.conf
+"""
+
+CONFIG_DIR = os.path.expanduser("~/Modus")
+WALLPAPERS_DIR_DEFAULT = os.path.expanduser("~/Modus/assets/wallpaper")
+
+# Default key binding values
+bind_vars = {
+ "prefix_restart": "SHIFT ALT",
+ "suffix_restart": "T",
+ "prefix_bluetooth": "ALT",
+ "suffix_bluetooth": "B",
+ "prefix_emoji": "SUPER",
+ "suffix_emoji": "E",
+ "prefix_cliphist": "SUPER",
+ "suffix_cliphist": "V",
+ "prefix_todo": "SUPER",
+ "suffix_todo": "T",
+ "prefix_sh": "SUPER",
+ "suffix_sh": "S",
+ "prefix_walls": "SUPER",
+ "suffix_walls": "W",
+ "prefix_screenshotregion": "SUPER",
+ "suffix_screenshotregion": "Z",
+ "prefix_screenshot": "",
+ "suffix_screenshot": "Print",
+ "prefix_screencast": "SUPER",
+ "suffix_screencast": "R",
+ "prefix_launcher": "SUPER",
+ "suffix_launcher": "D",
+ "prefix_power": "SUPER",
+ "suffix_power": "X",
+ "prefix_toggle": "SUPER",
+ "suffix_toggle": "H",
+ "prefix_randomwallpaper": "ALT SHIFT",
+ "suffix_randomwallpaper": "W",
+ "wallpapers_dir": WALLPAPERS_DIR_DEFAULT,
+}
+
+
+def deep_update(target: dict, update: dict) -> dict:
+ """
+ Recursively update a nested dictionary with values from another dictionary.
+ """
+ for key, value in update.items():
+ if isinstance(value, dict):
+ target[key] = deep_update(target.get(key, {}), value)
+ else:
+ target[key] = value
+ return target
+
+
+def parallel_subprocesses(commands):
+ """
+ Run multiple subprocess commands in parallel.
+ """
+ with ThreadPoolExecutor() as executor:
+ executor.map(subprocess.run, commands)
+
+
+def setup_colors():
+ subprocess.run(
+ [
+ "python",
+ "-O",
+ os.path.expanduser("~/Modus/config/material-colors/generate.py"),
+ "--color",
+ "#0000FF",
+ ]
+ )
+
+
+def setup_sddm():
+ commands = [
+ ["sudo", "mkdir", "-p", "/etc/sddm.conf.d"],
+ [
+ "sudo",
+ "cp",
+ os.path.expanduser("~/Modus/config/sddm/sddm.conf"),
+ "/etc/sddm.conf.d/",
+ ],
+ [
+ "sudo",
+ "cp",
+ os.path.expanduser("~/Modus/config/sddm/sddm.conf"),
+ "/etc/",
+ ],
+ ["sudo", "chmod", "644", "/etc/sddm.conf.d/sddm.conf"],
+ ["sudo", "chmod", "644", "/etc/sddm.conf"],
+ ["sudo", "chmod", "-R", "755", "/usr/share/sddm/themes/corners/"],
+ ]
+ parallel_subprocesses(commands)
+ subprocess.run([os.path.expanduser("~/Modus/config/sddm/scripts/wallpaper.sh")])
+
+
+def copy_wallpapers():
+ dest_wallpaper_dir = os.path.expanduser("~/Pictures/wallpaper")
+ src_wallpaper_dir = os.path.expanduser("~/Modus/assets/wallpaper")
+ if not os.path.exists(dest_wallpaper_dir):
+ shutil.copytree(src_wallpaper_dir, dest_wallpaper_dir, dirs_exist_ok=True)
+ subprocess.run(
+ [
+ "python",
+ os.path.expanduser("~/Modus/config/wallpaper.py"),
+ "-I",
+ os.path.join(dest_wallpaper_dir, "example-1.jpg"),
+ ]
+ )
+
+
+def load_bind_vars():
+ """
+ Load saved key binding variables from JSON, if available.
+ """
+ config_json = os.path.expanduser("~/Modus/config/assets/config.json")
+ try:
+ with open(config_json, "r") as f:
+ saved_vars = json.load(f)
+ bind_vars.update(saved_vars)
+ except FileNotFoundError:
+ # Use default values if no saved config exists
+ pass
+
+
+def generate_hyprconf() -> str:
+ """
+ Generate the Hypr configuration string using the current bind_vars.
+ """
+ home = os.path.expanduser("~")
+ return f"""exec-once = python {home}/Modus/main.py
+exec = pgrep -x "hypridle" > /dev/null || hypridle
+exec = swww-daemon
+exec-once = wl-paste --type text --watch cliphist store
+exec-once = wl-paste --type image --watch cliphist store
+
+$fabricSend = fabric-cli exec modus
+$scriptsDir = $HOME/Modus/config
+
+bind = {bind_vars["prefix_restart"]}, {bind_vars["suffix_restart"]}, exec, killall modus; python {home}/Modus/main.py # Reload Modus | Default: SUPER ALT + T
+bind = {bind_vars["prefix_bluetooth"]}, {bind_vars["suffix_bluetooth"]}, exec, $fabricSend 'launcher.open("bluetooth")' # Bluetooth | Default: ALT + B
+bind = {bind_vars["prefix_emoji"]}, {bind_vars["suffix_emoji"]}, exec, $fabricSend 'launcher.open("emoji")' # Emoji | Default: SUPER + E
+bind = {bind_vars["prefix_cliphist"]}, {bind_vars["suffix_cliphist"]}, exec, $fabricSend 'launcher.open("cliphist")' # Cliphist | Default: SUPER + V
+bind = {bind_vars["prefix_todo"]}, {bind_vars["suffix_todo"]}, exec, $fabricSend 'launcher.open("todo")' # Todo | Default: SUPER + T
+bind = {bind_vars["prefix_sh"]}, {bind_vars["suffix_sh"]}, exec, $fabricSend 'launcher.open("sh")' # Sh | Default: SUPER + S
+bind = {bind_vars["prefix_walls"]}, {bind_vars["suffix_walls"]}, exec, $fabricSend 'launcher.open("wallpapers")' # Wallpaper Selector | Default: SUPER + W
+bind ={bind_vars["prefix_randomwallpaper"]}, {bind_vars["suffix_randomwallpaper"]}, exec, python -O $scriptsDir/wallpaper.py -R # Random Wallpaper | Default: ALT SHIFT + W
+bind = {bind_vars["prefix_launcher"]}, {bind_vars["suffix_launcher"]}, exec, $fabricSend 'launcher.open("launcher")' # App Launcher | Default: SUPER + D
+bind = {bind_vars["prefix_power"]}, {bind_vars["suffix_power"]}, exec, $fabricSend 'launcher.open("power")' # Power Menu | Default: SUPER + X
+bind = {bind_vars["prefix_toggle"]}, {bind_vars["suffix_toggle"]}, exec, $fabricSend 'bar.toggle_hidden()' # Toggle Bar | Default: SUPER + H
+bind = {bind_vars["prefix_screenshotregion"]}, {bind_vars["suffix_screenshotregion"]}, exec, $fabricSend 'sc.screenshot()' # Screenshot Region | Default: SUPER + Z
+bind = {bind_vars["prefix_screenshot"]}, {bind_vars["suffix_screenshot"]}, exec, $fabricSend 'sc.screenshot(True)' # ScreenshotFullScreen | Default: Print
+bind = {bind_vars["prefix_screencast"]}, {bind_vars["suffix_screencast"]}, exec, $fabricSend 'sc.screencast()' # Screencast | Default: SUPER + R
+
+
+# Wallpapers directory: {bind_vars["wallpapers_dir"]}
+
+general {{
+ gaps_in = 2
+ gaps_out = 4
+ border_size = 0
+ layout = dwindle
+}}
+
+decoration {{
+ blur {{
+ enabled = false
+ }}
+ rounding = 15
+ active_opacity = 1
+ inactive_opacity = 1
+ fullscreen_opacity = 1
+
+ dim_inactive = true
+ dim_strength = 0.1
+ dim_special = 0.8
+ shadow {{
+ enabled = false
+ }}
+}}
+
+animations {{
+ enabled = true
+ # Animation curves
+ bezier = linear, 0, 0, 1, 1
+ bezier = md3_standard, 0.2, 0, 0, 1
+ bezier = md3_decel, 0.05, 0.7, 0.1, 1
+ bezier = md3_accel, 0.3, 0, 0.8, 0.15
+ bezier = overshot, 0.05, 0.9, 0.1, 1.1
+ bezier = crazyshot, 0.1, 1.5, 0.76, 0.92
+ bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0
+ bezier = menu_decel, 0.1, 1, 0, 1
+ bezier = menu_accel, 0.38, 0.04, 1, 0.07
+ bezier = easeInOutCirc, 0.85, 0, 0.15, 1
+ bezier = easeOutCirc, 0, 0.55, 0.45, 1
+ bezier = easeOutExpo, 0.16, 1, 0.3, 1
+ bezier = softAcDecel, 0.26, 0.26, 0.15, 1
+ bezier = md2, 0.4, 0, 0.2, 1 # use with .2s duration
+ # Animation configs
+ animation = windows, 1, 3, md3_decel, popin 60%
+ animation = windowsIn, 1, 3, md3_decel, popin 60%
+ animation = windowsOut, 1, 3, md3_accel, popin 60%
+ animation = border, 1, 10, default
+ animation = fade, 1, 3, md3_decel
+ animation = layers, 1, 2, md3_decel, slide
+ animation = layersIn, 1, 3, menu_decel, slide
+ animation = layersOut, 1, 1.6, menu_accel, slide
+ animation = fadeLayersIn, 1, 2, menu_decel
+ animation = fadeLayersOut, 1, 4.5, menu_accel
+ animation = workspaces, 1, 7, menu_decel, slide
+ # animation = workspaces, 1, 2.5, softAcDecel, slide
+ # animation = workspaces, 1, 7, menu_decel, slidefade 15%
+ # animation = specialWorkspace, 1, 3, md3_decel, slidefadevert 15%
+ animation = specialWorkspace, 1, 3, md3_decel, slidevert
+}}
+"""
+
+
+def backup_and_replace(src: str, dest: str, config_name: str):
+ """
+ Backup the existing configuration file and replace it with a new one.
+ """
+ if os.path.exists(dest):
+ backup_path = dest + ".bak"
+ if not os.path.exists(backup_path):
+ shutil.copy(dest, backup_path)
+ print(f"{config_name} config backed up to {backup_path}")
+ shutil.copy(src, dest)
+ print(f"{config_name} config replaced from {src}")
+
+
+class HyprConfGUI(Gtk.Window):
+ def __init__(self, show_lock_checkbox: bool, show_idle_checkbox: bool):
+ super().__init__(title="Configure Key Binds")
+ self.set_border_width(20)
+ self.set_default_size(500, 450)
+ self.set_resizable(False)
+
+ self.selected_face_icon = None
+
+ # Main container
+ main_vbox = Gtk.VBox(spacing=10)
+ self.add(main_vbox)
+
+ # Create input entries for key bindings
+ self.entries = []
+ bindings = [
+ ("Reload Modus", "prefix_restart", "suffix_restart"),
+ ("Bluetooth", "prefix_bluetooth", "suffix_bluetooth"),
+ ("Wallpaper Selector", "prefix_walls", "suffix_walls"),
+ ("Random Wallpaper", "prefix_randomwallpaper", "suffix_randomwallpaper"),
+ ("App Launcher", "prefix_launcher", "suffix_launcher"),
+ ("Power Menu", "prefix_power", "suffix_power"),
+ ("Emoji Selector", "prefix_emoji", "suffix_emoji"),
+ ("Clipboard History", "prefix_cliphist", "suffix_cliphist"),
+ ("Screenshot", "prefix_screenshot", "suffix_screenshot"),
+ ("ScreenRecorder", "prefix_screencast", "suffix_screencast"),
+ ("Screenshot Region", "prefix_screenshotregion", "suffix_screenshotregion"),
+ ("Sh runner", "prefix_sh", "suffix_sh"),
+ ("Todo List", "prefix_todo", "suffix_todo"),
+ ("Toggle Bar", "prefix_toggle", "suffix_toggle"),
+ ]
+
+ for label_text, prefix_key, suffix_key in bindings:
+ entry_box = Gtk.HBox(spacing=10)
+
+ label = Gtk.Label(label=label_text)
+ entry_box.pack_start(label, False, False, 0)
+
+ prefix_entry = Gtk.Entry()
+ prefix_entry.set_text(bind_vars[prefix_key])
+ entry_box.pack_start(prefix_entry, True, True, 0)
+
+ plus_label = Gtk.Label(label=" + ")
+ entry_box.pack_start(plus_label, False, False, 0)
+
+ suffix_entry = Gtk.Entry()
+ suffix_entry.set_text(bind_vars[suffix_key])
+ entry_box.pack_start(suffix_entry, True, True, 0)
+
+ main_vbox.pack_start(entry_box, False, False, 0)
+ self.entries.append((prefix_key, suffix_key, prefix_entry, suffix_entry))
+
+ # Wallpaper directory chooser
+ wall_box = Gtk.HBox(spacing=10)
+ wall_label = Gtk.Label(label="Wallpapers Directory")
+ wall_box.pack_start(wall_label, False, False, 0)
+ self.wall_dir_chooser = Gtk.FileChooserButton(
+ title="Select a folder", action=Gtk.FileChooserAction.SELECT_FOLDER
+ )
+ self.wall_dir_chooser.set_filename(bind_vars["wallpapers_dir"])
+ wall_box.pack_start(self.wall_dir_chooser, True, True, 0)
+ main_vbox.pack_start(wall_box, False, False, 0)
+
+ # Optional checkboxes for replacing configs
+ if show_lock_checkbox:
+ self.lock_checkbox = Gtk.CheckButton(label="Replace Hyprlock config")
+ self.lock_checkbox.set_active(False)
+ main_vbox.pack_start(self.lock_checkbox, False, False, 0)
+ if show_idle_checkbox:
+ self.idle_checkbox = Gtk.CheckButton(label="Replace Hypridle config")
+ self.idle_checkbox.set_active(False)
+ main_vbox.pack_start(self.idle_checkbox, False, False, 0)
+
+ # Accept and Cancel buttons
+ button_box = Gtk.HBox(spacing=10)
+ cancel_btn = Gtk.Button(label="Cancel")
+ cancel_btn.connect("clicked", self.on_cancel)
+ accept_btn = Gtk.Button(label="Accept")
+ accept_btn.connect("clicked", self.on_accept)
+ button_box.pack_end(accept_btn, False, False, 0)
+ button_box.pack_end(cancel_btn, False, False, 0)
+ main_vbox.pack_start(button_box, False, False, 0)
+
+ def on_accept(self, widget):
+ """
+ Save the configuration and update the necessary files.
+ """
+ # Update bind_vars from user inputs
+ for prefix_key, suffix_key, prefix_entry, suffix_entry in self.entries:
+ bind_vars[prefix_key] = prefix_entry.get_text()
+ bind_vars[suffix_key] = suffix_entry.get_text()
+
+ # Update wallpaper directory
+ bind_vars["wallpapers_dir"] = self.wall_dir_chooser.get_filename()
+
+ # Save the updated bind_vars to a JSON file
+ config_json = os.path.expanduser("~/Modus/config/assets/config.json")
+ os.makedirs(os.path.dirname(config_json), exist_ok=True)
+ with open(config_json, "w") as f:
+ json.dump(bind_vars, f)
+
+ # Replace hyprlock config if requested
+ if hasattr(self, "lock_checkbox") and self.lock_checkbox.get_active():
+ src_lock = os.path.expanduser("~/Modus/config/hypr/hyprlock.conf")
+ dest_lock = os.path.expanduser("~/.config/hypr/hyprlock.conf")
+ backup_and_replace(src_lock, dest_lock, "Hyprlock")
+
+ # Replace hypridle config if requested
+ if hasattr(self, "idle_checkbox") and self.idle_checkbox.get_active():
+ src_idle = os.path.expanduser("~/Modus/config/hypr/hypridle.conf")
+ dest_idle = os.path.expanduser("~/.config/hypr/hypridle.conf")
+ backup_and_replace(src_idle, dest_idle, "Hypridle")
+
+ # Append the source string to the Hyprland config if not present
+ hyprland_config_path = os.path.expanduser("~/.config/hypr/hyprland.conf")
+ with open(hyprland_config_path, "r") as f:
+ content = f.read()
+ if SOURCE_STRING not in content:
+ with open(hyprland_config_path, "a") as f:
+ f.write(SOURCE_STRING)
+
+ start_config()
+ self.destroy()
+
+ def on_cancel(self, widget):
+ self.destroy()
+
+
+def start_config():
+ """
+ Run final configuration steps: ensure necessary configs, write the hyprconf, and reload.
+ """
+ copy_wallpapers()
+ setup_colors()
+
+ # Write the generated hypr configuration to file
+ hypr_config_dir = os.path.expanduser("~/Modus/config/hypr/")
+ os.makedirs(hypr_config_dir, exist_ok=True)
+ hypr_conf_path = os.path.join(hypr_config_dir, "modus.conf")
+ with open(hypr_conf_path, "w") as f:
+ f.write(generate_hyprconf())
+
+ # Reload Hyprland configuration
+ os.system("hyprctl reload")
+
+
+def open_config():
+ """
+ Entry point for opening the configuration GUI.
+ """
+ load_bind_vars()
+
+ # Check and copy hyprlock config if needed
+ dest_lock = os.path.expanduser("~/.config/hypr/hyprlock.conf")
+ src_lock = os.path.expanduser("~/Modus/config/hypr/hyprlock.conf")
+ os.makedirs(os.path.dirname(dest_lock), exist_ok=True)
+ show_lock_checkbox = True
+ if not os.path.exists(dest_lock):
+ shutil.copy(src_lock, dest_lock)
+ show_lock_checkbox = False
+
+ # Check and copy hypridle config if needed
+ dest_idle = os.path.expanduser("~/.config/hypr/hypridle.conf")
+ src_idle = os.path.expanduser("~/Modus/config/hypr/hypridle.conf")
+ show_idle_checkbox = True
+ if not os.path.exists(dest_idle):
+ shutil.copy(src_idle, dest_idle)
+ show_idle_checkbox = False
+
+ # Create and run the GUI
+ window = HyprConfGUI(show_lock_checkbox, show_idle_checkbox)
+ window.connect("destroy", Gtk.main_quit)
+ window.show_all()
+ Gtk.main()
+
+
+if __name__ == "__main__":
+ open_config()
diff --git a/config/dark-theme.sh b/config/dark-theme.sh
new file mode 100755
index 0000000..fcb5461
--- /dev/null
+++ b/config/dark-theme.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Function to get the relative path based on the current script's location
+get_relative_path() {
+ local path=$1
+ local level=$2
+ local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+ for ((i = 1; i <= level; i++)); do
+ script_dir="$(dirname "$script_dir")"
+ done
+
+ echo "$script_dir/$path"
+}
+
+# Assign relative paths to variables
+GENERATOR=$(get_relative_path "./material-colors/generate.py")
+SETTINGS_FILE=$(get_relative_path "./assets/settings.json")
+
+# Function to read a value from the JSON file
+get_json_value() {
+ local key=$1
+ jq -r --arg key "$key" '.[$key]' $SETTINGS_FILE
+}
+
+# Function to update a value in the JSON file
+update_json_value() {
+ local key=$1
+ local value=$2
+ jq --arg key "$key" --arg value "$value" \
+ '.[$key] = $value' $SETTINGS_FILE >"$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" $SETTINGS_FILE
+}
+
+toggle() {
+ local color_scheme=$(get_json_value "color-scheme")
+ local generation_scheme=$(get_json_value "generation-scheme")
+
+ if [ "$color_scheme" == "dark" ]; then
+ python -O $GENERATOR -R --color-scheme light --scheme $generation_scheme
+ update_json_value "color-scheme" "light"
+ elif [ "$color_scheme" == "light" ]; then
+ python -O $GENERATOR -R --color-scheme dark --scheme $generation_scheme
+ update_json_value "color-scheme" "dark"
+ else
+ echo "Unknown color scheme: $color_scheme"
+ fi
+}
+
+set() {
+ local new_scheme=$1
+ local generation_scheme=$(get_json_value "generation-scheme")
+ python -O $GENERATOR -R --color-scheme $new_scheme --scheme $generation_scheme
+ update_json_value "color-scheme" $new_scheme
+}
+
+# Process arguments
+if [[ "$1" == "--toggle" ]]; then
+ toggle
+elif [[ "$1" == "--set" ]]; then
+ set $2
+else
+ echo "Usage: $0 --toggle | --set "
+fi
diff --git a/config/hypr/hypridle.conf b/config/hypr/hypridle.conf
new file mode 100644
index 0000000..48bd7d7
--- /dev/null
+++ b/config/hypr/hypridle.conf
@@ -0,0 +1,41 @@
+
+listener {
+ timeout = 500 # in seconds.
+ on-timeout = notify-send "You are idle!" # command to run when timeout has passed.
+ on-resume = notify-send "Welcome back!" # command to run when activity is detected after timeout has fired.
+}
+
+general {
+ lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances.
+ before_sleep_cmd = loginctl lock-session # lock before suspend.
+ after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display.
+}
+
+listener {
+ timeout = 150 # 2.5min.
+ on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor.
+ on-resume = brightnessctl -r # monitor backlight restore.
+}
+
+# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight.
+listener {
+ timeout = 150 # 2.5min.
+ on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight.
+ on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight.
+}
+
+listener {
+ timeout = 300 # 5min
+ on-timeout = loginctl lock-session # lock screen when timeout has passed
+}
+
+listener {
+ timeout = 330 # 5.5min
+ on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed
+ on-resume = hyprctl dispatch dpms on # screen on when activity is detected after timeout has fired.
+}
+
+listener {
+ timeout = 1800 # 30min
+ on-timeout = systemctl suspend # suspend pc
+}
diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf
new file mode 100644
index 0000000..48abea1
--- /dev/null
+++ b/config/hypr/hyprlock.conf
@@ -0,0 +1 @@
+source = ~/.cache/material/hyprlock.conf
diff --git a/config/hypr/modus.conf b/config/hypr/modus.conf
new file mode 100644
index 0000000..cd7dc0d
--- /dev/null
+++ b/config/hypr/modus.conf
@@ -0,0 +1,85 @@
+exec-once = python /home/sankalp/Modus/main.py
+exec = pgrep -x "hypridle" > /dev/null || hypridle
+exec = swww-daemon
+exec-once = wl-paste --type text --watch cliphist store
+exec-once = wl-paste --type image --watch cliphist store
+
+$fabricSend = fabric-cli exec modus
+$scriptsDir = $HOME/Modus/config
+
+bind = SHIFT ALT, T, exec, killall modus; python /home/sankalp/Modus/main.py # Reload Modus | Default: SUPER ALT + T
+bind = ALT, B, exec, $fabricSend 'launcher.open("bluetooth")' # Bluetooth | Default: ALT + B
+bind = SUPER, E, exec, $fabricSend 'launcher.open("emoji")' # Emoji | Default: SUPER + E
+bind = SUPER, V, exec, $fabricSend 'launcher.open("cliphist")' # Cliphist | Default: SUPER + V
+bind = SUPER, T, exec, $fabricSend 'launcher.open("todo")' # Todo | Default: SUPER + T
+bind = SUPER, S, exec, $fabricSend 'launcher.open("sh")' # Sh | Default: SUPER + S
+bind = SUPER, W, exec, $fabricSend 'launcher.open("wallpapers")' # Wallpaper Selector | Default: SUPER + W
+bind =ALT SHIFT, W, exec, python -O $scriptsDir/wallpaper.py -R # Random Wallpaper | Default: ALT SHIFT + W
+bind = SUPER, D, exec, $fabricSend 'launcher.open("launcher")' # App Launcher | Default: SUPER + D
+bind = SUPER, X, exec, $fabricSend 'launcher.open("power")' # Power Menu | Default: SUPER + X
+bind = SUPER, H, exec, $fabricSend 'bar.toggle_hidden()' # Toggle Bar | Default: SUPER + H
+bind = SUPER, Z, exec, $fabricSend 'sc.screenshot()' # Screenshot Region | Default: SUPER + Z
+bind = , Print, exec, $fabricSend 'sc.screenshot(True)' # ScreenshotFullScreen | Default: Print
+bind = SUPER, R, exec, $fabricSend 'sc.screencast()' # Screencast | Default: SUPER + R
+
+
+# Wallpapers directory: /home/sankalp/Pictures/wallpapers
+
+general {
+ gaps_in = 2
+ gaps_out = 4
+ border_size = 0
+ layout = dwindle
+}
+
+decoration {
+ blur {
+ enabled = false
+ }
+ rounding = 15
+ active_opacity = 1
+ inactive_opacity = 1
+ fullscreen_opacity = 1
+
+ dim_inactive = true
+ dim_strength = 0.1
+ dim_special = 0.8
+ shadow {
+ enabled = false
+ }
+}
+
+animations {
+ enabled = true
+ # Animation curves
+ bezier = linear, 0, 0, 1, 1
+ bezier = md3_standard, 0.2, 0, 0, 1
+ bezier = md3_decel, 0.05, 0.7, 0.1, 1
+ bezier = md3_accel, 0.3, 0, 0.8, 0.15
+ bezier = overshot, 0.05, 0.9, 0.1, 1.1
+ bezier = crazyshot, 0.1, 1.5, 0.76, 0.92
+ bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0
+ bezier = menu_decel, 0.1, 1, 0, 1
+ bezier = menu_accel, 0.38, 0.04, 1, 0.07
+ bezier = easeInOutCirc, 0.85, 0, 0.15, 1
+ bezier = easeOutCirc, 0, 0.55, 0.45, 1
+ bezier = easeOutExpo, 0.16, 1, 0.3, 1
+ bezier = softAcDecel, 0.26, 0.26, 0.15, 1
+ bezier = md2, 0.4, 0, 0.2, 1 # use with .2s duration
+ # Animation configs
+ animation = windows, 1, 3, md3_decel, popin 60%
+ animation = windowsIn, 1, 3, md3_decel, popin 60%
+ animation = windowsOut, 1, 3, md3_accel, popin 60%
+ animation = border, 1, 10, default
+ animation = fade, 1, 3, md3_decel
+ animation = layers, 1, 2, md3_decel, slide
+ animation = layersIn, 1, 3, menu_decel, slide
+ animation = layersOut, 1, 1.6, menu_accel, slide
+ animation = fadeLayersIn, 1, 2, menu_decel
+ animation = fadeLayersOut, 1, 4.5, menu_accel
+ animation = workspaces, 1, 7, menu_decel, slide
+ # animation = workspaces, 1, 2.5, softAcDecel, slide
+ # animation = workspaces, 1, 7, menu_decel, slidefade 15%
+ # animation = specialWorkspace, 1, 3, md3_decel, slidefadevert 15%
+ animation = specialWorkspace, 1, 3, md3_decel, slidevert
+}
diff --git a/config/material-colors/__pycache__/generate.cpython-312.opt-1.pyc b/config/material-colors/__pycache__/generate.cpython-312.opt-1.pyc
new file mode 100644
index 0000000..cf26bc0
Binary files /dev/null and b/config/material-colors/__pycache__/generate.cpython-312.opt-1.pyc differ
diff --git a/config/material-colors/__pycache__/generate.cpython-312.pyc b/config/material-colors/__pycache__/generate.cpython-312.pyc
new file mode 100644
index 0000000..cf26bc0
Binary files /dev/null and b/config/material-colors/__pycache__/generate.cpython-312.pyc differ
diff --git a/config/material-colors/__pycache__/generate.cpython-313.opt-1.pyc b/config/material-colors/__pycache__/generate.cpython-313.opt-1.pyc
new file mode 100644
index 0000000..c3560d2
Binary files /dev/null and b/config/material-colors/__pycache__/generate.cpython-313.opt-1.pyc differ
diff --git a/config/material-colors/__pycache__/generate.cpython-313.pyc b/config/material-colors/__pycache__/generate.cpython-313.pyc
new file mode 100644
index 0000000..1a6ea6a
Binary files /dev/null and b/config/material-colors/__pycache__/generate.cpython-313.pyc differ
diff --git a/config/material-colors/generate.py b/config/material-colors/generate.py
new file mode 100644
index 0000000..5bd382b
--- /dev/null
+++ b/config/material-colors/generate.py
@@ -0,0 +1,487 @@
+import argparse
+import hashlib
+import json
+import os
+import pickle
+import random
+import re
+import subprocess
+
+import numpy as np
+from materialyoucolor.dynamiccolor.material_dynamic_colors import (
+ MaterialDynamicColors,
+) # type: ignore # noqa
+from materialyoucolor.hct import Hct # type: ignore
+from materialyoucolor.quantize import QuantizeCelebi # type: ignore
+from materialyoucolor.scheme.dynamic_scheme import DynamicScheme # type: ignore # noqa
+from materialyoucolor.scheme.scheme_content import SchemeContent # type: ignore # noqa
+from materialyoucolor.scheme.scheme_expressive import (
+ SchemeExpressive,
+) # type: ignore # noqa
+from materialyoucolor.scheme.scheme_fidelity import (
+ SchemeFidelity,
+) # type: ignore # noqa
+from materialyoucolor.scheme.scheme_fruit_salad import (
+ SchemeFruitSalad,
+) # type: ignore # noqa
+from materialyoucolor.scheme.scheme_monochrome import (
+ SchemeMonochrome,
+) # type: ignore # noqa
+from materialyoucolor.scheme.scheme_neutral import SchemeNeutral # type: ignore # noqa
+from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow # type: ignore # noqa
+from materialyoucolor.scheme.scheme_tonal_spot import (
+ SchemeTonalSpot,
+) # type: ignore # noqa
+from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant # type: ignore # noqa
+from materialyoucolor.score.score import Score # type: ignore
+from PIL import Image
+
+schemes = {
+ "tonalSpot": SchemeTonalSpot,
+ "expressive": SchemeExpressive,
+ "fruitSalad": SchemeFruitSalad,
+ "monochrome": SchemeMonochrome,
+ "rainbow": SchemeRainbow,
+ "vibrant": SchemeVibrant,
+ "neutral": SchemeNeutral,
+ "fidelity": SchemeFidelity,
+ "content": SchemeContent,
+}
+
+
+def join(*args):
+ return os.path.join(*args)
+
+
+home = os.path.expanduser("~")
+
+script_dir = os.path.dirname(os.path.abspath(__file__))
+cache_path = f"{home}/.cache/material/"
+os.makedirs(cache_path, exist_ok=True)
+
+
+def rgb_to_hex(rgb):
+ return "#{:02x}{:02x}{:02x}".format(*rgb[:3])
+
+
+def rgba_to_rgb(rgba):
+ return f"{rgba[0]}, {rgba[1]}, {rgba[2]}"
+
+
+class Color:
+ def __init__(self, scheme) -> None:
+ self.scheme = scheme
+
+ def __call__(self, name: str):
+ color_name = getattr(MaterialDynamicColors, name)
+ if hasattr(color_name, "get_hct"):
+ return rgb_to_hex(color_name.get_hct(self.scheme).to_rgba())
+ else:
+ return "#000000"
+
+
+class ColorsCache:
+ def __init__(
+ self,
+ colors: DynamicScheme | dict,
+ wallpaper: str,
+ original_color: int,
+ contrast_level: int,
+ scheme_name: str,
+ ) -> None:
+ self.colors: dict[str, str] = {}
+ self.wallpaper = wallpaper
+ self.original_color = original_color
+ self.contrast_level = contrast_level
+ self.scheme_name = scheme_name
+ if isinstance(colors, DynamicScheme):
+ for color in vars(MaterialDynamicColors).keys():
+ color_name = getattr(MaterialDynamicColors, color)
+ if hasattr(color_name, "get_hct"):
+ self.colors[str(color)] = rgb_to_hex(
+ color_name.get_hct(colors).to_rgba()
+ )
+ else:
+ self.colors = colors
+
+
+def colors_dict(cache: ColorsCache):
+ dict = {
+ "wallpaper": cache.wallpaper,
+ "colors": cache.colors,
+ "original_color": cache.original_color,
+ "contrast_level": cache.contrast_level,
+ "scheme_name": cache.scheme_name,
+ }
+ return dict
+
+
+def get_cache_object(object: dict | str):
+ if isinstance(object, str):
+ object = dict(json.loads(object))
+ colors = object["colors"]
+ wallpaper = object["wallpaper"]
+ original_color = object["original_color"]
+ contrast_level = object.get("contrast_level", 0)
+ scheme_name = object.get("scheme_name", "tonalSpot")
+ return ColorsCache(colors, wallpaper, original_color, contrast_level, scheme_name)
+
+
+def get_file_list(folder_path):
+ file_list = []
+ for file in os.listdir(folder_path):
+ if os.path.isfile(join(folder_path, file)):
+ file_list.append(join(folder_path, file))
+ return file_list
+
+
+ready_templates = {
+ "colors.css": "@define-color {name} {hex};\n",
+ "colors.scss": "${name}: {hex};\n",
+}
+additional = {"onBackground": "foreground"}
+
+
+def generate_color_map(scheme: DynamicScheme):
+ color_map: dict[str, str] = {}
+ for color in vars(MaterialDynamicColors).keys():
+ color_name = getattr(MaterialDynamicColors, color)
+ if hasattr(color_name, "get_hct"):
+ rgba = color_name.get_hct(scheme).to_rgba()
+ color_map[color.strip()] = rgb_to_hex(rgba)
+ return color_map
+
+
+class ColorFormatter:
+ def __init__(self, scheme: DynamicScheme):
+ self.color_map = generate_color_map(scheme)
+
+ def apply_transformations(self, value, transformations):
+ intermediate_transforms = [
+ t for t in transformations if not (t.startswith("strip") or t == "rgb")
+ ]
+ final_transforms = [
+ t for t in transformations if t.startswith("strip") or t == "rgb"
+ ]
+
+ for transform in intermediate_transforms:
+ if transform.startswith("lighten"):
+ percent = int(re.search(r"\d+", transform).group())
+ value = self.adjust_brightness(value, percent)
+ elif transform.startswith("darken"):
+ percent = int(re.search(r"\d+", transform).group())
+ value = self.adjust_brightness(value, -percent)
+
+ for transform in final_transforms:
+ if transform.startswith("strip"):
+ value = value.lstrip("#")
+ elif transform == "rgb":
+ value = self.hex_to_rgb(value)
+
+ return value
+
+ def adjust_brightness(self, hex_color, factor):
+ def min_max(v):
+ return min(255, max(0, v))
+
+ hex_color = hex_color.lstrip("#")
+ r, g, b = (int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
+
+ r = min_max(int(r * (1 + factor / 100)))
+ g = min_max(int(g * (1 + factor / 100)))
+ b = min_max(int(b * (1 + factor / 100)))
+
+ return f"#{r:02X}{g:02X}{b:02X}".lower()
+
+ def hex_to_rgb(self, hex_color):
+ hex_color = hex_color.lstrip("#")
+ r, g, b = (int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
+ return f"{r},{g},{b}"
+
+ def parse_transformations(self, transformations_str):
+ transformations = re.findall(r"(\w+)(?:\((\d*)\))?", transformations_str)
+ result = []
+ for command, arg in transformations:
+ if command:
+ if arg:
+ result.append(f"{command}({arg})")
+ else:
+ result.append(command)
+ return result
+
+ def format(self, text):
+ pattern = r"(<(\w+)(?:\.(.+))?>)"
+ matches = re.findall(pattern, text)
+ result = []
+ last_end = 0
+
+ for match in matches:
+ full_match, key, transformations_str = match
+ if key in self.color_map:
+ result.append(text[last_end : text.find(full_match, last_end)])
+ value = self.color_map[key]
+ if transformations_str:
+ transformations = self.parse_transformations(transformations_str)
+ value = self.apply_transformations(value, transformations)
+ result.append(value)
+ last_end = text.find(full_match, last_end) + len(full_match)
+
+ result.append(text[last_end:])
+ result = "".join(result)
+ pattern = r"<\\\\([^>]+)>"
+
+ result = re.sub(pattern, r"<\1>", result)
+
+ return result
+
+
+def generate_templates(
+ folder: str,
+ output_folder: str,
+ scheme: DynamicScheme,
+ color_scheme: str,
+ wallpaper: str = "",
+):
+ if not os.path.exists(output_folder):
+ os.makedirs(output_folder)
+ if not os.path.exists(folder):
+ os.makedirs(folder)
+ file_list = get_file_list(folder)
+
+ for file_path in file_list:
+ with open(file_path) as f:
+ template = f.read()
+ formatter = ColorFormatter(scheme)
+ template = formatter.format(template)
+ template = (
+ template.replace("", color_scheme)
+ .replace("", output_folder)
+ .replace("", wallpaper)
+ )
+ new_path = join(output_folder, os.path.basename(file_path))
+ with open(new_path, "w") as f:
+ f.write(template)
+
+ for file in ready_templates:
+ _template = ""
+ for color in vars(MaterialDynamicColors).keys():
+ color_name = getattr(MaterialDynamicColors, color)
+ if hasattr(color_name, "get_hct"):
+ rgba = color_name.get_hct(scheme).to_rgba()
+ hex_color = rgb_to_hex(rgba)
+ rgb_color = rgba_to_rgb(rgba)
+ new_line = ready_templates[file].format(
+ name=color, hex=hex_color, rgb=rgb_color
+ )
+ _template += new_line
+ if color in additional:
+ new_line = ready_templates[file].format(
+ name=additional[color], hex=hex_color, rgb=rgb_color
+ )
+ _template += new_line
+
+ new_path = join(output_folder, os.path.basename(file))
+ with open(new_path, "w") as f:
+ f.write(_template)
+
+
+def run_hooks(folder: str):
+ if not os.path.exists(folder):
+ os.makedirs(folder)
+ file_list = get_file_list(folder)
+ for file_path in file_list:
+ file_name = os.path.basename(file_path)
+ if str(file_name).endswith(".py"):
+ subprocess.run(["python", "-O", file_path])
+ elif str(file_name).endswith(".sh"):
+ subprocess.run(["sh", file_path])
+
+
+def process_image(image_path, quality=2, num_colors=128):
+ def get_cache_path(image_path):
+ global cache_path
+ _cache_path = join(cache_path, "cached_colors")
+ hash_object = hashlib.md5(image_path.encode())
+ cache_filename = hash_object.hexdigest() + ".pkl"
+ os.makedirs(_cache_path, exist_ok=True)
+ return join(_cache_path, cache_filename)
+
+ def load_from_cache(cache_path):
+ if os.path.exists(cache_path):
+ with open(cache_path, "rb") as f:
+ return pickle.load(f)
+ return None
+
+ def save_to_cache(cache_path, data):
+ with open(cache_path, "wb") as f:
+ pickle.dump(data, f)
+
+ cache_path = get_cache_path(image_path)
+
+ cached_result = load_from_cache(cache_path)
+ if cached_result is not None:
+ return cached_result
+
+ image = Image.open(image_path).convert("RGB")
+
+ image_data = np.array(image)
+ pixel_array = image_data[::quality, ::quality].reshape(-1, 3)
+
+ result = QuantizeCelebi(pixel_array, num_colors)
+
+ color = Score.score(result)[0]
+
+ save_to_cache(cache_path, color)
+
+ return color
+
+
+def main(
+ color_scheme: str,
+ image_path: str,
+ use_color: int | None = None,
+ scheme_name: str | None = None,
+ contrast_level: int = 0,
+):
+ scheme_name = scheme_name or "tonalSpot"
+ scheme = schemes[scheme_name]
+ is_dark = True if color_scheme == "dark" else False
+ if use_color is None:
+ color = process_image(image_path, 4, 1024)
+
+ else:
+ color = use_color
+
+ scheme = scheme(Hct.from_int(color), is_dark, contrast_level)
+ # for color in vars(MaterialDynamicColors).keys():
+ # color_name = getattr(MaterialDynamicColors, color)
+ # if hasattr(color_name, "get_hct"):
+ # print(color, rgb_to_hex(color_name.get_hct(scheme).to_rgba()))
+
+ with open(join(cache_path, "colors.json"), "w") as f:
+ object = ColorsCache(scheme, image_path, color, contrast_level, scheme_name)
+ json.dump(colors_dict(object), f, indent=2)
+
+ generate_templates(
+ f"{script_dir}/templates", cache_path, scheme, color_scheme, image_path
+ )
+ generate_templates(
+ f"{script_dir}/templates/svg",
+ join(cache_path, "svg/"),
+ scheme,
+ color_scheme,
+ image_path,
+ )
+
+ if is_dark:
+ subprocess.run(["sh", join(script_dir, "gtk-material.sh")])
+ else:
+ subprocess.run(["sh", join(script_dir, "gtk-material.sh"), "--light"])
+
+ run_hooks(join(script_dir, "hooks"))
+
+
+def _argparse() -> tuple[bool, bool, str, str, str, str]:
+ parser = argparse.ArgumentParser()
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument("-R", help="Restore previous colorscheme.", action="store_true")
+ group.add_argument(
+ "-w", help="Use last used wallpaper for color generation.", action="store_true"
+ )
+ group.add_argument("--image", type=str, help="Image for color scheme generation")
+ group.add_argument(
+ "--color", type=str, help="Main color for color scheme generation"
+ )
+ parser.add_argument(
+ "--color-scheme",
+ type=str,
+ default="dark",
+ choices=["dark", "light"],
+ help="Color scheme variant",
+ )
+ parser.add_argument(
+ "--scheme",
+ type=str,
+ default="",
+ choices=list(schemes.keys()),
+ help="Scheme for color generation",
+ )
+
+ args = parser.parse_args()
+
+ restore_palette = args.R
+ use_last_used_wallpaper = args.w
+ image = args.image
+ color_scheme = args.color_scheme
+ use_color = args.color
+ scheme = args.scheme
+ return (
+ restore_palette,
+ use_last_used_wallpaper,
+ image,
+ color_scheme,
+ use_color,
+ scheme,
+ )
+
+
+def _main():
+ (
+ restore_palette,
+ use_last_used_wallpaper,
+ image,
+ color_scheme,
+ use_color,
+ scheme,
+ ) = _argparse()
+ if not scheme:
+ scheme = None
+ if use_color is not None:
+ try:
+ with open(join(cache_path, "colors.json")) as f:
+ content = get_cache_object(f.read())
+ main(
+ color_scheme,
+ image_path=content.wallpaper,
+ use_color=int(use_color.lstrip("#"), 16),
+ scheme_name=scheme,
+ )
+ except Exception:
+ main(
+ color_scheme,
+ image_path="/dev/null",
+ use_color=int(use_color.lstrip("#"), 16),
+ scheme_name=scheme,
+ )
+
+ elif restore_palette:
+ with open(join(cache_path, "colors.json")) as f:
+ content = get_cache_object(f.read())
+ main(
+ color_scheme,
+ image_path=content.wallpaper,
+ use_color=content.original_color,
+ scheme_name=scheme or content.scheme_name,
+ contrast_level=content.contrast_level,
+ )
+ elif use_last_used_wallpaper:
+ with open(join(cache_path, "colors.json")) as f:
+ content = get_cache_object(f.read())
+ main(
+ color_scheme,
+ image_path=content.wallpaper,
+ scheme_name=scheme or content.scheme_name,
+ contrast_level=content.contrast_level,
+ )
+ else:
+ if os.path.isdir(image):
+ files = [
+ f for f in os.listdir(image) if f.endswith((".png", ".jpg", ".jpeg"))
+ ]
+ if files:
+ image = join(image, random.choice(files))
+ main(color_scheme, image_path=image, scheme_name=scheme)
+
+
+if __name__ == "__main__":
+ _main()
diff --git a/config/material-colors/gtk-material.sh b/config/material-colors/gtk-material.sh
new file mode 100755
index 0000000..a197435
--- /dev/null
+++ b/config/material-colors/gtk-material.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+dark_icon="Tela-nord-dark"
+light_icon="Tela-nord-light"
+
+if [ "$1" == "--light" ]; then
+ gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3
+ gsettings set org.gnome.desktop.interface icon-theme "$light_icon"
+ gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
+else
+ gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3-dark
+ gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
+ gsettings set org.gnome.desktop.interface icon-theme "$dark_icon"
+fi
diff --git a/config/material-colors/hooks/discord.sh b/config/material-colors/hooks/discord.sh
new file mode 100755
index 0000000..2ec3a3b
--- /dev/null
+++ b/config/material-colors/hooks/discord.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+material_cache="$HOME"/.cache/material/
+
+sass $material_cache/material-discord.scss $material_cache/material-discord.css
diff --git a/config/material-colors/hooks/sddm.sh b/config/material-colors/hooks/sddm.sh
new file mode 100755
index 0000000..1528b6f
--- /dev/null
+++ b/config/material-colors/hooks/sddm.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+"$HOME"/dotfiles/sddm/scripts/wallpaper.sh 1>/dev/null
diff --git a/config/material-colors/hooks/telegram.sh b/config/material-colors/hooks/telegram.sh
new file mode 100755
index 0000000..dc001d7
--- /dev/null
+++ b/config/material-colors/hooks/telegram.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+cache_folder="$HOME"/.cache/material
+telegram_theme_cache="$HOME"/.cache/telegram-theme
+
+bg_color_file="$cache_folder/bg-color"
+bg_color=$(cat "$bg_color_file")
+magick -size 256x256 "xc:$bg_color" $telegram_theme_cache/tiled.png
+
+mkdir -p $telegram_theme_cache
+
+cp $cache_folder/colors.tdesktop-theme $telegram_theme_cache/colors.tdesktop-theme
+
+zip -q -j $telegram_theme_cache/pallete.tdesktop-theme $telegram_theme_cache/tiled.png $telegram_theme_cache/colors.tdesktop-theme
diff --git a/config/material-colors/templates/alacritty-dark.toml b/config/material-colors/templates/alacritty-dark.toml
new file mode 100644
index 0000000..3f3c701
--- /dev/null
+++ b/config/material-colors/templates/alacritty-dark.toml
@@ -0,0 +1,72 @@
+[colors.primary]
+background = ''
+foreground = ''
+
+
+[colors.cursor]
+text = '#1E1E2E'
+cursor = '#F5E0DC'
+
+[colors.vi_mode_cursor]
+text = '#1E1E2E'
+cursor = '#B4BEFE'
+
+
+[colors.search.matches]
+foreground = '#1E1E2E'
+background = '#A6ADC8'
+
+[colors.search.focused_match]
+foreground = '#1E1E2E'
+background = '#A6E3A1'
+
+[colors.footer_bar]
+foreground = '#1E1E2E'
+background = '#A6ADC8'
+
+
+[colors.hints.start]
+foreground = '#1E1E2E'
+background = '#F9E2AF'
+
+[colors.hints.end]
+foreground = '#1E1E2E'
+background = '#A6ADC8'
+
+
+[colors.selection]
+text = '#1E1E2E'
+background = '#F5E0DC'
+
+
+[colors.normal]
+black = '#45475A'
+red = '#F38BA8'
+green = '#A6E3A1'
+yellow = '#F9E2AF'
+blue = '#89B4FA'
+magenta = '#F5C2E7'
+cyan = '#94E2D5'
+white = '#BAC2DE'
+
+
+[colors.bright]
+black = '#585B70'
+red = '#F38BA8'
+green = '#A6E3A1'
+yellow = '#F9E2AF'
+blue = '#89B4FA'
+magenta = '#F5C2E7'
+cyan = '#94E2D5'
+white = '#A6ADC8'
+
+
+[colors.dim]
+black = '#45475A'
+red = '#F38BA8'
+green = '#A6E3A1'
+yellow = '#F9E2AF'
+blue = '#89B4FA'
+magenta = '#F5C2E7'
+cyan = '#94E2D5'
+white = '#BAC2DE'
diff --git a/config/material-colors/templates/alacritty-light.toml b/config/material-colors/templates/alacritty-light.toml
new file mode 100644
index 0000000..a86bdec
--- /dev/null
+++ b/config/material-colors/templates/alacritty-light.toml
@@ -0,0 +1,72 @@
+[colors.primary]
+background = ''
+foreground = ''
+
+
+[colors.cursor]
+text = '#EFF1F5'
+cursor = '#DC8A78'
+
+[colors.vi_mode_cursor]
+text = '#EFF1F5'
+cursor = '#7287FD'
+
+
+[colors.search.matches]
+foreground = '#EFF1F5'
+background = '#6C6F85'
+
+[colors.search.focused_match]
+foreground = '#EFF1F5'
+background = '#40A02B'
+
+[colors.footer_bar]
+foreground = '#EFF1F5'
+background = '#6C6F85'
+
+
+[colors.hints.start]
+foreground = '#EFF1F5'
+background = '#DF8E1D'
+
+[colors.hints.end]
+foreground = '#EFF1F5'
+background = '#6C6F85'
+
+
+[colors.selection]
+text = '#EFF1F5'
+background = '#DC8A78'
+
+
+[colors.normal]
+black = '#5C5F77'
+red = '#D20F39'
+green = '#40A02B'
+yellow = '#DF8E1D'
+blue = '#1E66F5'
+magenta = '#EA76CB'
+cyan = '#179299'
+white = '#ACB0BE'
+
+
+[colors.bright]
+black = '#6C6F85'
+red = '#D20F39'
+green = '#40A02B'
+yellow = '#DF8E1D'
+blue = '#1E66F5'
+magenta = '#EA76CB'
+cyan = '#179299'
+white = '#BCC0CC'
+
+
+[colors.dim]
+black = '#5C5F77'
+red = '#D20F39'
+green = '#40A02B'
+yellow = '#DF8E1D'
+blue = '#1E66F5'
+magenta = '#EA76CB'
+cyan = '#179299'
+white = '#ACB0BE'
diff --git a/config/material-colors/templates/alacritty.toml b/config/material-colors/templates/alacritty.toml
new file mode 100644
index 0000000..f62d701
--- /dev/null
+++ b/config/material-colors/templates/alacritty.toml
@@ -0,0 +1,10 @@
+[general]
+import = [
+ "/alacritty-.toml"
+]
+[font]
+normal = { family = "MesloLGS NF", style = "Regular" }
+bold = { family = "MesloLGS NF", style = "Bold" }
+italic = { family = "MesloLGS NF", style = "Italic" }
+bold_italic = { family = "MesloLGS NF", style = "Bold Italic" }
+size = 12.0
diff --git a/config/material-colors/templates/bg-color b/config/material-colors/templates/bg-color
new file mode 100644
index 0000000..af5dbef
--- /dev/null
+++ b/config/material-colors/templates/bg-color
@@ -0,0 +1 @@
+
diff --git a/config/material-colors/templates/colors-hyprland.conf b/config/material-colors/templates/colors-hyprland.conf
new file mode 100644
index 0000000..2766e30
--- /dev/null
+++ b/config/material-colors/templates/colors-hyprland.conf
@@ -0,0 +1,5 @@
+$background = rgb()
+$foreground = rgb()
+$border_color_active = rgb()
+$border_color_inactive = rgb()
+# <\\outline>
diff --git a/config/material-colors/templates/colors-kitty.conf b/config/material-colors/templates/colors-kitty.conf
new file mode 100644
index 0000000..eeebd86
--- /dev/null
+++ b/config/material-colors/templates/colors-kitty.conf
@@ -0,0 +1,27 @@
+foreground
+background
+cursor
+
+color0
+color8
+
+color1
+color9
+
+color2
+color10
+
+color3
+color11
+
+color4
+color12
+
+color5
+color13
+
+color6
+color14
+
+color7
+color15
\ No newline at end of file
diff --git a/config/material-colors/templates/colors-sddm-style.conf b/config/material-colors/templates/colors-sddm-style.conf
new file mode 100644
index 0000000..d9417aa
--- /dev/null
+++ b/config/material-colors/templates/colors-sddm-style.conf
@@ -0,0 +1,129 @@
+## Please see https://github.com/aczw/sddm-theme-corners/blob/main/CONFIG.md for
+## more information about these options. Happy configuring!
+
+[General]
+
+# BgSource: string. Path to an image, used as the wallpaper. Can be placed
+# in the `backgrounds/` folder for convenience (see below!)
+#
+# FontFamily: string. Name of the font family. You can find this with
+# something like `fontconfig`, for example.
+#
+# FontSize: number. This value is used for everything *except* the date/time.
+#
+# Padding: number. How far away things should be from the edge of your screen.
+#
+# Radius: number. Corner radius for UI. Set to 0 to disable rounded corners.
+#
+# Scale: number. Adjusts the size of UI elements. Can be anything, but I
+# would stick between 1 and 2 (e.g. 1.5).
+
+BgSource="backgrounds/CURRENTWALLPAPER"
+FontFamily="Atkinson Hyperlegible"
+FontSize=9
+Padding=50
+Radius=10
+Scale=1
+
+# UserPictureEnabled: boolean. By default the user picture is shown. Set to false
+# if you don't have/want a user picture, or you don't use the
+# user selection functionality.
+#
+# UserBorderWidth: number. Width of the border around your picture. Set to
+# 0 to remove.
+#
+# UserBorderColor: color. Border color around your picture. Useless if border
+# width is 0.
+#
+# UserColor: color. Background color of the default, blank avatar. Only
+# visible if you don't have your own picture.
+
+UserPictureEnabled=false
+UserBorderWidth=5
+UserBorderColor=""
+UserColor=""
+
+# InputColor: color. Background color of the input fields.
+#
+# InputTextColor: color. Color of text you enter in the fields.
+#
+# InputBorderWidth: number. Width of the border around the active field. Set
+# to 0 to remove.
+#
+# InputBorderColor: color. Border color of active field. Useless if border
+# width is 0.
+#
+# UserPlaceholderText: string. Placeholder text shown when user field is empty.
+#
+# PassPlaceholderText: string. Placeholder text shown when user field is empty.
+#
+# HidePassword: boolean. Whether to replace your entered password with dots.
+
+InputColor=""
+InputTextColor=""
+InputBorderWidth=4
+InputBorderColor=""
+UserPlaceholderText="user"
+PassPlaceholderText="password"
+HidePassword=true
+
+# LoginButtonTextColor: color. Text color on the login button.
+#
+# LoginButtonText: string. Text displayed on the button.
+#
+# LoginButtonColor: color. Background color of the button.
+
+LoginButtonTextColor=""
+LoginButtonText="Login"
+LoginButtonColor=""
+
+# PopupColor: color. Background color of popup window.
+#
+# PopupActiveColor: color. Color around the currently selected entry.
+#
+# PopupActiveTextColor: color. Text color of the currently selected entry.
+# Mainly provided for potential contrast issues.
+
+PopupColor=""
+PopupActiveColor=""
+PopupActiveTextColor=""
+
+# SessionButtonColor: color. Session button background color.
+#
+# SessionIconColor: color. Color of the icon inside the session button.
+#
+# PowerButtonColor: color. Power button background color.
+#
+# PowerIconColor: color. Color of the icon inside the power button.
+
+SessionButtonColor=""
+SessionIconColor=""
+PowerButtonColor=""
+PowerIconColor=""
+
+# DateTimeSpacing: number. Spacing between the date and time.
+#
+# Date/TimeColor: color. Date/time text color.
+#
+# Date/TimeSize: number. Font size for the date/time.
+#
+# Date/TimeIsBold: boolean. Whether date/time text should be bolded.
+#
+# Date/TimeOpacity: number. Date/time text opacity.
+#
+# Date/TimeFormat: string. Change the format of how the date and time is displayed.
+# Note that they use different formats.
+
+DateTimeSpacing=-20
+
+DateColor=""
+DateSize=36
+DateIsBold=false
+DateOpacity=1.0
+DateFormat="dddd, MMMM d"
+
+TimeColor=""
+TimeSize=48
+TimeIsBold=true
+TimeOpacity=1.0
+TimeFormat="hh:mm AP"
diff --git a/config/material-colors/templates/colors.tdesktop-theme b/config/material-colors/templates/colors.tdesktop-theme
new file mode 100644
index 0000000..1dc6a05
--- /dev/null
+++ b/config/material-colors/templates/colors.tdesktop-theme
@@ -0,0 +1,568 @@
+// vim:ft=cfg
+
+name: pywal;
+
+// Color presets //
+
+secondary: ;
+onSecondary: ;
+outline: ;
+shadow: ;
+
+BACKGROUND: ;
+BACKGROUND_LIT_LIGHT: ;
+BACKGROUND_LIGHT: ;
+BACKGROUND_EXTRA_LIGHT: ;
+ON_BACKGROUND: ;
+ON_BACKGROUND_DARKER: ;
+
+ACCENT: ;
+ON_ACCENT: ;
+ACCENT_LIGHT: ;
+ON_ACCENT_LIGHT: ;
+ACCENT_DARK: ;
+ON_ACCENT_DARK: ;
+
+ERROR: ;
+ERROR_RIPPLE: #ff9180;
+ON_ERROR: ;
+
+SUCCES: #66bb6a;
+SUCCES_LIGHT: #81c784;
+SUCCES_DARK: #388e3c;
+
+COLOR_PINK: #e016a0; // Just for testing purposes :)
+
+// basic
+windowBg: BACKGROUND; // Window backgrounds
+windowFg: ON_BACKGROUND; // Main text / chat text
+windowBgOver: BACKGROUND_LIGHT; // Search field background + buttons color in context menu
+windowBgRipple: BACKGROUND_EXTRA_LIGHT; // Inactive chat in chats list (press & hold)
+windowFgOver: windowFg; // black: fallback for over text color
+windowSubTextFg: ON_BACKGROUND_DARKER; // Chats list message preview text
+windowSubTextFgOver: ON_BACKGROUND_DARKER; // Mouse over chats list message preview text
+windowBoldFg: ON_BACKGROUND; // Bold font (titles in Settings, Left menu options)
+windowBoldFgOver: ACCENT_LIGHT; // Mouse over chats list chat name text (+ Left menu options on hover)
+windowBgActive: ACCENT; // Active button background (+ checkboxes background)
+windowFgActive: ON_ACCENT; // Active selected chats list text / button text + checkboxes' "ticks" color
+windowActiveTextFg: ACCENT_DARK; // Online status, links, recording cancel, etc
+windowShadowFg: BACKGROUND; // Window border shadows
+windowShadowFgFallback: BACKGROUND; // Notification border
+
+shadowFg: #00000018; // Internal border shadows
+slideFadeOutBg: #0000003c; // Slide animation (chat to profile) fade out filling
+slideFadeOutShadowFg: windowShadowFg; // Slide animation (chat to profile) fade out right section shadow
+
+imageBg: BACKGROUND; // Image background fallback (when photo size is less than minimum allowed)
+imageBgTransparent: ON_BACKGROUND; // Image background when displaying an image with opacity where no opacity is needed
+
+//widgets
+activeButtonBg: ACCENT; // Currently selected button background
+activeButtonBgOver: ACCENT_LIGHT; // Mouse over currently selected button background
+activeButtonBgRipple: ACCENT; // Primary button background color (and active chat) - Press & hold
+activeButtonFg: ON_ACCENT; // Currently selected button text
+activeButtonFgOver: ON_ACCENT_LIGHT; // Mouse over currently selected button text
+activeButtonSecondaryFg: ON_BACKGROUND; // Counter color on primary button
+activeButtonSecondaryFgOver: ON_BACKGROUND; // Counter color on primary button (hover)
+activeLineFg: ACCENT_LIGHT; // Active input field line color (normal)
+activeLineFgError: ERROR; // Active input field line color (error)
+
+lightButtonBg: BACKGROUND; // Secondary button background color (default)
+lightButtonBgOver: BACKGROUND_LIGHT; // Secondary button background color (hover)
+lightButtonBgRipple: BACKGROUND_EXTRA_LIGHT; // Secondary button background color (press & hold)
+lightButtonFg: ON_BACKGROUND; // Secondary button text color
+lightButtonFgOver: lightButtonFg; // Secondary button text color (hover)
+
+attentionButtonFg: ERROR; // Default attention button text (like confirm button on log out)
+attentionButtonFgOver: ON_ERROR; // Default attention button text with mouse over
+attentionButtonBgOver: ERROR; // Default attention button background with mouse over
+attentionButtonBgRipple: ERROR_RIPPLE; // Default attention button ripple effect
+
+outlineButtonBg: BACKGROUND; // Buttons background in profiles (shared media)
+outlineButtonBgOver: lightButtonBgOver; // Buttons background in profiles (hover)
+outlineButtonOutlineFg: windowBgActive; // Default left outlined button left outline border
+outlineButtonBgRipple: lightButtonBgRipple; // Default left outlined button ripple effect
+
+menuBg: BACKGROUND; // Default popup menu background
+menuBgOver: windowBgOver; // Default popup menu item background with mouse over
+menuBgRipple: windowBgRipple; // Default popup menu item ripple effect
+menuIconFg: ON_BACKGROUND; // Icons color (left menu button, scroll down, paperclip..)
+menuIconFgOver: ACCENT_DARK; // Icons color on hover (left menu button, scroll down, paperclip..)
+menuSubmenuArrowFg: #373737; // Default popup menu submenu arrow icon (like in message field context menu in case of RTL system language)
+menuFgDisabled: #727272; // Default popup menu item disabled text (like unavailable items in message field context menu)
+menuSeparatorFg: BACKGROUND; // Default popup menu separator (like in message field context menu)
+
+//
+
+scrollBarBg: ACCENT; // Scrollbar (chats list) current position
+scrollBarBgOver: ACCENT_DARK; // Mouse over scrollbar (chats list) current position
+scrollBg: #0000001a; // Scrollbar (chats list) background
+scrollBgOver: #0000002c; // Mouse over scrollbar (chats list) background
+
+smallCloseIconFg: ACCENT; // Notification close button (default)
+smallCloseIconFgOver: ACCENT_LIGHT; // Notification close button (hover)
+
+radialFg: ON_BACKGROUND; // Default radial loader line (like in Media Viewer when loading a photo)
+radialBg: #00000056; // Default radial loader background (like in Media Viewer when loading a photo)
+
+placeholderFg: ON_BACKGROUND_DARKER; // Inactive input box placeholder text
+placeholderFgActive: ON_BACKGROUND_DARKER; // Active input box placeholder text
+inputBorderFg: ACCENT; // Default input field bottom border (like in code input field when you log in and field is not focused)
+filterInputBorderFg: ACCENT_DARK; // Default rounded input field border (like in chats list search field when field is focused)
+filterInputInactiveBg: windowBgOver; // Default rounded input field background (like in chats list search field when field is inactive)
+checkboxFg: #b3b3b3; // Default unchecked checkbox rounded rectangle (and also emoji category icons)
+
+sliderBgInactive: #e1eaef; // Inactive media player button (prev/next song)
+sliderBgActive: windowBgActive; // Active media player button (prev/next song)
+
+tooltipBg: #eef2f5; // Tooltip background (hover on message sent time)
+tooltipFg: #5d6c80; // Tooltip text color
+tooltipBorderFg: #c9d1db; // Tooltip border color
+
+
+// custom title bar for Windows and macOS
+titleBg: BACKGROUND; // Title bar color
+titleBgActive: titleBg; // Title bar color when Telegram window is focused
+titleButtonBg: titleBg; // Title bar min/max/close buttons background (Windows only)
+titleShadow: #00000003; // One pixel line shadow at the bottom of custom window title
+titleButtonFg: BACKGROUND; // Title bar buttons(min/max/close) (Windows only)
+titleButtonBgOver: BACKGROUND_LIGHT; // Title bar min/max background (hover) (Windows only)
+titleButtonFgOver: ON_BACKGROUND; // Title bar min/max icons (Windows only)
+titleButtonBgActive: titleButtonBg; // Custom window title minimize/maximize/restore button background when window is active (Windows only)
+titleButtonFgActive: titleButtonFg; // Custom window title minimize/maximize/restore button icon when window is active (Windows only)
+titleButtonBgActiveOver: titleButtonBgOver; // Custom window title minimize/maximize/restore button background with mouse over when window is active (Windows only)
+titleButtonFgActiveOver: titleButtonFgOver; // Custom window title minimize/maximize/restore button icon with mouse over when window is active (Windows only)
+titleButtonCloseBg: titleButtonBg; // Custom window title close button background when window is inactive (Windows only)
+titleButtonCloseFg: titleButtonFg; // Custom window title close button icon when window is inactive (Windows only)
+titleButtonCloseBgOver: ERROR; // Close button background (hover)
+titleButtonCloseFgOver: ON_ERROR; // Close button icon color (hover)
+titleButtonCloseBgActive: titleButtonCloseBg; // Custom window title close button background when window is active (Windows only)
+titleButtonCloseFgActive: titleButtonCloseFg; // Custom window title close button icon when window is active (Windows only)
+titleButtonCloseBgActiveOver: titleButtonCloseBgOver; // Custom window title close button background with mouse over when window is active (Windows only)
+titleButtonCloseFgActiveOver: titleButtonCloseFgOver; // Custom window title close button icon with mouse over when window is active (Windows only)
+titleFgActive: #3e3c3e; // Active title bar text (Mac)
+titleFg: #acacac; // Inactive title bar text (Mac)
+
+// tray icon
+trayCounterBg: ON_ERROR; // Unread messages counter background in tray (not muted, default red)
+trayCounterBgMute: BACKGROUND; // Unread messages counter background in tray (muted, default gray)
+trayCounterFg: ON_BACKGROUND; // Unread messages counter text (number)
+trayCounterBgMacInvert: ON_BACKGROUND; // Tray icon counter background when tray icon is pressed or when dark theme of macOS is used (macOS only)
+trayCounterFgMacInvert: ON_BACKGROUND; // Tray icon counter text when tray icon is pressed or when dark theme of macOS is used (macOS only)
+
+// layers
+layerBg: #0000007f; // Box and main menu background layer fade (for example, current chat tint when forwarding message)
+
+cancelIconFg: menuIconFg; // Default for settings close icon and box search cancel icon
+cancelIconFgOver: menuIconFgOver; // Default for settings close icon and box search cancel icon with mouse over
+
+// boxes
+boxBg: BACKGROUND; // Popup windows background color
+boxTextFg: ON_BACKGROUND; // Popup windows text color
+boxTextFgGood: SUCCES; // Popup windows "good" text (e.g. "Username available")
+boxTextFgError: ERROR; // Popup windows "bad" text (e.g. "Username already taken")
+boxTitleFg: ACCENT; // Popup windows titles color (sessions, contacts...)
+boxSearchBg: boxBg; // Box search field background (like in contacts box)
+// boxSearchCancelIconFg: cancelIconFg; // (not implemented yet) Search cancel X button icon (like in contacts box)
+boxSearchCancelIconFgOver: cancelIconFgOver; // (not implemented yet) Search cancel X button icon with mouse over
+
+boxTitleAdditionalFg: ACCENT_LIGHT; // Box title additional text (like in create group box when you see chosen members count)
+boxTitleCloseFg: cancelIconFg; // Settings close icon and box search cancel icon (like in contacts box)
+boxTitleCloseFgOver: cancelIconFgOver; // Settings close icon and box search cancel icon (like in contacts box) with mouse over
+
+membersAboutLimitFg: windowSubTextFgOver; // Text in channel members box about the limit (max 200 last members are shown)
+
+contactsBg: BACKGROUND; // Contacts (and some other) list background color
+contactsBgOver: windowBgOver; // Contacts (and some other) list mouse over background
+contactsNameFg: ON_BACKGROUND; // Contacts (and some other) box row name text
+contactsStatusFg: ON_BACKGROUND_DARKER; // Contacts (and some other) box row additional text (like last seen stamp)
+contactsStatusFgOver: windowSubTextFgOver; // Contacts (and some other) box row additional text (like last seen stamp) with mouse over
+contactsStatusFgOnline: ACCENT_LIGHT; // Contacts (and some other) box row active additional text (like online status)
+
+photoCropFadeBg: layerBg; // "Out-of-bounds" area in photo cropping (avatars etc...)
+photoCropPointFg: ON_BACKGROUND; // Photo crop "corners" (which you drag to crop photo)
+
+callArrowFg: boxTextFgGood; // Received phone call arrow (in calls list box)
+callArrowMissedFg: boxTextFgError; // Missed phone call arrow (in calls list box)
+
+// intro
+introBg: BACKGROUND; // Login screen background
+introTitleFg: windowBoldFg; // Login title text
+introDescriptionFg: ON_BACKGROUND_DARKER; // Login description text
+introErrorFg: ERROR; // Login error text (like when providing a wrong log in code)
+
+introCoverTopBg: BACKGROUND; // Gradient finish at the top of the login screen
+introCoverBottomBg: BACKGROUND; // Gradient start at the bottom of the login screen
+introCoverIconsFg: ACCENT_DARK; // Icons and clouds colors
+introCoverPlaneTrace: 69; // Plane trace
+introCoverPlaneInner: ON_ACCENT; // Plane color inside
+introCoverPlaneOuter: ACCENT; // Plane color outside
+introCoverPlaneTop: ON_BACKGROUND; // Main plane color
+
+dialogsMenuIconFg: menuIconFg; // Main menu and lock telegram icon
+dialogsMenuIconFgOver: menuIconFgOver; // Main menu and lock telegram icon with mouse over
+
+dialogsBg: BACKGROUND; // Chats list background color
+dialogsNameFg: ON_BACKGROUND; // Chat list name text
+dialogsChatIconFg: dialogsNameFg; // Chat list group or channel icon
+dialogsDateFg: ON_BACKGROUND_DARKER; // Chats list date text
+dialogsTextFg: ON_BACKGROUND_DARKER; // Chats list message preview text
+dialogsTextFgService: ACCENT_LIGHT; // Chats list message preview sender name
+dialogsDraftFg: ACCENT; // "Draft" word
+dialogsVerifiedIconBg: windowBgActive; // Verification icon background
+dialogsVerifiedIconFg: ON_ACCENT; // Verification icon check color
+dialogsSendingIconFg: #c1c1c1; // Chat list sending message icon (clock)
+dialogsSentIconFg: ACCENT; // Chat list sent message tick / double tick icon
+dialogsUnreadBg: ACCENT; // Chats list unread counter background
+dialogsUnreadBgMuted: ACCENT_DARK; // Chat list unread badge background for muted chat
+dialogsUnreadFg: ON_ACCENT; // Unread counter text color
+dialogsOnlineBadgeFg: ACCENT_LIGHT; // Chat list online status (for inactive item)
+
+dialogsBgOver: BACKGROUND_LIGHT; // Inactive chat color on hover
+dialogsNameFgOver: ACCENT_LIGHT; // Chat list name text with mouse over
+dialogsChatIconFgOver: dialogsNameFgOver; // Chat list group or channel icon with mouse over
+dialogsDateFgOver: windowSubTextFgOver; // Chat list date text with mouse over
+dialogsTextFgOver: windowSubTextFgOver; // Chat list message text with mouse over
+dialogsTextFgServiceOver: dialogsTextFgService; // Mouse over chats list message preview sender name
+dialogsDraftFgOver: dialogsDraftFg; // Chat list draft label with mouse over
+dialogsVerifiedIconBgOver: dialogsVerifiedIconBg; // Chat list verified icon background with mouse over
+dialogsVerifiedIconFgOver: dialogsVerifiedIconFg; // Chat list verified icon check with mouse over
+dialogsSendingIconFgOver: dialogsSendingIconFg; // Chat list sending message icon (clock) with mouse over
+dialogsSentIconFgOver: dialogsSentIconFg; // Chat list sent message tick / double tick icon with mouse over
+dialogsUnreadBgOver: dialogsUnreadBg; // Chat list unread badge background for NOT muted chat with mouse over
+dialogsUnreadBgMutedOver: dialogsUnreadBgMuted; // Chat list unread badge background for muted chat with mouse over
+dialogsUnreadFgOver: dialogsUnreadFg; // Chat list unread badge text with mouse over
+
+dialogsBgActive: ACCENT; // Active chat color (in chats list)
+dialogsNameFgActive: ON_ACCENT; // Active chat name text (in chats list)
+dialogsChatIconFgActive: dialogsNameFgActive; // Active chat group or channel icon (in chats list)
+dialogsDateFgActive: ON_ACCENT; // Active chat date color
+dialogsTextFgActive: ON_ACCENT; // Active chat message preview color
+dialogsTextFgServiceActive: dialogsTextFgActive;// Active chat service messages color
+dialogsDraftFgActive: ON_ACCENT_LIGHT; // "Draft" word when chat is selected
+dialogsVerifiedIconBgActive: dialogsTextFgActive; // Active chat verified icon background (in chats list)
+dialogsVerifiedIconFgActive: dialogsBgActive; // Active chat verified icon check (in chats list)
+dialogsSendingIconFgActive: ON_ACCENT_LIGHT; // Active chat sending message icon (clock) (in chats list)
+dialogsSentIconFgActive: dialogsTextFgActive; // Active chat sent message tick / double tick icon (in chats list)
+dialogsUnreadBgActive: dialogsTextFgActive; // Active chat unread badge background for NOT muted chat (in chats list)
+dialogsUnreadBgMutedActive: dialogsDraftFgActive; // Active chat unread badge background for muted chat (in chats list)
+dialogsUnreadFgActive: dialogsBgActive; // Active chat unread badge text (in chats list)
+
+dialogsRippleBg: windowBgRipple;
+dialogsRippleBgActive: activeButtonBgRipple;
+
+dialogsForwardBg: dialogsBgActive; // Forwarding panel background (when forwarding messages in the smallest window size)
+dialogsForwardFg: dialogsNameFgActive; // Forwarding panel text (when forwarding messages in the smallest window size)
+
+searchedBarBg: BACKGROUND; // Search results window background color
+searchedBarFg: ACCENT_LIGHT; // Search results text color
+
+// history
+topBarBg: BACKGROUND; // Chat header background
+
+emojiPanBg: BACKGROUND; // Sticker panel background
+emojiPanCategories: BACKGROUND; // Sticker panel bottom bar background
+emojiPanHeaderFg: ACCENT; // Sticker panel title text
+emojiPanHeaderBg: BACKGROUND; // Sticker panel top bar background
+stickerPanDeleteBg: #000000cc; // Delete X button background for custom sent stickers in stickers panel (legacy)
+stickerPanDeleteFg: ON_BACKGROUND; // Delete X button icon for custom sent stickers in stickers panel (legacy)
+stickerPreviewBg: #2f2f2fCC; // Sticker and GIF preview background (when you press and hold on a sticker)
+
+historyTextInFg: ON_BACKGROUND; // Incoming message text color
+historyTextInFgSelected: ON_ACCENT; // Selected incoming message text or text in a selected message
+historyTextOutFg: ON_BACKGROUND; // Outgoing message text color
+historyTextOutFgSelected: ON_ACCENT; // Outgoing message selected text or text in a selected message
+historyLinkInFg: ACCENT_LIGHT; // Incoming message link color
+historyLinkInFgSelected: historyLinkInFg; // Incoming message link in a selected text or message
+historyLinkOutFg: ACCENT_LIGHT; // Outgoing message link color
+historyLinkOutFgSelected: historyLinkOutFg; // Outgoing message link in a selected text or message
+historyFileNameInFg: historyTextInFg; // Incoming message filename text color
+historyFileNameInFgSelected: historyFileNameInFg; // Incoming media filename text in a selected message
+historyFileNameOutFg: historyTextOutFg; // Outgoing message filename text color
+historyFileNameOutFgSelected: historyFileNameOutFg; // Outgoing media filename text in a selected message
+historyOutIconFg: dialogsSentIconFg; // "Eye" and "Checks" color for outgoing messages (selected)
+historyOutIconFgSelected: ACCENT_DARK; // "Eye" and "Checks" color for outgoing messages (selected)
+historyIconFgInverted: ON_ACCENT; // "Checks" on stickers (outgoing)
+historySendingOutIconFg: ACCENT_LIGHT; // "Clock" icon while sending file (outgoing)
+historySendingInIconFg: ACCENT_LIGHT; // "Clock" icon while sending file (incoming)
+historySendingInvertedIconFg: ACCENT_LIGHT; // Media sending message icon (clock) (like in sent photo)
+historyCallArrowInFg: callArrowFg; // Received phone call arrow
+historyCallArrowInFgSelected: callArrowFg; // Received phone call arrow in a selected message
+historyCallArrowMissedInFg: callArrowMissedFg; // Missed phone call arrow
+historyCallArrowMissedInFgSelected: callArrowMissedFg; // Missed phone call arrow in a selected message
+historyCallArrowOutFg: historyCallArrowInFg; // Outgoing phone call arrow
+historyCallArrowOutFgSelected: historyCallArrowInFgSelected; // Outgoing phone call arrow
+
+historyUnreadBarBg: #424444; // Unread messages bar background color
+historyUnreadBarBorder: BACKGROUND; // Unread messages bar border color
+historyUnreadBarFg: #ededed; // Unread messages bar text color
+
+historyForwardChooseBg: #0000004c; // "Choose recipient" BACKGROUND color (forwarding)
+historyForwardChooseFg: BACKGROUND; // "Choose recipient" text color (forwarding)
+
+historyPeer1NameFg: #E53935; // Group chat sender name - Red
+historyPeer1NameFgSelected: historyPeer1NameFg; // Red group member name in a selected message
+historyPeer1UserpicBg: #EF9A9A; // Group chat userpic background - Red
+
+historyPeer2NameFg: #7CB342; // Sender name - Green
+historyPeer2NameFgSelected: historyPeer2NameFg; // Green group member name in a selected message
+historyPeer2UserpicBg: #C5E1A5; // Userpic background - Green
+
+historyPeer3NameFg: #FDD835; // Sender name - Yellow
+historyPeer3NameFgSelected: historyPeer3NameFg; // Yellow group member name in a selected message
+historyPeer3UserpicBg: #FFF59D; // Userpic background - Yellow
+
+historyPeer4NameFg: #C0CA33; // Sender name - Light green
+historyPeer4NameFgSelected: historyPeer4NameFg; // Blue group member name in a selected message
+historyPeer4UserpicBg: #81D4FA; // Userpic background - Blue
+
+historyPeer5NameFg: #7E57C2; // Sender name - Purple
+historyPeer5NameFgSelected: historyPeer5NameFg; // Purple group member name in a selected message
+historyPeer5UserpicBg: #B39DDB; // Userpic background - Light Purple
+
+historyPeer6NameFg: #D81B60; // Sender name - "Raspberry"
+historyPeer6NameFgSelected: historyPeer6NameFg; // "Raspberry" group member name in a selected message
+historyPeer6UserpicBg: #F48FB1; // Userpic background - Light "Raspberry"
+
+historyPeer7NameFg: #00ACC1; // Sender name - Cyan
+historyPeer7NameFgSelected: historyPeer7NameFg; // Cyan group member name in a selected message
+historyPeer7UserpicBg: #80DEEA; // Userpic background - Cyan
+
+historyPeer8NameFg: #FB8C00; // Sender name - Orange
+historyPeer8NameFgSelected: historyPeer8NameFg; // Orange group member name in a selected message
+historyPeer8UserpicBg: #FFE082; // Userpic background - Light Orange
+
+historyPeerUserpicFg: ON_BACKGROUND; // Default userpic initials
+
+// Some values are marked as (adjusted), it means they're adjusted by
+// hue and saturation of the average background color if user chooses
+// some other (not bundled to this color theme) background. If the
+// bundled background is used those colors are not adjusted in any way.
+historyScrollBarBg: ACCENT; // Scrollbar (history view) background (adjusted)
+historyScrollBarBgOver: ACCENT_LIGHT; // Scrollbar (history view) background (hover) (adjusted)
+historyScrollBg: BACKGROUND; // Scrollbar (history view) current position background (adjusted)
+historyScrollBgOver: BACKGROUND_LIGHT; // Scrollbar (history view) current position background (hover) (adjusted)
+
+msgInBg: BACKGROUND_LIGHT; // Incoming message background
+msgInBgSelected: ACCENT; // Selected incoming message background
+msgOutBg: BACKGROUND_EXTRA_LIGHT; // Outgoing message background
+msgOutBgSelected: ACCENT; // Selected outgoing message background
+msgSelectOverlay: 50; // Selected media (images...) overlay
+msgStickerOverlay: 50; // Selected sticker overlay
+msgInServiceFg: ACCENT; // Incoming reply quoted name
+msgInServiceFgSelected: ON_ACCENT; // Selected incoming reply quoted name
+msgOutServiceFg: ACCENT; // Outgoing reply quoted name
+msgOutServiceFgSelected: ON_ACCENT; // Selected outgoing reply quoted name
+msgInShadow: BACKGROUND_LIT_LIGHT; // Incoming message box shadow
+msgInShadowSelected: BACKGROUND_LIT_LIGHT; // Selected incoming message box shadow
+msgOutShadow: BACKGROUND_LIT_LIGHT; // Outgoing message box shadow
+msgOutShadowSelected: BACKGROUND_LIT_LIGHT; // Selected outgoing message box shadow
+msgInDateFg: ON_BACKGROUND_DARKER; // Incoming message date text
+msgInDateFgSelected: ON_ACCENT; // Incoming selected message date text
+msgOutDateFg: ON_BACKGROUND; // Outgoing message date text
+msgOutDateFgSelected: ON_ACCENT; // Outgoing selected message date text
+msgServiceFg: ON_ACCENT; // Service messages text color (join, left etc)
+msgServiceBg: ACCENT; // Service messages BACKGROUND color (join, left etc) (adjusted)
+msgServiceBgSelected: ACCENT; // Service message selected text background (like in a service message about group title being changed) (adjusted)
+msgInReplyBarColor: ACCENT; // Incoming msg: vertical bar next to reply
+msgInReplyBarSelColor: ACCENT; // Incoming msg: vertical bar next to reply (selected)
+msgOutReplyBarColor: ACCENT; // Outgoing msg: vertical bar next to reply
+msgOutReplyBarSelColor: ACCENT; // Outgoing msg: vertical bar next to reply (selected)
+msgImgReplyBarColor: msgServiceFg; // Sticker message reply outline
+msgInMonoFg: ACCENT_LIGHT; // Monowidth font / incoming msg
+msgOutMonoFg: ACCENT_LIGHT; // Monowidth font / outgoing msg
+msgInMonoFgSelected: msgInMonoFg; // Incoming message monospace text in a selected text or message
+msgOutMonoFgSelected: msgOutMonoFg; // Outgoing message monospace text in a selected text or message
+msgDateImgFg: msgServiceFg; // Media message time text (like time text in a sent photo)
+msgDateImgBg: ACCENT; // Media message time bubble background (like time bubble in a sent photo) or file with thumbnail download icon circle background
+msgDateImgBgOver: ON_ACCENT; // Media message download icon circle background with mouse over (like file with thumbnail download icon)
+msgDateImgBgSelected: ACCENT; // Selected media message time bubble background
+
+msgFileThumbLinkInFg: lightButtonFg; // Incoming media file message with thumbnail download / open with button text
+msgFileThumbLinkInFgSelected: lightButtonFgOver; // Incoming selected media file message with thumbnail download / open with button text
+msgFileThumbLinkOutFg: ACCENT; // Outgoing media file message with thumbnail download / open with button text
+msgFileThumbLinkOutFgSelected: ACCENT_LIGHT; // Outgoing selected media file message with thumbnail download / open with button text
+msgFileInBg: windowBgActive; // Incoming audio file download circle background
+msgFileInBgOver: ACCENT_LIGHT; // Incoming audio file download circle background with mouse over
+msgFileInBgSelected: ACCENT_LIGHT; // Incoming selected audio file download circle background
+msgFileOutBg: ACCENT; // Outgoing audio file download circle background
+msgFileOutBgOver: ACCENT_DARK; // Outgoing audio file download circle background with mouse over
+msgFileOutBgSelected: ACCENT; // Outgoing selected audio file download circle background
+
+msgFile1Bg: #72b1df; // Blue shared links / files without image square thumbnail
+msgFile1BgDark: #5c9ece; // Blue shared files without image download circle background
+msgFile1BgOver: #5294c4; // Blue shared files without image download circle background with mouse over
+msgFile1BgSelected: #5099d0; // Blue shared files without image download circle background if file is selected
+msgFile2Bg: #61b96e; // Green shared links / shared files without image square thumbnail
+msgFile2BgDark: #4da859; // Green shared files without image download circle background
+msgFile2BgOver: #44a050; // Green shared files without image download circle background with mouse over
+msgFile2BgSelected: #46a07e; // Green shared files without image download circle background if file is selected
+msgFile3Bg: #e47272; // Red shared links / shared files without image square thumbnail
+msgFile3BgDark: #cd5b5e; // Red shared files without image download circle background
+msgFile3BgOver: #c35154; // Red shared files without image download circle background with mouse over
+msgFile3BgSelected: #9f6a82; // Red shared files without image download circle background if file is selected
+msgFile4Bg: #efc274; // Yellow shared links / shared files without image square thumbnail
+msgFile4BgDark: #e6a561; // Yellow shared files without image download circle background
+msgFile4BgOver: #dc9c5a; // Yellow shared files without image download circle background with mouse over
+msgFile4BgSelected: #b19d84; // Yellow shared files without image download circle background if file is selected
+
+historyFileInIconFg: ON_ACCENT; // Incoming file without thumbnail (like audio file) download arrow icon
+historyFileInIconFgSelected: ON_ACCENT; // Incoming selected file without thumbnail (like audio file) download arrow icon
+historyFileInRadialFg: ON_ACCENT; // Incoming file without thumbnail (like audio file) radial download animation line
+historyFileInRadialFgSelected: ON_ACCENT; // Incoming selected file without thumbnail (like audio file) radial download animation line
+historyFileOutIconFg: ON_ACCENT; // Outgoing file without thumbnail (like audio file) download arrow icon
+historyFileOutIconFgSelected: ON_ACCENT; // Outgoing selected file without thumbnail (like audio file) download arrow icon
+historyFileOutRadialFg: ON_ACCENT; // Outgoing file without thumbnail (like audio file) radial download animation line
+historyFileOutRadialFgSelected: ON_ACCENT; // Outgoing selected file without thumbnail (like audio file) radial download animation line
+historyFileThumbIconFg: ON_ACCENT; // File with thumbnail (or photo / video) download arrow icon
+historyFileThumbIconFgSelected: ON_ACCENT; // Selected file with thumbnail (or photo / video) download arrow icon
+historyFileThumbRadialFg: ON_ACCENT; // File with thumbnail (or photo / video) radial download animation line
+historyFileThumbRadialFgSelected: ON_ACCENT; // Selected file with thumbnail (or photo / video) radial download animation line
+
+historyVideoMessageProgressFg: historyFileThumbIconFg; // Radial playback progress in round video messages
+msgWaveformInActive: windowBgActive; // Incoming Voice "heard" part
+msgWaveformInActiveSelected: ACCENT_LIGHT; // Selected incoming Voice "heard" part
+msgWaveformInInactive: #d4dee6; // Incoming Voice "unheard" part
+msgWaveformInInactiveSelected: ON_BACKGROUND; // Selected incoming Voice "unheard" part
+msgWaveformOutActive: windowBgActive; // Outgoing Voice "heard" part
+msgWaveformOutActiveSelected: ACCENT_LIGHT; // Selected outgoing Voice "heard" part
+msgWaveformOutInactive: ON_BACKGROUND; // Outgoing Voice "unheard" part
+msgWaveformOutInactiveSelected: ON_BACKGROUND; // Selected outgoing Voice "unheard" part
+
+msgBotKbOverBgAdd: ACCENT_DARK; // Inline button (hover)
+msgBotKbIconFg: ON_ACCENT; // Inline button icon color (URL Buttons, for example)
+msgBotKbRippleBg: #00000020; // Inline button (press & hold)
+
+mediaInFg: msgInDateFg; // Incoming media message status text (like in file that is being downloaded)
+mediaInFgSelected: msgInDateFgSelected; // Incoming selected media message status text (like in file that is being downloaded)
+mediaOutFg: msgOutDateFg; // Outgoing media message status text (like in file that is being downloaded)
+mediaOutFgSelected: msgOutDateFgSelected; // Outgoing selected media message status text (like in file that is being downloaded)
+
+youtubePlayIconBg: #ef5350ee; // Youtube play icon background (when a link to a youtube video with a webpage preview is sent)
+youtubePlayIconFg: #ffcdd2; // Youtube play icon arrow (when a link to a youtube video with a webpage preview is sent)
+videoPlayIconBg: #0000007f; // Other video play icon background (like when a link to a vimeo video with a webpage preview is sent)
+videoPlayIconFg: ON_BACKGROUND; // Other video play icon arrow (like when a link to a vimeo video with a webpage preview is sent)
+toastBg: #000000b2; // Toast notification background (like when you click on your t.me link when editing your username)
+toastFg: ON_BACKGROUND; // Toast notification text (like when you click on your t.me link when editing your username)
+
+reportSpamBg: emojiPanHeaderBg; // Report spam panel background (like a non contact user writes your for the first time)
+reportSpamFg: ON_BACKGROUND_DARKER; // Report spam panel text (when you send a report from that panel)
+
+historyToDownBg: BACKGROUND; // "Scroll to bottom" button background
+historyToDownBgOver: windowBgOver; // "Scroll to bottom" button background (hover)
+historyToDownBgRipple: windowBgRipple; // "Scroll to bottom" button background (press & hold)
+historyToDownFg: menuIconFg; // "Scroll to bottom" internal icon color
+historyToDownFgOver: menuIconFgOver; // "Scroll to bottom" internal icon color (hover)
+historyToDownShadow: #00000040; // "Scroll to bottom" button shadow
+
+historyComposeAreaBg: BACKGROUND; // Text input field background
+historyComposeAreaFg: ON_BACKGROUND; // Text color in "Type your message" field
+historyComposeAreaFgService: msgInDateFg; // Text color in "Type your message" field when replying to a media message
+historyComposeIconFg: menuIconFg; // Text input field: Paperclip, Smile, Bot command icons
+historyComposeIconFgOver: ACCENT_DARK; // Text input field: Paperclip, Smile, Bot command icons (hover)
+historySendIconFg: ACCENT_DARK; // Text input field: Send icon
+historySendIconFgOver: ACCENT; // Text input field: Send icon (hover)
+historyPinnedBg: historyComposeAreaBg; // Pinned message area background
+historyReplyBg: historyComposeAreaBg; // Reply / forward / edit message area background
+historyReplyIconFg: windowBgActive; // Reply / forward / edit message left icon
+historyReplyCancelFg: cancelIconFg; // Reply / forward / edit message cancel button
+historyReplyCancelFgOver: cancelIconFgOver; // Reply / forward / edit message cancel button with mouse over
+
+historyComposeButtonBg: historyComposeAreaBg; // Unblock / join channel / mute channel button background
+historyComposeButtonBgOver: windowBgOver; // Unblock / join channel / mute channel button background with mouse over
+historyComposeButtonBgRipple: windowBgRipple; // Unblock / join channel / mute channel button ripple effect
+
+// overview
+overviewCheckBg: #00000040; // Shared files / links checkbox background for not selected rows when some rows are selected
+overviewCheckFg: BACKGROUND; // Shared files / links checkbox icon for not selected rows when some rows are selected
+overviewCheckFgActive: BACKGROUND; // Shared files / links checkbox icon for selected rows
+overviewPhotoSelectOverlay: #40ace333; // Shared photos / videos / links fill for selected rows
+
+// profile
+profileStatusFgOver: COLOR_PINK; // Group members list in group profile user last seen text with mouse over
+profileVerifiedCheckBg: windowBgActive; // Profile verified check icon background
+profileVerifiedCheckFg: windowFgActive; // Profile verified check icon tick
+profileAdminStartFg: ACCENT_LIGHT; // Star color for group/channhel admins and moderators (look in members list)
+
+// settings
+notificationsBoxMonitorFg: ON_BACKGROUND_DARKER;// Custom notifications settings box monitor color
+notificationsBoxScreenBg: dialogsBgActive; // Custom notifications settings box monitor screen background
+
+notificationSampleUserpicFg: windowBgActive; // Custom notifications settings box small sample userpic placeholder
+notificationSampleCloseFg: #d7d7d7; // Custom notifications settings box small sample close button placeholder
+notificationSampleTextFg: #d7d7d7; // Custom notifications settings box small sample text placeholder
+notificationSampleNameFg: #939393; // Custom notifications settings box small sample name placeholder
+
+changePhoneSimcardFrom: notificationSampleTextFg; // Change phone number box left simcard icon
+changePhoneSimcardTo: notificationSampleNameFg; // Change phone number box right simcard and plane icons
+
+mainMenuBg: BACKGROUND; // Left menu background (lower part, not buttons)
+mainMenuCoverBg: dialogsBgActive; // Left menu background (upper part)
+mainMenuCoverFg: ON_BACKGROUND; // Main menu top cover text
+mainMenuCloudFg: activeButtonFg; // "Cloud" icon in main menu
+mainMenuCloudBg: activeButtonBgRipple; // "Cloud" icon background in main menu
+
+mediaPlayerBg: BACKGROUND; // Music player background
+mediaPlayerActiveFg: ACCENT; // Clickable Next song/Prev song button in music player + played part color
+mediaPlayerInactiveFg: #4f5151; // "Disabled" Next song/Prev song button in music player + not player part color
+mediaPlayerDisabledFg: ACCENT_DARK; // Music player audio loading progress (when you're playing an audio file and switch to the previous one which is not loaded yet)
+
+// mediaview
+mediaviewFileBg: BACKGROUND; // File rectangle background (when you view a png file in Media Viewer and go to a previous, not loaded yet, file)
+mediaviewFileNameFg: ON_BACKGROUND_DARKER; // File name in file rectangle
+mediaviewFileSizeFg: ON_BACKGROUND_DARKER; // File size text in file rectangle
+mediaviewFileRedCornerFg: #d55959; // Red file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .pdf)
+mediaviewFileYellowCornerFg: #e8a659; // Yellow file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .zip)
+mediaviewFileGreenCornerFg: #49a957; // Green file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .exe)
+mediaviewFileBlueCornerFg: #599dcf; // Blue file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .dmg)
+mediaviewFileExtFg: activeButtonFg; // File extension text in file thumbnail placeholder in file rectangle
+
+mediaviewMenuBg: BACKGROUND; // Context menu in Media Viewer background
+mediaviewMenuBgOver: BACKGROUND_LIGHT; // Menu items background (hover)
+mediaviewMenuBgRipple: BACKGROUND_EXTRA_LIGHT; // Menu items background (press & hold)
+mediaviewMenuFg: ON_BACKGROUND; // Text color in media view menu
+
+mediaviewBg: #222222eb; // Media Viewer background
+mediaviewVideoBg: imageBg; // Media Viewer background when viewing a video in full screen
+mediaviewControlBg: #0000003c; // Controls background (like next photo / previous photo)
+mediaviewControlFg: ON_BACKGROUND; // Controls icon (like next photo / previous photo)
+mediaviewCaptionBg: #11111180; // Caption text background (when viewing photo with caption)
+mediaviewCaptionFg: mediaviewControlFg; // Caption text color
+mediaviewTextLinkFg: #91d9ff; // Links color in captions
+mediaviewSaveMsgBg: toastBg; // 'Something was saved to % folder' message background
+mediaviewSaveMsgFg: toastFg; // 'Something was saved to % folder' message text color
+
+mediaviewPlaybackActive: #c7c7c7; // Video playback progress already played part
+mediaviewPlaybackInactive: #252525; // Video playback progress upcoming (not played yet) part
+mediaviewPlaybackActiveOver: ON_BACKGROUND; // Video playback progress already played part with mouse over
+mediaviewPlaybackInactiveOver: #474747; // Video playback progress upcoming (not played yet) part with mouse over
+mediaviewPlaybackProgressFg: ON_BACKGROUND; // Video playback progress text
+mediaviewPlaybackIconFg: mediaviewPlaybackActive; // Video playback controls icon
+mediaviewPlaybackIconFgOver: mediaviewPlaybackActiveOver; // Video playback controls icon with mouse over
+mediaviewTransparentBg: ON_BACKGROUND; // Transparent filling part (when viewing a transparent .png file in Media Viewer)
+mediaviewTransparentFg: #cccccc; // Another transparent filling part
+
+// notification
+notificationBg: BACKGROUND; // Notification background
+
+// calls
+callBg: #26282cf2; // Phone call popup background
+callNameFg: #ffffff; // Phone call popup name text
+callFingerprintBg: #00000066; // Phone call popup emoji fingerprint background
+callStatusFg: #aaabac; // Phone call popup status text
+callIconFg: #ffffff; // Phone call popup answer, hangup and mute mic icon
+callAnswerBg: #64c15b; // Phone call popup answer button background
+callAnswerRipple: #52b149; // Phone call popup answer button ripple effect
+callAnswerBgOuter: #50eb4126; // Phone call popup answer button outer ripple effect
+callHangupBg: #d75a5a; // Phone call popup hangup button background
+callHangupRipple: #c04646; // Phone call popup hangup button ripple effect
+callCancelBg: #ffffff; // Phone call popup line busy cancel button background
+callCancelFg: #777777; // Phone call popup line busy cancel button icon
+callCancelRipple: #f1f1f1; // Phone call popup line busy cancel button ripple effect
+callMuteRipple: #ffffff12; // Phone call popup mute mic ripple effect
+
+callBarBg: dialogsBgActive; // Active phone call bar background
+callBarMuteRipple: dialogsRippleBgActive; // Active phone call bar mute and hangup button ripple effect
+callBarBgMuted: dialogsUnreadBgMuted; // Phone call bar with muted mic background
+callBarUnmuteRipple: shadowFg; // Phone call bar with muted mic mute and hangup button ripple effect
+callBarFg: dialogsNameFgActive; // Phone call bar text and icons
diff --git a/config/material-colors/templates/hyprlock.conf b/config/material-colors/templates/hyprlock.conf
new file mode 100644
index 0000000..12e97a0
--- /dev/null
+++ b/config/material-colors/templates/hyprlock.conf
@@ -0,0 +1,145 @@
+# Configuration
+ # (general settings)
+ general {
+ grace = 2
+ hide_cursor = true
+ ignore_empty_input = true
+ text_trim = true
+ }
+ # (background config)
+ background {
+ monitor =
+ path = ~/.cache/current_wallpaper.png # only png supported for now
+ color = rgba(, 1.0)
+ blur_passes = 3 # 0 disables blurring
+ blur_size = 1
+ noise = 0.01
+ contrast = 0.8916
+ brightness = 0.7
+ vibrancy = 0.1696
+ vibrancy_darkness = 0.0
+ }
+#
+
+# Password input
+ input-field {
+ monitor =
+ size = 225, 50
+ outline_thickness = 0
+ dots_size = 0.33
+ dots_spacing = 0.45
+ dots_center = true
+ dots_rounding = -1
+ outer_color = rgba(0,0,0,0)
+ inner_color = rgba(0,0,0,0)
+ font_color = rgba(, 1.0)
+ fade_on_empty = false
+ fade_timeout = 1000
+ font_family = Product Sans
+ placeholder_text =
+ hide_input = false
+ rounding = 4
+ check_color = rgba(0,0,0,0)
+ fail_color = rgba(0,0,0,0)
+ fail_text = $FAIL ($ATTEMPTS)
+ fail_transition = 200
+ capslock_color = -1
+ numlock_color = -1
+ bothlock_color = -1
+ invert_numlock = false
+ swap_font_color = false
+ position = 0, 150
+ halign = center
+ valign = bottom
+ }
+#
+
+
+# Time
+ # (hours)
+ label {
+ monitor =
+ text = cmd[update:1000] echo -e "$(date +"%H")"
+ color = rgba(, 1.0)
+ shadow_pass = 2
+ shadow_size = 3
+ shadow_color = rgb(0,0,0)
+ shadow_boost = 1.2
+ font_size = 150
+ font_family = Product Sans Light
+ position = 0, 90
+ halign = center
+ valign = center
+ }
+ # (minutes)
+ label {
+ monitor =
+ text = cmd[update:1000] echo -e "$(date +"%M")"
+ color = rgba(, 1.0)
+ font_size = 150
+ font_family = Product Sans Light
+ position = 0, -90
+ halign = center
+ valign = center
+ }
+#
+
+# Date
+ # (label)
+ label {
+ monitor =
+ text = cmd[update:1000] echo -e "$(date +"%A, %B %d")"
+ color = rgba(, 1.0)
+ font_size = 15
+ font_family = Product Sans Medium
+ position = 100, -75
+ shadow_passes = 5
+ shadow_size = 10
+ halign = left
+ valign = top
+ }
+ # (icon)
+ label {
+ monitor =
+ text = calendar_today
+ color = rgba(, 1.0)
+ font_size = 15
+ font_family = Material Symbols Outlined
+ position = 75, -75
+ shadow_passes = 5
+ shadow_size = 10
+ halign = left
+ valign = top
+ }
+#
+
+# Input layout
+ # (label)
+ label {
+ monitor =
+ text = $LAYOUT
+ color = rgba(, 1.0)
+ font_size = 15
+ font_family = Product Sans Medium
+ position = 100, -110
+ shadow_passes = 5
+ shadow_size = 10
+ halign = left
+ valign = top
+ }
+ # (icon)
+ label {
+ monitor =
+ text = keyboard
+ color = rgba(, 1.0)
+ font_size = 15
+ font_family = Material Symbols Outlined
+ position = 75, -112
+ shadow_passes = 5
+ shadow_size = 10
+ halign = left
+ valign = top
+ }
+#
+
+
diff --git a/config/material-colors/templates/material-discord.scss b/config/material-colors/templates/material-discord.scss
new file mode 100644
index 0000000..607ee99
--- /dev/null
+++ b/config/material-colors/templates/material-discord.scss
@@ -0,0 +1,55 @@
+@use "sass:color";
+
+@import url(https://capnkitten.github.io/BetterDiscord/Themes/Material-Discord/css/source.css);
+@import "/colors.scss";
+
+
+$color-scheme: ;
+
+$hue: round(color.channel($primary, "hue", $space: hsl));
+$saturation: round(color.channel($primary, "saturation", $space: hsl));
+$lightness: round(color.channel($primary, "lightness", $space: hsl));
+
+* {
+ transition: color 0.2s ease-in-out;
+ transition-property: background-color, color;
+}
+
+.theme-#{$color-scheme} {
+ --main-color: #{$background};
+ --main-alt: #{$surfaceContainerLow};
+
+ --message-color: #{$surfaceContainerLowest};
+ --message-color-hover: #{$surfaceContainer};
+ --message-color-alt: #{$surfaceContainer};
+ --attachment-color: #{$background};
+
+ --accent-hue: #{$hue};
+ --accent-saturation: #{$saturation};
+ --accent-lightness: #{$lightness};
+ --accent-text-color: #{$onPrimary};
+
+ --main-textarea-color: #{$surfaceContainerHigh};
+ --main-textarea-color-alt: #{$surfaceContainerHighest};
+ --status-picker-color: #{$surfaceContainerHigh};
+
+ --tooltip-color: #{$surfaceContainer};
+ --popout-color: #{$surfaceContainer};
+ --popout-color-alt: #{$surfaceContainerLowest};
+ --popout-header-border: #{$onSurface};
+ --separator-color: #{$outlineVariant};
+ --sidebar-panel-color: #{$surfaceContainerLowest};
+ --server-color: #{$surfaceContainerLow};
+}
+
+[class*="botTag_"] svg path {
+ fill: #{$onPrimary};
+}
+
+[class*="repliedTextContent_"] {
+ padding: 0px 5px 0px 5px !important;
+}
+
+[class*="userPopoutOuter_"] {
+ border-radius: 16px !important;
+}
diff --git a/config/material-colors/templates/svg/brightness-onPrimary.svg b/config/material-colors/templates/svg/brightness-onPrimary.svg
new file mode 100644
index 0000000..faa8d91
--- /dev/null
+++ b/config/material-colors/templates/svg/brightness-onPrimary.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/config/material-colors/templates/svg/dark-onPrimary.svg b/config/material-colors/templates/svg/dark-onPrimary.svg
new file mode 100644
index 0000000..08a4400
--- /dev/null
+++ b/config/material-colors/templates/svg/dark-onPrimary.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/config/sddm/Main.qml b/config/sddm/Main.qml
new file mode 100644
index 0000000..cb7b43b
--- /dev/null
+++ b/config/sddm/Main.qml
@@ -0,0 +1,38 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Window 2.15
+
+import "./components"
+
+Rectangle {
+ id: root
+
+ height: Screen.height
+ width: Screen.width
+
+ Image {
+ anchors { fill: parent }
+
+ source: config.BgSource
+ fillMode: Image.PreserveAspectCrop
+ clip: true
+ }
+
+ Item {
+ anchors {
+ fill: parent
+ margins: config.Padding
+ }
+
+ DateTimePanel {
+ anchors {
+ top: parent.top
+ right: parent.right
+ }
+ }
+
+ LoginPanel {
+ anchors { fill: parent }
+ }
+ }
+}
diff --git a/config/sddm/scripts/disable.sh b/config/sddm/scripts/disable.sh
new file mode 100755
index 0000000..b95c874
--- /dev/null
+++ b/config/sddm/scripts/disable.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+figlet "Disable SDDM"
+if [ -f /etc/systemd/system/display-manager.service ]; then
+ if gum confirm "Do you want to disable the current display manager?"; then
+ sudo rm /etc/systemd/system/display-manager.service
+ echo ":: Current display manager removed."
+ echo ":: Please reboot your system."
+ fi
+else
+ echo ":: No Display Manager enabled."
+fi
+sleep 3
diff --git a/config/sddm/scripts/enable.sh b/config/sddm/scripts/enable.sh
new file mode 100755
index 0000000..6383ed6
--- /dev/null
+++ b/config/sddm/scripts/enable.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+figlet "Enable SDDM"
+if [ -f /etc/systemd/system/display-manager.service ]; then
+ echo ":: Display Manager is already enabled."
+else
+ if gum confirm "Do you want to enable SDDM as your display manager?"; then
+ sudo systemctl enable sddm.service
+ echo ":: Display manager SDDM has been enabled."
+ echo ":: Please reboot your system!"
+ fi
+fi
+sleep 3
diff --git a/config/sddm/scripts/wallpaper.sh b/config/sddm/scripts/wallpaper.sh
new file mode 100755
index 0000000..f8a0b36
--- /dev/null
+++ b/config/sddm/scripts/wallpaper.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+cache_file="$HOME/.cache/current_wallpaper"
+if [ ! -d /etc/sddm.conf.d/ ]; then
+ sudo mkdir /etc/sddm.conf.d
+ echo "Folder /etc/sddm.conf.d created."
+fi
+
+cp $HOME/dotfiles/sddm/sddm.conf /etc/sddm.conf.d/
+cp $HOME/dotfiles/sddm/sddm.conf /etc/
+if [ "$1" != "init" ]; then
+ echo "File /etc/sddm.conf.d/sddm.conf updated."
+fi
+
+current_wallpaper=$(cat "$cache_file")
+extension="${current_wallpaper##*.}"
+
+cp $current_wallpaper /usr/share/sddm/themes/corners/backgrounds/current_wallpaper.$extension
+
+if [ "$1" != "init" ]; then
+ echo "Current wallpaper copied into /usr/share/sddm/themes/corners/backgrounds/"
+fi
+
+new_wall=$(echo $current_wallpaper | sed "s|$HOME/wallpaper/||g")
+cp $HOME/.cache/material/colors-sddm-style.conf /usr/share/sddm/themes/corners/theme.conf
+sed -i 's/CURRENTWALLPAPER/'"current_wallpaper.$extension"'/' /usr/share/sddm/themes/corners/theme.conf
+
+if [ "$1" != "init" ]; then
+ echo "File theme.conf updated in /usr/share/sddm/themes/corners/"
+
+ echo "DONE! Please logout to test sddm."
+fi
diff --git a/config/sddm/sddm.conf b/config/sddm/sddm.conf
new file mode 100644
index 0000000..e459a7a
--- /dev/null
+++ b/config/sddm/sddm.conf
@@ -0,0 +1,138 @@
+[Autologin]
+# Whether sddm should automatically log back into sessions when they exit
+Relogin=false
+
+# Name of session file for autologin session (if empty try last logged in)
+Session=
+
+# Username for autologin session
+User=
+
+[General]
+# Which display server should be used.
+# Valid values are: x11, x11-user, wayland. Wayland support is experimental
+DisplayServer=x11
+
+# Comma-separated list of environment variables to be set
+GreeterEnvironment=
+
+# Halt command
+HaltCommand=/usr/bin/systemctl poweroff
+
+# Input method module
+InputMethod=
+
+# Comma-separated list of Linux namespaces for user session to enter
+Namespaces=
+
+# Initial NumLock state. Can be on, off or none.
+# If property is set to none, numlock won't be changed
+# NOTE: Currently ignored if autologin is enabled.
+Numlock=none
+
+# Reboot command
+RebootCommand=/usr/bin/systemctl reboot
+
+
+[Theme]
+# Current theme name
+Current=corners
+
+# Cursor size used in the greeter
+CursorSize=6
+
+# Cursor theme used in the greeter
+CursorTheme=Bibata-Original-Classic
+
+# Number of users to use as threshold
+# above which avatars are disabled
+# unless explicitly enabled with EnableAvatars
+DisableAvatarsThreshold=7
+
+# Enable display of custom user avatars
+EnableAvatars=false
+
+# Global directory for user avatars
+# The files should be named .face.icon
+FacesDir=/usr/share/sddm/faces
+
+# Font used in the greeter
+Font=
+
+# Theme directory path
+# ThemeDir=/usr/share/sddm/themes
+ThemeDir=/usr/share/sddm/themes
+
+[Users]
+# Default $PATH for logged in users
+DefaultPath=/usr/local/sbin:/usr/local/bin:/usr/bin
+
+# Comma-separated list of shells.
+# Users with these shells as their default won't be listed
+HideShells=
+
+# Comma-separated list of users that should not be listed
+HideUsers=
+
+# Maximum user id for displayed users
+MaximumUid=60513
+
+# Minimum user id for displayed users
+MinimumUid=1000
+
+# Remember the session of the last successfully logged in user
+RememberLastSession=true
+
+# Remember the last successfully logged in user
+RememberLastUser=true
+
+# When logging in as the same user twice, restore the original session, rather than create a new one
+ReuseSession=true
+
+
+[Wayland]
+# Path of the Wayland compositor to execute when starting the greeter
+CompositorCommand=weston --shell=fullscreen-shell.so
+
+# Enable Qt's automatic high-DPI scaling
+EnableHiDPI=true
+
+# Path to a script to execute when starting the desktop session
+SessionCommand=/usr/share/sddm/scripts/wayland-session
+
+# Comma-separated list of directories containing available Wayland sessions
+SessionDir=/usr/local/share/wayland-sessions,/usr/share/wayland-sessions
+
+# Path to the user session log file
+SessionLogFile=.local/share/sddm/wayland-session.log
+
+
+[X11]
+# Path to a script to execute when starting the display server
+DisplayCommand=/usr/share/sddm/scripts/Xsetup
+
+# Path to a script to execute when stopping the display server
+DisplayStopCommand=/usr/share/sddm/scripts/Xstop
+
+# Enable Qt's automatic high-DPI scaling
+EnableHiDPI=true
+
+# Arguments passed to the X server invocation
+ServerArguments=-nolisten tcp
+
+# Path to X server binary
+ServerPath=/usr/bin/X
+
+# Path to a script to execute when starting the desktop session
+SessionCommand=/usr/share/sddm/scripts/Xsession
+
+# Comma-separated list of directories containing available X sessions
+SessionDir=/usr/local/share/xsessions,/usr/share/xsessions
+
+# Path to the user session log file
+SessionLogFile=.local/share/sddm/xorg-session.log
+
+# Path to Xephyr binary
+XephyrPath=/usr/bin/Xephyr
+
+
diff --git a/config/wallpaper.py b/config/wallpaper.py
new file mode 100644
index 0000000..1703b5a
--- /dev/null
+++ b/config/wallpaper.py
@@ -0,0 +1,271 @@
+import os
+import sys
+import importlib.util
+import argparse
+import fcntl
+import subprocess
+import asyncio
+import random as _random
+import colorsys
+import json
+import inspect
+
+
+def get_relative_path(path: str, level: int = 1) -> str:
+ prev_globals = inspect.stack()[level][0].f_globals
+ file_var = (
+ os.path.dirname(os.path.abspath(prev_globals["__file__"]))
+ if "__file__" in prev_globals
+ else os.getcwd()
+ )
+ return os.path.join(file_var, path)
+
+
+lock_file_path = "/tmp/wallpaper.lock"
+settings_file_path = get_relative_path("../config/assets/settings.json")
+
+
+def acquire_lock():
+ global lock_file
+ lock_file = open(lock_file_path, "w")
+ try:
+ fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ lock_file.write(str(os.getpid()))
+ lock_file.flush()
+ except IOError:
+ print("Another instance of the script is already running.")
+ sys.exit(1)
+
+
+def release_lock():
+ fcntl.flock(lock_file, fcntl.LOCK_UN)
+ lock_file.close()
+ os.remove(lock_file_path)
+
+
+def hue_to_numeric_hex(hue):
+ hue = hue / 360.0
+ rgb = colorsys.hls_to_rgb(hue, 0.5, 1.0)
+ hex_color_str = "#{:02x}{:02x}{:02x}".format(
+ int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255)
+ )
+ numeric_hex_color = int(hex_color_str.lstrip("#"), 16)
+ return numeric_hex_color
+
+
+def load_settings():
+ default_settings = {
+ "color-scheme": "dark",
+ "custom-color": "none",
+ "generation-scheme": "tonalSpot",
+ }
+
+ if not os.path.exists(settings_file_path):
+ os.makedirs(os.path.dirname(settings_file_path), exist_ok=True)
+ with open(settings_file_path, "w") as file:
+ json.dump(default_settings, file, indent=4)
+
+ with open(settings_file_path, "r") as file:
+ return json.load(file)
+
+
+parser = argparse.ArgumentParser()
+group = parser.add_mutually_exclusive_group(required=True)
+group.add_argument("-I", "--image", type=str, help="Image")
+group.add_argument(
+ "-P",
+ "--prev",
+ help="Use last used wallpaper for color generation",
+ action="store_true",
+)
+group.add_argument(
+ "-R", "--random", help="Random image from folder", action="store_true"
+)
+parser.add_argument("-n", "--notify", help="Send notifications", action="store_true")
+parser.add_argument(
+ "--status", type=str, help="Status file", default="/tmp/wallpaper.status"
+)
+
+args = parser.parse_args()
+
+random = args.random
+prev = args.prev
+image = args.image
+notify = args.notify
+status = args.status
+
+HOME = os.path.expanduser("~")
+
+module_path = get_relative_path("./material-colors")
+sys.path.append(module_path)
+
+module_name = "generate"
+file_path = f"{module_path}/{module_name}.py"
+
+spec = importlib.util.spec_from_file_location(module_name, file_path)
+GENERATOR = importlib.util.module_from_spec(spec) # type: ignore
+spec.loader.exec_module(GENERATOR) # type: ignore
+
+cache_file = f"{HOME}/.cache/current_wallpaper"
+square = f"{HOME}/.cache/square_wallpaper.png"
+png = f"{HOME}/.cache/current_wallpaper.png"
+
+
+def current_state(state_str: str):
+ with open(status, "w") as f:
+ f.write(state_str)
+
+
+def send_notify(label: str, desc: str):
+ if not notify:
+ return
+ subprocess.run(["notify-send", label, desc])
+
+
+def state(name: str | None, label: str | None, desc: str | None):
+ if name is not None:
+ current_state(name)
+ if label is not None:
+ send_notify(label, desc or "")
+
+
+def join(*args):
+ return os.path.join(*args)
+
+
+async def main():
+ state("init", None, None)
+
+ settings = load_settings()
+ color_scheme = settings["color-scheme"]
+ custom_color = settings["custom-color"]
+ generation_scheme = settings["generation-scheme"]
+ swww_animation = "wipe"
+ wallpaper_engine = "swww"
+
+ new_wallpaper = f"{HOME}/Pictures/wallpapers/example-1.jpg"
+ # new_wallpaper = get_relative_path("../assets/wallpapers/1.png")
+
+ if random:
+ files = [
+ f
+ for f in os.listdir(f"{HOME}/Pictures/wallpapers/")
+ if f.endswith((".png", ".jpg", ".jpeg"))
+ ]
+ if files:
+ new_wallpaper = join(f"{HOME}/Pictures/wallpapers", _random.choice(files))
+ elif prev:
+ try:
+ with open(cache_file) as f:
+ new_wallpaper = f.read().strip()
+ except FileNotFoundError:
+ pass
+ elif image is not None:
+ new_wallpaper = os.path.abspath(image)
+
+ print(f":: Wallpaper {new_wallpaper}")
+
+ with open(cache_file, "w") as f:
+ f.write(new_wallpaper)
+
+ with_image = f"with image {new_wallpaper}"
+
+ # -----------------------------------------------------
+ # Set the new wallpaper
+ # -----------------------------------------------------
+
+ transition_type = swww_animation
+
+ state("changing", "Changing wallpaper...", with_image)
+ print(":: Changing wallpaper...")
+
+ if wallpaper_engine == "swww":
+ print(":: Using swww")
+
+ cursor_pos = subprocess.getoutput("hyprctl cursorpos").replace(", ", ",")
+
+ subprocess.run(
+ [
+ "swww",
+ "img",
+ new_wallpaper,
+ "--transition-bezier",
+ ".43,1.19,1,.4",
+ "--transition-fps",
+ "60",
+ "--transition-type",
+ transition_type,
+ "--transition-duration",
+ "0.7",
+ "--transition-pos",
+ cursor_pos,
+ ]
+ )
+
+ else:
+ print(":: Wallpaper Engine disabled")
+
+ # -----------------------------------------------------
+ # Generate colors
+ # -----------------------------------------------------
+ state("colors", "Generating colors...", with_image)
+ print(":: Generate colors")
+ _starts_with = lambda x: str(x).startswith("-")
+
+ GENERATOR.main(
+ color_scheme,
+ new_wallpaper,
+ (
+ hue_to_numeric_hex(int(custom_color.lstrip("-")))
+ if _starts_with(custom_color)
+ else (int(custom_color.lstrip("#"), 16) if custom_color != "none" else None)
+ ),
+ scheme_name=generation_scheme,
+ )
+
+ # Generate square and png versions
+ await asyncio.gather(square_image(new_wallpaper), png_image(new_wallpaper))
+
+ state("finish", "Wallpaper procedure complete!", with_image)
+
+
+async def png_image(wallpaper: str):
+ if wallpaper.lower().endswith((".jpg", ".jpeg")):
+ state(None, "Converting jpg to png...", f"with image {wallpaper}")
+ print(":: Converting jpg to png...")
+ cmd = f"magick {wallpaper}[0] {png}"
+ else:
+ cmd = f"cp -f {wallpaper} {png}"
+
+ process = await asyncio.create_subprocess_shell(
+ cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
+ )
+ stdout, stderr = await process.communicate()
+
+ if process.returncode != 0:
+ print(f":: Error while processing image: {stderr.decode()}")
+ else:
+ print(":: JPG successfully converted to PNG!")
+
+
+async def square_image(wallpaper):
+ state(None, "Creating square version...", f"with image {wallpaper}")
+ print(":: Creating square version")
+ cmd = f"magick {wallpaper}[0] -gravity Center -extent 1:1 {square}"
+ process = await asyncio.create_subprocess_shell(
+ cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
+ )
+ stdout, stderr = await process.communicate()
+
+ if process.returncode != 0:
+ print(f":: Error while processing image: {stderr.decode()}")
+ else:
+ print(":: Square image created!")
+
+
+if __name__ == "__main__":
+ acquire_lock()
+ try:
+ asyncio.run(main())
+ finally:
+ release_lock()
diff --git a/config/wayland-idle-inhibitor.py b/config/wayland-idle-inhibitor.py
new file mode 100755
index 0000000..c731f67
--- /dev/null
+++ b/config/wayland-idle-inhibitor.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+
+import sys
+from dataclasses import dataclass
+from signal import SIGINT, SIGTERM, signal
+from threading import Event
+import setproctitle
+
+from pywayland.client.display import Display # type: ignore
+from pywayland.protocol.idle_inhibit_unstable_v1.zwp_idle_inhibit_manager_v1 import ( # type: ignore
+ ZwpIdleInhibitManagerV1,
+)
+from pywayland.protocol.wayland.wl_compositor import WlCompositor # type: ignore
+from pywayland.protocol.wayland.wl_registry import WlRegistryProxy # type: ignore
+from pywayland.protocol.wayland.wl_surface import WlSurface # type: ignore
+
+
+@dataclass
+class GlobalRegistry:
+ surface: WlSurface | None = None
+ inhibit_manager: ZwpIdleInhibitManagerV1 | None = None
+
+
+def handle_registry_global(
+ wl_registry: WlRegistryProxy, id_num: int, iface_name: str, version: int
+) -> None:
+ global_registry: GlobalRegistry = wl_registry.user_data or GlobalRegistry()
+
+ if iface_name == "wl_compositor":
+ compositor = wl_registry.bind(id_num, WlCompositor, version)
+ global_registry.surface = compositor.create_surface() # type: ignore
+ elif iface_name == "zwp_idle_inhibit_manager_v1":
+ global_registry.inhibit_manager = wl_registry.bind(
+ id_num, ZwpIdleInhibitManagerV1, version
+ )
+
+
+def main() -> None:
+ done = Event()
+ signal(SIGINT, lambda _, __: done.set())
+ signal(SIGTERM, lambda _, __: done.set())
+
+ global_registry = GlobalRegistry()
+
+ display = Display()
+ display.connect()
+
+ registry = display.get_registry() # type: ignore
+ registry.user_data = global_registry
+ registry.dispatcher["global"] = handle_registry_global
+
+ def shutdown() -> None:
+ display.dispatch()
+ display.roundtrip()
+ display.disconnect()
+
+ display.dispatch()
+ display.roundtrip()
+
+ if global_registry.surface is None or global_registry.inhibit_manager is None:
+ print("Wayland seems not to support idle_inhibit_unstable_v1 protocol.")
+ shutdown()
+ sys.exit(1)
+
+ inhibitor = global_registry.inhibit_manager.create_inhibitor( # type: ignore
+ global_registry.surface
+ )
+
+ display.dispatch()
+ display.roundtrip()
+
+ print("Inhibiting idle...")
+ done.wait()
+ print("Shutting down...")
+
+ inhibitor.destroy()
+
+ shutdown()
+
+
+if __name__ == "__main__":
+ setproctitle.setproctitle("wayland-idle-inhibitor.py")
+ main()
diff --git a/install.sh b/install.sh
index 1d421d5..d805837 100644
--- a/install.sh
+++ b/install.sh
@@ -25,6 +25,7 @@ PACKAGES=(
python-numpy
python-pywayland
python-pyxdg
+ sddm-theme-corners-git
swww
swappy
wl-clipboard
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..56baf28
--- /dev/null
+++ b/main.py
@@ -0,0 +1,69 @@
+import os
+
+import setproctitle
+from fabric import Application
+from fabric.utils import get_relative_path, monitor_file
+from loguru import logger
+
+from modules.bar.bar import Bar
+from modules.launcher.launcher import Launcher
+from modules.notification_popup import NotificationPopup
+from modules.osd import OSDContainer
+from modules.corners import Corners
+from services import sc
+
+for log in [
+ "fabric.hyprland.widgets",
+ "fabric.audio.service",
+ "fabric.bluetooth.service",
+]:
+ logger.disable(log)
+
+
+def update_main_css():
+ colors_css_path = f"/home/{os.getlogin()}/.cache/material/colors.css"
+ main_css_path = get_relative_path("styles/main.css")
+
+ if os.path.exists(colors_css_path):
+ with open(main_css_path, "r+") as css_file:
+ content = css_file.read()
+ updated_content = content.replace("@COLORS_CSS_PATH", colors_css_path)
+ css_file.seek(0)
+ css_file.write(updated_content)
+ css_file.truncate()
+ else:
+ logger.warning(f"[Main] colors.css not found at {colors_css_path}")
+
+
+def apply_style(app: Application):
+ logger.info("[Main] Applying CSS")
+ app.set_stylesheet_from_file(get_relative_path("styles/main.css"))
+
+
+if __name__ == "__main__":
+ update_main_css()
+ sc = sc
+ bar = Bar()
+ corners = Corners()
+ osd = OSDContainer()
+ notif = NotificationPopup()
+ launcher = Launcher()
+
+ app = Application(
+ "modus",
+ bar,
+ launcher,
+ osd,
+ )
+ setproctitle.setproctitle("modus")
+
+ # Monitor CSS files for changes
+ css_file = monitor_file(get_relative_path("styles"))
+ _ = css_file.connect("changed", lambda *_: apply_style(app))
+
+ color_css_file = monitor_file(f"/home/{os.getlogin()}/.cache/material/colors.css")
+ _ = color_css_file.connect("changed", lambda *_: apply_style(app))
+
+ # Apply the styles and run the application
+ apply_style(app)
+ app.run()
diff --git a/modules/__pycache__/corners.cpython-313.pyc b/modules/__pycache__/corners.cpython-313.pyc
new file mode 100644
index 0000000..cca949f
Binary files /dev/null and b/modules/__pycache__/corners.cpython-313.pyc differ
diff --git a/modules/__pycache__/notification_popup.cpython-313.pyc b/modules/__pycache__/notification_popup.cpython-313.pyc
new file mode 100644
index 0000000..3f45a46
Binary files /dev/null and b/modules/__pycache__/notification_popup.cpython-313.pyc differ
diff --git a/modules/__pycache__/osd.cpython-313.pyc b/modules/__pycache__/osd.cpython-313.pyc
new file mode 100644
index 0000000..373fc64
Binary files /dev/null and b/modules/__pycache__/osd.cpython-313.pyc differ
diff --git a/modules/bar/__pycache__/bar.cpython-313.pyc b/modules/bar/__pycache__/bar.cpython-313.pyc
new file mode 100644
index 0000000..2eaaca3
Binary files /dev/null and b/modules/bar/__pycache__/bar.cpython-313.pyc differ
diff --git a/modules/bar/bar.py b/modules/bar/bar.py
new file mode 100644
index 0000000..acd5e2c
--- /dev/null
+++ b/modules/bar/bar.py
@@ -0,0 +1,138 @@
+from fabric.hyprland.widgets import Language
+from fabric.system_tray.widgets import SystemTray
+from fabric.utils import FormattedString, bulk_replace
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.centerbox import CenterBox
+from fabric.widgets.datetime import DateTime
+from fabric.widgets.label import Label
+from fabric.widgets.wayland import WaylandWindow as Window
+from gi.repository import GLib
+from modules.bar.components import (
+ BatteryLabel,
+ BluetoothIndicator,
+ IdleIndicator,
+ MicrophoneIndicator,
+ NetworkIndicator,
+ PowerProfileIndicator,
+ SystemInfo,
+ TaskBar,
+ VolumeIndicator,
+ workspace,
+)
+from snippets import MaterialIcon
+from services import sc
+
+
+class Bar(Window):
+ def __init__(self):
+ self.workspaces = Button(child=workspace, name="workspaces")
+ self.language = Language(
+ formatter=FormattedString(
+ "{replace_lang(language)}",
+ replace_lang=lambda lang: bulk_replace(
+ lang,
+ (r".*Eng.*", r".*Nep.*"),
+ ("en", "np"),
+ regex=True,
+ ),
+ ),
+ )
+
+ self.recording_indicator = Button(
+ name="recording-indicator",
+ child=MaterialIcon("screen_record", 14),
+ visible=False,
+ on_clicked=lambda *_: sc.screencast_stop(),
+ )
+
+ sc.connect(
+ "recording", lambda _, status: self.on_recording_status_change(status)
+ )
+
+ self.date_time = DateTime(formatters=["%-I:%M ๓ฐง %a %d %b"], name="datetime")
+
+ self.battery = BatteryLabel(name="battery")
+ self.volume = VolumeIndicator()
+ self.bluetooth = BluetoothIndicator()
+ self.network = NetworkIndicator()
+ self.microphone = MicrophoneIndicator()
+ self.idle = IdleIndicator()
+ self.taskbar = TaskBar()
+ self.info = SystemInfo()
+ self.powerindicator = PowerProfileIndicator()
+ self.tray = SystemTray(name="tray", icon_size=16, spacing=4)
+ self.launcher = Button(
+ name="logo",
+ child=Label(name="logo-name", label="๓ฐฃ ๓ฐซฟ๓ฐซฐ๓ฐซต"),
+ on_clicked=lambda *_: GLib.spawn_command_line_async(
+ "fabric-cli exec modus 'launcher.open(\"launcher\")'"
+ ),
+ )
+
+ self.applets = Box(
+ name="applets",
+ spacing=4,
+ orientation="h",
+ children=[
+ self.language,
+ self.battery,
+ self.powerindicator,
+ self.bluetooth,
+ self.network,
+ self.volume,
+ self.microphone,
+ self.idle,
+ ],
+ )
+
+ self.bar = CenterBox(
+ name="bar",
+ start_children=Box(
+ name="start-container",
+ spacing=8,
+ orientation="h",
+ children=[
+ self.launcher,
+ self.workspaces,
+ self.info,
+ ],
+ ),
+ center_children=Box(
+ name="center-container",
+ spacing=8,
+ orientation="h",
+ children=self.taskbar,
+ ),
+ end_children=Box(
+ name="end-container",
+ spacing=8,
+ orientation="h",
+ children=[
+ self.recording_indicator,
+ self.tray,
+ self.applets,
+ self.date_time,
+ ],
+ ),
+ )
+ super().__init__(
+ layer="top",
+ anchor="left bottom right",
+ exclusivity="auto",
+ visible=True,
+ child=self.bar,
+ )
+
+ self.hidden = False
+
+ def on_recording_status_change(self, status):
+ print(f"Recording status changed: {status}")
+ self.recording_indicator.set_visible(status)
+
+ def toggle_hidden(self):
+ self.hidden = not self.hidden
+ if self.hidden:
+ self.bar.add_style_class("hidden")
+ else:
+ self.bar.remove_style_class("hidden")
diff --git a/modules/bar/components/__init__.py b/modules/bar/components/__init__.py
new file mode 100644
index 0000000..278c35f
--- /dev/null
+++ b/modules/bar/components/__init__.py
@@ -0,0 +1,10 @@
+from .battery import *
+from .bluetooth import *
+from .idle import *
+from .stats import *
+from .microphone import *
+from .network import *
+from .powerprofile import *
+from .taskbar import *
+from .volume import *
+from .workspace import *
diff --git a/modules/bar/components/__pycache__/__init__.cpython-313.pyc b/modules/bar/components/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..cf8495f
Binary files /dev/null and b/modules/bar/components/__pycache__/__init__.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/battery.cpython-313.pyc b/modules/bar/components/__pycache__/battery.cpython-313.pyc
new file mode 100644
index 0000000..84586f3
Binary files /dev/null and b/modules/bar/components/__pycache__/battery.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/bluetooth.cpython-313.pyc b/modules/bar/components/__pycache__/bluetooth.cpython-313.pyc
new file mode 100644
index 0000000..25afe78
Binary files /dev/null and b/modules/bar/components/__pycache__/bluetooth.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/idle.cpython-313.pyc b/modules/bar/components/__pycache__/idle.cpython-313.pyc
new file mode 100644
index 0000000..55b894d
Binary files /dev/null and b/modules/bar/components/__pycache__/idle.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/microphone.cpython-313.pyc b/modules/bar/components/__pycache__/microphone.cpython-313.pyc
new file mode 100644
index 0000000..64023d5
Binary files /dev/null and b/modules/bar/components/__pycache__/microphone.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/network.cpython-313.pyc b/modules/bar/components/__pycache__/network.cpython-313.pyc
new file mode 100644
index 0000000..af3aa99
Binary files /dev/null and b/modules/bar/components/__pycache__/network.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/powerprofile.cpython-313.pyc b/modules/bar/components/__pycache__/powerprofile.cpython-313.pyc
new file mode 100644
index 0000000..a29d50f
Binary files /dev/null and b/modules/bar/components/__pycache__/powerprofile.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/recorder.cpython-313.pyc b/modules/bar/components/__pycache__/recorder.cpython-313.pyc
new file mode 100644
index 0000000..c9af69f
Binary files /dev/null and b/modules/bar/components/__pycache__/recorder.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/stats.cpython-313.pyc b/modules/bar/components/__pycache__/stats.cpython-313.pyc
new file mode 100644
index 0000000..737038d
Binary files /dev/null and b/modules/bar/components/__pycache__/stats.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/taskbar.cpython-313.pyc b/modules/bar/components/__pycache__/taskbar.cpython-313.pyc
new file mode 100644
index 0000000..bf0830f
Binary files /dev/null and b/modules/bar/components/__pycache__/taskbar.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/volume.cpython-313.pyc b/modules/bar/components/__pycache__/volume.cpython-313.pyc
new file mode 100644
index 0000000..36fe0f6
Binary files /dev/null and b/modules/bar/components/__pycache__/volume.cpython-313.pyc differ
diff --git a/modules/bar/components/__pycache__/workspace.cpython-313.pyc b/modules/bar/components/__pycache__/workspace.cpython-313.pyc
new file mode 100644
index 0000000..8842c1c
Binary files /dev/null and b/modules/bar/components/__pycache__/workspace.cpython-313.pyc differ
diff --git a/modules/bar/components/battery.py b/modules/bar/components/battery.py
new file mode 100644
index 0000000..2dd55b8
--- /dev/null
+++ b/modules/bar/components/battery.py
@@ -0,0 +1,68 @@
+import psutil
+from fabric import Fabricator
+from fabric.widgets.box import Box
+from fabric.widgets.overlay import Overlay
+from fabric.widgets.circularprogressbar import CircularProgressBar
+from snippets import MaterialIcon
+
+
+class BatteryLabel(Box):
+ ICONS_CHARGING = [
+ "battery_charging_20",
+ "battery_charging_20",
+ "battery_charging_20",
+ "battery_charging_30",
+ "battery_charging_30",
+ "battery_charging_50",
+ "battery_charging_60",
+ "battery_charging_80",
+ "battery_charging_80",
+ "battery_charging_90",
+ "battery_charging_full",
+ ]
+ ICONS_NOT_CHARGING = [
+ "battery_alert",
+ "battery_1_bar",
+ "battery_1_bar",
+ "battery_2_bar",
+ "battery_2_bar",
+ "battery_3_bar",
+ "battery_4_bar",
+ "battery_4_bar",
+ "battery_5_bar",
+ "battery_6_bar",
+ "battery_full",
+ ]
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ Fabricator(interval=1000, poll_from=self.update_battery_status)
+
+ def update_battery_status(self, *_):
+ battery = psutil.sensors_battery()
+ if battery is None:
+ self.hide()
+ return
+ is_charging = battery.power_plugged if battery else False
+ icons = self.ICONS_CHARGING if is_charging else self.ICONS_NOT_CHARGING
+ battery_percent = round(battery.percent)
+ index = min(max(battery_percent // 10, 0), 10)
+ battery_icon = MaterialIcon(icons[index], size=16)
+
+ self.progress_bar = CircularProgressBar(
+ name="progress", line_style="round", line_width=1, size=24
+ )
+
+ self.battery_overlay = Overlay(child=self.progress_bar, overlays=battery_icon)
+
+ self.children = self.battery_overlay
+
+ battery_percent = round(battery.percent)
+ self.progress_bar.value = battery_percent / 100
+ # self.show() if battery_percent < 100 else self.hide()
+
+ self.set_tooltip_text(
+ f"Battery: {battery_percent}%\nStatus: {'Charging' if is_charging else 'Discharging'}"
+ )
+
+ return True
diff --git a/modules/bar/components/bluetooth.py b/modules/bar/components/bluetooth.py
new file mode 100644
index 0000000..ffc4fec
--- /dev/null
+++ b/modules/bar/components/bluetooth.py
@@ -0,0 +1,34 @@
+from fabric.bluetooth import BluetoothClient
+from fabric.widgets.box import Box
+from snippets import MaterialIcon
+
+
+class BluetoothIndicator(Box):
+ ICON_ENABLED = "bluetooth"
+ ICON_DISABLED = "bluetooth_disabled"
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.bluetooth_client = BluetoothClient()
+
+ self.bluetooth_icon = None
+
+ self.bluetooth_client.connect("changed", self.update_bluetooth_status)
+
+ self.update_bluetooth_status()
+
+ def update_bluetooth_status(self, *_):
+ icon_label = (
+ self.ICON_ENABLED if self.bluetooth_client.enabled else self.ICON_DISABLED
+ )
+
+ new_icon = MaterialIcon(icon_label, size=16)
+
+ if self.bluetooth_icon:
+ self.remove(self.bluetooth_icon)
+
+ self.bluetooth_icon = new_icon
+ self.add(self.bluetooth_icon)
+
+ def on_destroy(self):
+ self.bluetooth_client.disconnect("changed", self.update_bluetooth_status)
diff --git a/modules/bar/components/idle.py b/modules/bar/components/idle.py
new file mode 100644
index 0000000..6ad444a
--- /dev/null
+++ b/modules/bar/components/idle.py
@@ -0,0 +1,27 @@
+from fabric import Fabricator
+from fabric.utils import exec_shell_command
+from fabric.widgets.box import Box
+from snippets import MaterialIcon
+
+
+class IdleIndicator(Box):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.idle_icon = self.create_idle_icon()
+ self.fabricator = Fabricator(interval=1000, poll_from=self.check_idle_status)
+
+ self.children = [self.idle_icon]
+
+ def create_idle_icon(self):
+ return MaterialIcon("coffee", 16)
+
+ def check_idle_status(self, *_):
+ output = exec_shell_command("pidof wayland-idle-inhibitor.py")
+ is_idle = bool(str(output).strip())
+ self.update_idle_status(is_idle)
+
+ def update_idle_status(self, is_idle):
+ if is_idle:
+ self.idle_icon.set_visible(True)
+ else:
+ self.idle_icon.set_visible(False)
diff --git a/modules/bar/components/microphone.py b/modules/bar/components/microphone.py
new file mode 100644
index 0000000..a89baf7
--- /dev/null
+++ b/modules/bar/components/microphone.py
@@ -0,0 +1,33 @@
+from fabric.audio.service import Audio
+from fabric.widgets.box import Box
+from snippets import MaterialIcon
+
+
+class MicrophoneIndicator(Box):
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.audio_service = Audio()
+ self.microphone_icon = self.create_microphone_icon()
+
+ self.audio_service.connect("microphone_changed", self.update_microphone_status)
+ self.update_microphone_status()
+
+ self.children = (self.microphone_icon,)
+
+ def create_microphone_icon(self):
+ return MaterialIcon("mic_off", size=16)
+
+ def update_microphone_status(self, *args):
+ current_microphone = self.audio_service.microphone
+
+ if current_microphone:
+ is_muted = current_microphone.muted
+ icon_name = "mic_off" if is_muted else "mic"
+
+ self.microphone_icon.set_label(icon_name)
+ self.microphone_icon.set_visible(is_muted)
+ else:
+ self.microphone_icon.set_visible(False)
+
+ return True
diff --git a/modules/bar/components/network.py b/modules/bar/components/network.py
new file mode 100644
index 0000000..3407134
--- /dev/null
+++ b/modules/bar/components/network.py
@@ -0,0 +1,84 @@
+import subprocess
+
+import psutil
+from fabric import Fabricator
+from fabric.widgets.box import Box
+from snippets import MaterialIcon
+
+
+class NetworkIndicator(Box):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.update_interval = 5000 # Increased interval to 5 seconds
+ self.last_status = None
+ self.wifi_strength_cache = None
+ self.fabricator = Fabricator(
+ interval=self.update_interval,
+ poll_from=self.update_network_status,
+ )
+
+ def update_network_status(self, *_):
+ current_status = self.get_network_status()
+ if current_status != self.last_status:
+ self.update_icon(current_status)
+ self.last_status = current_status
+ return True
+
+ def update_icon(self, current_status):
+ self.icon_label = MaterialIcon(current_status, size=16)
+ self.children = (self.icon_label,)
+
+ def get_network_status(self):
+ if self.is_ethernet_connected():
+ return "lan"
+ if self.is_wifi_connected():
+ return self.get_wifi_strength_icon()
+ return "signal_wifi_off"
+
+ def get_wifi_strength_icon(self):
+ wifi_strength = self.check_wifi_strength()
+ if wifi_strength is not None:
+ self.wifi_strength_cache = wifi_strength # Cache the result
+ else:
+ wifi_strength = self.wifi_strength_cache # Use cached value if available
+
+ return self.wifi_signal_icon(wifi_strength)
+
+ def wifi_signal_icon(self, strength):
+ if strength is None or strength <= -100:
+ return "signal_wifi_0_bar"
+ if strength > -50:
+ return "signal_wifi_4_bar"
+ if strength > -60:
+ return "network_wifi_3_bar"
+ if strength > -70:
+ return "network_wifi_2_bar"
+ return "network_wifi_1_bar"
+
+ def check_wifi_strength(self):
+ try:
+ result = subprocess.run(["iwconfig"], capture_output=True, text=True)
+ for line in result.stdout.splitlines():
+ if "Signal level" in line:
+ signal_level = line.split("Signal level=")[1].split(" ")[0]
+ return int(signal_level.strip().replace("dBm", ""))
+ return None
+ except Exception:
+ return None
+
+ def is_wifi_connected(self):
+ return any(
+ self._is_interface_up(interface, ["wlan", "wifi"])
+ for interface in psutil.net_if_addrs()
+ )
+
+ def is_ethernet_connected(self):
+ return any(
+ self._is_interface_up(interface, ["enp", "eth"])
+ for interface in psutil.net_if_addrs()
+ )
+
+ def _is_interface_up(self, interface, keywords):
+ if any(substring in interface.lower() for substring in keywords):
+ return psutil.net_if_stats().get(interface, {}).isup
+ return False
diff --git a/modules/bar/components/powerprofile.py b/modules/bar/components/powerprofile.py
new file mode 100644
index 0000000..a1817cc
--- /dev/null
+++ b/modules/bar/components/powerprofile.py
@@ -0,0 +1,44 @@
+from fabric import Fabricator
+from fabric.utils import exec_shell_command
+from fabric.widgets.box import Box
+from snippets import MaterialIcon
+
+PROFILE_ICONS = {
+ "power-saver": "data_saver_on",
+ "balanced": None,
+ "performance": "mode_heat",
+}
+
+
+class PowerProfileIndicator(Box):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+
+ self.profile_icon = None
+
+ self.fabricator = Fabricator(interval=1000, poll_from=self.update_power_profile)
+
+ def update_power_profile(self, *_):
+ profile = self.get_power_profile()
+ self.update_icon(profile)
+ return True
+
+ def get_power_profile(self):
+ result = exec_shell_command("powerprofilesctl get")
+ return result.strip() or "power-saver"
+
+ def update_icon(self, profile):
+ icon_name = PROFILE_ICONS.get(profile)
+
+ new_icon = MaterialIcon(icon_name, 16) if icon_name else None
+
+ if self.profile_icon:
+ self.remove(self.profile_icon)
+
+ if new_icon:
+ self.profile_icon = new_icon
+ self.add(self.profile_icon)
+ else:
+ if self.profile_icon:
+ self.profile_icon.hide()
+ self.profile_icon = None
diff --git a/modules/bar/components/stats.py b/modules/bar/components/stats.py
new file mode 100644
index 0000000..6471e76
--- /dev/null
+++ b/modules/bar/components/stats.py
@@ -0,0 +1,94 @@
+from time import sleep
+import psutil
+from fabric import Fabricator
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.circularprogressbar import CircularProgressBar
+from fabric.widgets.label import Label
+from fabric.widgets.overlay import Overlay
+from snippets import MaterialIcon
+
+
+class SystemInfo(Button):
+ ICONS = [
+ ("CPU", "settings_motion_mode"),
+ ("Swap", "swap_horiz"),
+ ("RAM", "memory_alt"),
+ ("Temp", "thermometer"),
+ ]
+
+ def __init__(self):
+ super().__init__(child=self._initialize_content())
+
+ Fabricator(
+ poll_from=self._refresh_system_info,
+ stream=True,
+ on_changed=lambda fab, data: self._update_ui(data),
+ )
+
+ def _initialize_content(self):
+ self.box = Box(orientation="h", name="tray")
+ self.progress_bars = {}
+ self.labels = {}
+ self.icons = {}
+
+ for system, icon_name in self.ICONS:
+ self._create_system_item(system, icon_name)
+
+ return self.box
+
+ def _create_system_item(self, system, icon_name):
+ self.progress_bars[system] = self._create_progress_bar()
+ self.labels[system] = self._create_label()
+ self.icons[system] = self._create_icon(icon_name)
+
+ overlay = Overlay(
+ child=self.progress_bars[system], overlays=[self.icons[system]]
+ )
+ self.box.pack_start(overlay, False, False, 0)
+ self.box.pack_start(self.labels[system], False, False, 0)
+
+ def _create_progress_bar(self):
+ return CircularProgressBar(
+ name="progress", line_style="round", line_width=1, size=24
+ )
+
+ def _create_label(self):
+ return Label(style="font-size:14px; margin: 4px;")
+
+ def _create_icon(self, icon_name):
+ return MaterialIcon(icon_name, size=16)
+
+ def _refresh_system_info(self, fab: Fabricator):
+ while True:
+ yield {
+ "CPU": round(psutil.cpu_percent()),
+ "RAM": round(psutil.virtual_memory().percent),
+ "Swap": round(psutil.swap_memory().percent),
+ "Temp": self._get_device_temperature(),
+ }
+ sleep(1)
+
+ @staticmethod
+ def _get_device_temperature():
+ try:
+ temps = psutil.sensors_temperatures()
+ if "coretemp" in temps:
+ return round(temps["coretemp"][0].current, 1)
+ elif "cpu_thermal" in temps:
+ return round(temps["cpu_thermal"][0].current, 1)
+ return None
+ except Exception:
+ return None
+
+ def _update_ui(self, usages):
+ for system, usage in usages.items():
+ if usage is None:
+ usage = 0
+ self.labels[system].set_label("N/A")
+ else:
+ usage = int(usage)
+
+ self.progress_bars[system].value = usage / 100
+ self.labels[system].set_label(f"{usage}")
+ self.progress_bars[system].set_tooltip_text(f"{system} Usage: {usage}%")
diff --git a/modules/bar/components/taskbar.py b/modules/bar/components/taskbar.py
new file mode 100644
index 0000000..cc8af45
--- /dev/null
+++ b/modules/bar/components/taskbar.py
@@ -0,0 +1,154 @@
+import json
+import os
+from typing import TypedDict
+
+from fabric.hyprland.widgets import get_hyprland_connection
+from fabric.utils import exec_shell_command_async
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.image import Image
+from gi.repository import GdkPixbuf, GLib, Gtk
+from loguru import logger
+
+
+class PagerClient(TypedDict):
+ title: str
+ initialClass: str
+ mapped: bool
+ hidden: bool
+ address: str
+
+
+class TaskBar(Box):
+ def __init__(self, icon_size: int = 20, **kwargs):
+ super().__init__(
+ orientation="h",
+ spacing=7,
+ name="taskbar",
+ **kwargs,
+ )
+ self.connection = get_hyprland_connection()
+ self.icon_size = icon_size
+ self.icon_theme = Gtk.IconTheme.get_default()
+
+ self.set_visible(False)
+
+ if self.connection.ready:
+ self.render_with_delay()
+ else:
+ self.connection.connect("event::ready", lambda *_: self.render_with_delay())
+
+ for event in (
+ "activewindow",
+ "openwindow",
+ "closewindow",
+ "changefloatingmode",
+ ):
+ self.connection.connect("event::" + event, lambda *_: self.render(None))
+
+ def render_with_delay(self, *_):
+ GLib.timeout_add(101, self.render)
+
+ def render(self, *_):
+ self.children = []
+
+ clients = self.fetch_clients()
+ active_window_address = self.get_active_window_address()
+
+ visible_clients = [
+ client for client in clients if client["mapped"] and not client["hidden"]
+ ]
+
+ if visible_clients:
+ for client in visible_clients:
+ window_class = client["initialClass"].lower()
+ icon = self.bake_window_icon(window_class)
+
+ button = Button(image=icon, tooltip_text=client["title"])
+ if client["address"] == active_window_address:
+ button.add_style_class("activated")
+ button.connect(
+ "button-press-event",
+ self.on_icon_click,
+ client["address"],
+ )
+
+ self.add(button)
+ self.set_visible(True)
+ self.show_all()
+ else:
+ self.set_visible(False)
+
+ self.set_visible(len(self.children) > 0)
+ if self.children:
+ self.show_all()
+
+ def get_active_window_address(self) -> str:
+ active_window_info = json.loads(
+ self.connection.send_command("j/activewindow").reply.decode()
+ )
+ return active_window_info.get("address", "")
+
+ def on_icon_click(self, widget, event, address):
+ exec_shell_command_async(
+ f"hyprctl dispatch focuswindow address:{address}", lambda *_: None
+ )
+
+ def fetch_clients(self) -> list[PagerClient]:
+ return json.loads(self.connection.send_command("j/clients").reply.decode())
+
+ def bake_window_icon(
+ self,
+ window_class: str,
+ fallback_icon: str = "image-missing",
+ ) -> Image:
+ icon_name = self.get_icon_from_desktop_entry(window_class)
+
+ if icon_name:
+ pixbuf = self.load_icon(icon_name)
+ else:
+ pixbuf = self.load_icon(window_class, fallback_icon)
+
+ return Image(pixbuf=pixbuf, size=self.icon_size)
+
+ def get_icon_from_desktop_entry(self, window_class: str) -> str:
+ for data_dir in GLib.get_system_data_dirs():
+ applications_dir = os.path.join(data_dir, "applications")
+
+ if os.path.isdir(applications_dir):
+ for desktop_file in os.listdir(applications_dir):
+ if desktop_file.endswith(".desktop"):
+ file_path = os.path.join(applications_dir, desktop_file)
+ try:
+ with open(file_path) as f:
+ app_name = None
+ icon_name = None
+ for line in f:
+ if line.startswith("Name="):
+ app_name = line.split("=", 2)[1].strip().lower()
+ elif line.startswith("Icon=") and app_name:
+ icon_name = line.split("=", 2)[1].strip()
+ if window_class in app_name:
+ return icon_name
+ except Exception as e:
+ logger.error(f"Error reading {file_path}: {e}")
+ return None
+
+ def load_icon(
+ self,
+ icon_name: str,
+ fallback_icon: str = "image-missing",
+ ) -> GdkPixbuf.Pixbuf:
+ try:
+ pixbuf = self.icon_theme.load_icon(
+ icon_name,
+ self.icon_size,
+ Gtk.IconLookupFlags.FORCE_SIZE,
+ )
+ except Exception:
+ pixbuf = self.icon_theme.load_icon(
+ fallback_icon,
+ self.icon_size,
+ Gtk.IconLookupFlags.FORCE_SIZE,
+ )
+ return pixbuf
diff --git a/modules/bar/components/volume.py b/modules/bar/components/volume.py
new file mode 100644
index 0000000..0fed57c
--- /dev/null
+++ b/modules/bar/components/volume.py
@@ -0,0 +1,81 @@
+from fabric import Fabricator
+from fabric.utils import exec_shell_command
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from snippets import MaterialIcon
+from services import audio
+
+VOLUME_ICONS = {
+ "muted": "volume_off",
+ "low": "volume_mute",
+ "medium-low": "volume_down",
+ "medium-high": "volume_up",
+ "high": "volume_up",
+}
+
+
+class VolumeIndicator(Box):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+
+ self.audio_service = audio
+ self.volume_icon_button = self.create_volume_icon()
+
+ self.volume_icon_button.connect("button-press-event", self.on_button_press)
+ self.audio_service.connect("changed", self.update_volume_status)
+
+ Fabricator(interval=1000, poll_from=self.update_volume_status)
+ self.children = (self.volume_icon_button,)
+
+ def create_volume_icon(self):
+ icon = MaterialIcon(VOLUME_ICONS["muted"], size=16)
+ button = Button(child=icon)
+ button.icon_widget = icon
+ return button
+
+ def on_button_press(self, widget, event):
+ if event.button == 1:
+ self.toggle_mute()
+ elif event.button == 3:
+ self.open_audio_settings()
+
+ def toggle_mute(self):
+ current_stream = self.audio_service.speaker
+ if current_stream:
+ current_stream.muted = not current_stream.muted
+ # self.update_volume_status()
+
+ def open_audio_settings(self):
+ exec_shell_command("pavucontrol")
+
+ def update_volume_status(self, *_):
+ current_stream = self.audio_service.speaker
+ if current_stream:
+ self.update_icon(current_stream)
+
+ return True
+
+ def update_icon(self, stream):
+ if stream.muted:
+ icon_name = VOLUME_ICONS["muted"]
+ volume_percentage = 0
+ tooltip_text = "Volume Muted"
+ else:
+ volume_level = stream.volume
+ icon_name = self.get_volume_icon(volume_level)
+ volume_percentage = int(volume_level)
+ tooltip_text = f"Volume: {volume_percentage}%"
+
+ self.volume_icon_button.icon_widget.set_label(icon_name)
+
+ self.volume_icon_button.set_tooltip_text(tooltip_text)
+
+ def get_volume_icon(self, volume_level):
+ if volume_level == 0:
+ return VOLUME_ICONS["low"]
+ elif volume_level <= 33:
+ return VOLUME_ICONS["medium-low"]
+ elif volume_level <= 66:
+ return VOLUME_ICONS["medium-high"]
+ else:
+ return VOLUME_ICONS["high"]
diff --git a/modules/bar/components/workspace.py b/modules/bar/components/workspace.py
new file mode 100644
index 0000000..f13372d
--- /dev/null
+++ b/modules/bar/components/workspace.py
@@ -0,0 +1,19 @@
+import json
+
+from fabric.hyprland.service import Hyprland
+from fabric.widgets.label import Label
+
+connection = Hyprland()
+
+workspaceData = connection.send_command("j/activeworkspace").reply
+activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"]
+workspace = Label(label=f"Workspace {activeWorkspace}")
+
+
+def on_workspace(obj, signal):
+ global activeWorkspace
+ activeWorkspace = json.loads(signal.data[0])
+ workspace.set_label(f"Workspace {activeWorkspace}")
+
+
+connection.connect("event::workspace", on_workspace)
diff --git a/modules/corners.py b/modules/corners.py
new file mode 100644
index 0000000..10ce26d
--- /dev/null
+++ b/modules/corners.py
@@ -0,0 +1,64 @@
+from fabric.widgets.box import Box
+from fabric.widgets.wayland import WaylandWindow as Window
+from fabric.widgets.shapes import Corner
+
+
+class MyCorner(Box):
+ def __init__(self, corner):
+ super().__init__(
+ name="corner-container",
+ children=Corner(
+ name="corner",
+ orientation=corner,
+ size=20,
+ ),
+ )
+
+
+class Corners(Window):
+ def __init__(self):
+ super().__init__(
+ name="corners",
+ layer="top",
+ anchor="top bottom left right",
+ exclusivity="normal",
+ pass_through=True,
+ visible=False,
+ all_visible=False,
+ )
+
+ self.all_corners = Box(
+ name="all-corners",
+ orientation="v",
+ h_expand=True,
+ v_expand=True,
+ h_align="fill",
+ v_align="fill",
+ children=[
+ Box(
+ name="top-corners",
+ orientation="h",
+ h_align="fill",
+ children=[
+ MyCorner("top-left"),
+ Box(h_expand=True),
+ MyCorner("top-right"),
+ ],
+ ),
+ Box(v_expand=True),
+ Box(
+ name="bottom-corners",
+ orientation="h",
+ h_align="fill",
+ children=[
+ MyCorner("bottom-left"),
+ Box(h_expand=True),
+ MyCorner("bottom-right"),
+ ],
+ ),
+ ],
+ )
+
+ self.add(self.all_corners)
+
+ self.show_all()
diff --git a/modules/launcher/__pycache__/launcher.cpython-313.pyc b/modules/launcher/__pycache__/launcher.cpython-313.pyc
new file mode 100644
index 0000000..23b3668
Binary files /dev/null and b/modules/launcher/__pycache__/launcher.cpython-313.pyc differ
diff --git a/modules/launcher/components/__init__.py b/modules/launcher/components/__init__.py
new file mode 100644
index 0000000..24ba7fe
--- /dev/null
+++ b/modules/launcher/components/__init__.py
@@ -0,0 +1,9 @@
+from .applauncher import *
+from .bluetooth import *
+from .cliphist import *
+from .dashboard import *
+from .emoji import *
+from .power import *
+from .sh import *
+from .todo import *
+from .wallpapers import *
diff --git a/modules/launcher/components/__pycache__/__init__.cpython-313.pyc b/modules/launcher/components/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..1b2d266
Binary files /dev/null and b/modules/launcher/components/__pycache__/__init__.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/applauncher.cpython-313.pyc b/modules/launcher/components/__pycache__/applauncher.cpython-313.pyc
new file mode 100644
index 0000000..4d47aaa
Binary files /dev/null and b/modules/launcher/components/__pycache__/applauncher.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/bluetooth.cpython-313.pyc b/modules/launcher/components/__pycache__/bluetooth.cpython-313.pyc
new file mode 100644
index 0000000..6ffa4bd
Binary files /dev/null and b/modules/launcher/components/__pycache__/bluetooth.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/cliphist.cpython-313.pyc b/modules/launcher/components/__pycache__/cliphist.cpython-313.pyc
new file mode 100644
index 0000000..828765b
Binary files /dev/null and b/modules/launcher/components/__pycache__/cliphist.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/dashboard.cpython-313.pyc b/modules/launcher/components/__pycache__/dashboard.cpython-313.pyc
new file mode 100644
index 0000000..ba4f55c
Binary files /dev/null and b/modules/launcher/components/__pycache__/dashboard.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/emoji.cpython-313.pyc b/modules/launcher/components/__pycache__/emoji.cpython-313.pyc
new file mode 100644
index 0000000..b9282dc
Binary files /dev/null and b/modules/launcher/components/__pycache__/emoji.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/network.cpython-313.pyc b/modules/launcher/components/__pycache__/network.cpython-313.pyc
new file mode 100644
index 0000000..113557f
Binary files /dev/null and b/modules/launcher/components/__pycache__/network.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/power.cpython-313.pyc b/modules/launcher/components/__pycache__/power.cpython-313.pyc
new file mode 100644
index 0000000..e36f763
Binary files /dev/null and b/modules/launcher/components/__pycache__/power.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/sh.cpython-313.pyc b/modules/launcher/components/__pycache__/sh.cpython-313.pyc
new file mode 100644
index 0000000..1ed1902
Binary files /dev/null and b/modules/launcher/components/__pycache__/sh.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/todo.cpython-313.pyc b/modules/launcher/components/__pycache__/todo.cpython-313.pyc
new file mode 100644
index 0000000..8bfe708
Binary files /dev/null and b/modules/launcher/components/__pycache__/todo.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/wallpapers.cpython-313.pyc b/modules/launcher/components/__pycache__/wallpapers.cpython-313.pyc
new file mode 100644
index 0000000..1bc90dd
Binary files /dev/null and b/modules/launcher/components/__pycache__/wallpapers.cpython-313.pyc differ
diff --git a/modules/launcher/components/__pycache__/window_switcher.cpython-313.pyc b/modules/launcher/components/__pycache__/window_switcher.cpython-313.pyc
new file mode 100644
index 0000000..c461453
Binary files /dev/null and b/modules/launcher/components/__pycache__/window_switcher.cpython-313.pyc differ
diff --git a/modules/launcher/components/applauncher.py b/modules/launcher/components/applauncher.py
new file mode 100644
index 0000000..4e755ae
--- /dev/null
+++ b/modules/launcher/components/applauncher.py
@@ -0,0 +1,240 @@
+from collections.abc import Iterator
+import operator
+from fabric.utils import DesktopApp, get_desktop_applications, idle_add, remove_handler
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.label import Label
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from gi.repository import GLib, Gdk
+from snippets import read_config
+from fabric.widgets.image import Image
+
+
+class AppLauncher(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="app-launcher",
+ visible=False,
+ all_visible=False,
+ **kwargs,
+ )
+
+ self.launcher = kwargs["launcher"]
+ self.selected_index = -1
+
+ self._arranger_handler: int = 0
+ self._all_apps = get_desktop_applications()
+ self.config = read_config()
+
+ self.viewport = Box(name="viewport", spacing=4, orientation="v")
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()),
+ on_activate=lambda entry, *_: self.on_search_entry_activate(
+ entry.get_text()
+ ),
+ on_key_press_event=self.on_search_entry_key_press, # Handle key presses
+ )
+ self.scrolled_window = ScrolledWindow(
+ name="scrolled-window",
+ spacing=10,
+ h_scrollbar_policy="never",
+ v_scrollbar_policy="never",
+ child=self.viewport,
+ )
+
+ self.header_box = Box(
+ name="header_box",
+ orientation="h",
+ children=[self.search_entry],
+ )
+
+ self.launcher_box = Box(
+ name="launcher-box",
+ h_expand=True,
+ orientation="v",
+ children=[
+ self.header_box,
+ self.scrolled_window,
+ ],
+ )
+
+ self.resize_viewport()
+
+ self.add(self.launcher_box)
+ self.show_all()
+
+ def close_launcher(self, *_):
+ self.viewport.children = []
+ self.selected_index = -1 # Reset selection
+ self.launcher.close()
+
+ def open_launcher(self):
+ self._all_apps = get_desktop_applications()
+ self.arrange_viewport()
+ self.show_all()
+
+ def arrange_viewport(self, query: str = ""):
+ remove_handler(self._arranger_handler) if self._arranger_handler else None
+ self.viewport.children = []
+ self.selected_index = -1
+
+ if not query.strip():
+ return False
+
+ filtered_apps = iter(
+ sorted(
+ [
+ app
+ for app in self._all_apps
+ if query.casefold()
+ in (
+ (app.display_name or "")
+ + (" " + app.name + " ")
+ + (app.generic_name or "")
+ ).casefold()
+ ][:6],
+ key=lambda app: (app.display_name or "").casefold(),
+ )
+ )
+ should_resize = operator.length_hint(filtered_apps) == len(self._all_apps)
+
+ self._arranger_handler = idle_add(
+ lambda apps_iter: self.add_next_application(apps_iter)
+ or self.handle_arrange_complete(should_resize, query),
+ filtered_apps,
+ pin=True,
+ )
+
+ def handle_arrange_complete(self, should_resize, query):
+ if should_resize:
+ self.resize_viewport()
+ # Only auto-select first item if query exists
+ if query.strip() != "" and self.viewport.get_children():
+ self.update_selection(0)
+ return False
+
+ def add_next_application(self, apps_iter: Iterator[DesktopApp]):
+ if not (app := next(apps_iter, None)):
+ return False
+
+ self.viewport.add(self.bake_application_slot(app))
+ return True
+
+ def resize_viewport(self):
+ self.scrolled_window.set_min_content_width(
+ self.viewport.get_allocation().width # type: ignore
+ )
+ return False
+
+ def bake_application_slot(self, app: DesktopApp, **kwargs) -> Button:
+ button = Button(
+ name="launcher-app",
+ child=Box(
+ orientation="h",
+ children=[
+ Image(
+ pixbuf=app.get_icon_pixbuf(size=32),
+ h_align="start",
+ name="launcher-app-icon",
+ ),
+ Label(
+ label=app.display_name or "Unknown",
+ ellipsization="end",
+ v_align="center",
+ h_align="center",
+ ),
+ ],
+ ),
+ tooltip_text=app.description,
+ on_clicked=lambda *_: (app.launch(), self.close_launcher()),
+ **kwargs,
+ )
+ return button
+
+ def update_selection(self, new_index: int):
+ # Unselect current
+ if self.selected_index != -1 and self.selected_index < len(
+ self.viewport.get_children()
+ ):
+ current_button = self.viewport.get_children()[self.selected_index]
+ current_button.get_style_context().remove_class("selected")
+ # Select new
+ if new_index != -1 and new_index < len(self.viewport.get_children()):
+ new_button = self.viewport.get_children()[new_index]
+ new_button.get_style_context().add_class("selected")
+ self.selected_index = new_index
+ self.scroll_to_selected(new_button)
+ else:
+ self.selected_index = -1
+
+ def scroll_to_selected(self, button):
+ def scroll():
+ adj = self.scrolled_window.get_vadjustment()
+ alloc = button.get_allocation()
+ if alloc.height == 0:
+ return False # Retry if allocation isn't ready
+
+ y = alloc.y
+ height = alloc.height
+ page_size = adj.get_page_size()
+ current_value = adj.get_value()
+
+ # Calculate visible boundaries
+ visible_top = current_value
+ visible_bottom = current_value + page_size
+
+ if y < visible_top:
+ # Item above viewport - align to top
+ adj.set_value(y)
+ elif y + height > visible_bottom:
+ # Item below viewport - align to bottom
+ new_value = y + height - page_size
+ adj.set_value(new_value)
+ # No action if already fully visible
+ return False
+
+ GLib.idle_add(scroll)
+
+ def on_search_entry_activate(self, text):
+ commands = self.config.get("commands", {})
+
+ if text in commands:
+ command = commands[text]
+ eval(command, {"launcher": self.launcher}) # Dynamically execute command
+ else:
+ children = self.viewport.get_children()
+ if children:
+ # Only activate if we have selection or non-empty query
+ if text.strip() == "" and self.selected_index == -1:
+ return # Prevent accidental activation when empty
+ selected_index = self.selected_index if self.selected_index != -1 else 0
+ if 0 <= selected_index < len(children):
+ children[selected_index].clicked()
+
+ def on_search_entry_key_press(self, widget, event):
+ keyval = event.keyval
+ if keyval == Gdk.KEY_Down:
+ self.move_selection(1)
+ return True
+ elif keyval == Gdk.KEY_Up:
+ self.move_selection(-1)
+ return True
+ elif keyval == Gdk.KEY_Escape:
+ self.close_launcher()
+ return True
+ return False
+
+ def move_selection(self, delta: int):
+ children = self.viewport.get_children()
+ if not children:
+ return
+ # Allow starting selection from nothing when empty
+ if self.selected_index == -1 and delta == 1:
+ new_index = 0
+ else:
+ new_index = self.selected_index + delta
+ new_index = max(0, min(new_index, len(children) - 1))
+ self.update_selection(new_index)
diff --git a/modules/launcher/components/bluetooth.py b/modules/launcher/components/bluetooth.py
new file mode 100644
index 0000000..aa82591
--- /dev/null
+++ b/modules/launcher/components/bluetooth.py
@@ -0,0 +1,132 @@
+from fabric.widgets.box import Box
+from fabric.widgets.label import Label
+from fabric.widgets.image import Image
+from fabric.widgets.button import Button
+from fabric.widgets.centerbox import CenterBox
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from fabric.bluetooth import BluetoothClient, BluetoothDevice
+from snippets import MaterialIcon
+
+
+class BluetoothDeviceSlot(CenterBox):
+ def __init__(self, device: BluetoothDevice, **kwargs):
+ super().__init__(name="bluetooth-device", **kwargs)
+ self.device = device
+ self.device.connect("changed", self.on_changed)
+ self.device.connect(
+ "notify::closed", lambda *_: self.device.closed and self.destroy()
+ )
+
+ self.connection_icon = MaterialIcon("bluetooth_disabled", 12)
+ self.connect_button = Button(
+ name="bluetooth-connect",
+ label="Connect",
+ on_clicked=lambda *_: self.device.set_connecting(not self.device.connected),
+ )
+
+ self.start_children = [
+ Box(
+ spacing=8,
+ children=[
+ Image(icon_name=device.icon_name + "-symbolic", size=32),
+ Label(label=device.name),
+ self.connection_icon,
+ ],
+ )
+ ]
+ self.end_children = self.connect_button
+
+ self.device.emit("changed") # to update display status
+
+ def on_changed(self, *_):
+ self.connection_icon.set_label(
+ "bluetooth" if self.device.connected else "bluetooth_disabled"
+ )
+
+ if self.device.connecting:
+ self.connect_button.set_label(
+ "Connecting..." if not self.device.connecting else "Disconnecting..."
+ )
+ else:
+ self.connect_button.set_label(
+ "Connect" if not self.device.connected else "Disconnect"
+ )
+ return
+
+
+class BluetoothConnections(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="bluetooth",
+ spacing=8,
+ orientation="vertical",
+ **kwargs,
+ )
+
+ self.client = BluetoothClient(on_device_added=self.on_device_added)
+ self.toggle_icon = MaterialIcon("bluetooth_disabled")
+ self.scan_icon = MaterialIcon("stop")
+
+ self.scan_button = Button(
+ name="bluetooth-scan",
+ child=self.scan_icon,
+ tooltip_text="scan",
+ on_clicked=lambda *_: self.client.toggle_scan(),
+ )
+ self.toggle_button = Button(
+ name="bluetooth-toggle",
+ tooltip_text="bluetooth-toggle",
+ child=self.toggle_icon,
+ on_clicked=lambda *_: self.client.toggle_power(),
+ )
+
+ self.client.connect(
+ "notify::enabled",
+ lambda *_: self.toggle_icon.set_label(
+ "bluetooth" if self.client.enabled else "bluetooth_disabled"
+ ),
+ )
+ self.client.connect(
+ "notify::scanning",
+ lambda *_: self.scan_icon.set_label(
+ "stop" if self.client.scanning else "bluetooth_searching"
+ ),
+ )
+
+ self.paired_box = Box(spacing=2, orientation="vertical")
+ self.available_box = Box(spacing=2, orientation="vertical")
+
+ self.children = [
+ CenterBox(
+ name="bluetooth-header",
+ start_children=self.scan_button,
+ center_children=Label(name="bluetooth-text", label="Bluetooth Devices"),
+ end_children=self.toggle_button,
+ ),
+ Label(name="bluetooth-section", label="Paired"),
+ ScrolledWindow(
+ name="bluetooth-paired",
+ v_expand=True,
+ child=self.paired_box,
+ ),
+ Label(name="bluetooth-section", label="Available"),
+ ScrolledWindow(
+ name="bluetooth-paired",
+ v_expand=True,
+ child=self.available_box,
+ ),
+ ]
+
+ # to run notify closures thus display the status
+ # without having to wait until an actual change
+ self.client.notify("scanning")
+ self.client.notify("enabled")
+
+ def on_device_added(self, client: BluetoothClient, address: str):
+ if not (device := client.get_device(address)):
+ return
+ slot = BluetoothDeviceSlot(device)
+
+ if device.paired:
+ return self.paired_box.add(slot)
+ return self.available_box.add(slot)
diff --git a/modules/launcher/components/cliphist.py b/modules/launcher/components/cliphist.py
new file mode 100644
index 0000000..6ccf863
--- /dev/null
+++ b/modules/launcher/components/cliphist.py
@@ -0,0 +1,205 @@
+import os
+import subprocess
+from typing import List
+
+from fabric import Fabricator
+from fabric.utils import remove_handler
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.label import Label
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from gi.repository import GLib
+from snippets import MaterialIcon
+
+
+class Cliphist(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="cliphist-launcher",
+ all_visible=False,
+ visible=False,
+ **kwargs,
+ )
+
+ self._arranger_handler = 0
+ self.cliphist_manager = CliphistManager(self)
+ self.viewport = None
+ self.launcher = kwargs["launcher"]
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ on_activate=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ )
+
+ self.toggle_button = Button(
+ child=MaterialIcon("delete_forever"),
+ name="clear-launcher-button",
+ on_clicked=self.on_button_clicked,
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=10,
+ orientation="h",
+ children=[self.search_entry, self.toggle_button],
+ )
+
+ self.launcher_box = Box(
+ name="cliphist-launcher-box",
+ spacing=10,
+ orientation="v",
+ h_expand=True,
+ children=[self.header_box],
+ )
+
+ self.add(self.launcher_box)
+
+ def on_button_clicked(self, *_):
+ GLib.spawn_command_line_async("cliphist wipe")
+ self.cliphist_manager.update_cliphist_history()
+
+ def open_launcher(self):
+ if not self.viewport:
+ self.viewport = Box(name="viewport", spacing=4, orientation="v")
+ self.scrolled_window = ScrolledWindow(
+ name="cliphist-history",
+ spacing=10,
+ h_scrollbar_policy="never",
+ child=self.viewport,
+ )
+ self.launcher_box.add(self.scrolled_window)
+
+ self.viewport.children = []
+ self.cliphist_manager.arrange_viewport()
+
+ self.viewport.show()
+ self.search_entry.grab_focus()
+
+ def close_launcher(self):
+ self.launcher.close()
+
+ def handle_search_input(self, text: str):
+ self.cliphist_manager.arrange_viewport(text)
+
+
+class CliphistManager:
+ def __init__(self, launcher):
+ self.launcher = launcher
+ self.cliphist_history = []
+ self.wl_paste_watcher = Fabricator(
+ poll_from="wl-paste --watch echo", stream=True, interval=-1
+ )
+ self.wl_paste_watcher.connect(
+ "changed", lambda *_: self.update_cliphist_history()
+ )
+
+ def get_clip_history(self) -> List[dict]:
+ try:
+ result = subprocess.run(
+ ["cliphist", "list"], capture_output=True, text=True, check=True
+ )
+ return self._parse_clip_history(result.stdout)
+ except subprocess.CalledProcessError as e:
+ print(f"Error fetching cliphist history: {e}")
+ return []
+
+ def _parse_clip_history(self, output: str) -> List[dict]:
+ items = []
+ for line in output.splitlines():
+ if line.strip():
+ parts = line.strip().split(maxsplit=1)
+ if len(parts) == 2:
+ items.append({"id": parts[0], "content": parts[1]})
+ return items
+
+ def copy_clip(self, clip_id: str):
+ try:
+ decode_result = subprocess.run(
+ ["cliphist", "decode", clip_id], capture_output=True, check=True
+ )
+ subprocess.run(["wl-copy"], input=decode_result.stdout, check=True)
+ self.launcher.close_launcher()
+ except subprocess.CalledProcessError as e:
+ print(f"Error copying clip {clip_id}: {e}")
+
+ def save_image_file(self, clip_id: str) -> str:
+ output_file = f"/tmp/cliphist-{clip_id}.png"
+ os.makedirs("/tmp", exist_ok=True)
+
+ try:
+ decode_result = subprocess.run(
+ ["cliphist", "decode", clip_id], capture_output=True, check=True
+ )
+
+ with open(output_file, "wb") as f:
+ f.write(decode_result.stdout)
+
+ return output_file
+ except (subprocess.CalledProcessError, IOError) as e:
+ print(f"Error saving image file for clip {clip_id}: {e}")
+ return ""
+
+ def query_clips(self, query: str = "") -> List[dict]:
+ history = self.get_clip_history()
+
+ if not query.strip():
+ return history
+
+ return [item for item in history if query.lower() in item["content"].lower()]
+
+ def bake_clip_slot(self, item: dict) -> Button:
+ if "[[ binary data" in item["content"].lower():
+ return self._create_image_button(item)
+ return self._create_text_button(item)
+
+ def _create_image_button(self, item: dict) -> Button:
+ output_file = self.save_image_file(item["id"])
+ if output_file and os.path.exists(output_file):
+ button = Button(
+ h_align="start",
+ name="clip-img-item",
+ on_clicked=lambda _, clip_id=item["id"]: self.copy_clip(clip_id),
+ )
+
+ button.set_style(
+ f"background-image: url('{output_file}'); background-size: cover; background-position: center;"
+ )
+ return button
+
+ return None
+
+ def _create_text_button(self, item: dict) -> Button:
+ return Button(
+ child=Label(
+ label=item["content"][:55]
+ + ("..." if len(item["content"]) > 55 else ""),
+ h_expand=True,
+ v_align="center",
+ h_align="start",
+ ),
+ on_clicked=lambda _, clip_id=item["id"]: self.copy_clip(clip_id),
+ name="clip-item",
+ )
+
+ def update_cliphist_history(self):
+ self.cliphist_history = self.get_clip_history()
+ if self.launcher.viewport:
+ GLib.idle_add(self.arrange_viewport)
+
+ def arrange_viewport(self, query: str = ""):
+ if not self.launcher.viewport:
+ return
+
+ if self.launcher._arranger_handler:
+ remove_handler(self.launcher._arranger_handler)
+
+ self.launcher.viewport.children = []
+ filtered_clips = self.query_clips(query)
+
+ for clip in filtered_clips:
+ button = self.bake_clip_slot(clip)
+ if button:
+ self.launcher.viewport.add(button)
diff --git a/modules/launcher/components/custom_color_wallpapers (copy 2).py b/modules/launcher/components/custom_color_wallpapers (copy 2).py
new file mode 100644
index 0000000..25c717b
--- /dev/null
+++ b/modules/launcher/components/custom_color_wallpapers (copy 2).py
@@ -0,0 +1,357 @@
+import hashlib
+import json
+import os
+from PIL import Image
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from gi.repository import GdkPixbuf, GLib, Gtk, Gio
+from snippets import MaterialIcon
+from fabric.utils import exec_shell_command, get_relative_path
+import concurrent.futures
+from concurrent.futures import ThreadPoolExecutor
+from fabric.widgets.label import Label
+
+
+def is_valid_hex_color(value: str) -> bool:
+ """Validate if the string is a Hex color."""
+ return (
+ value.startswith("#")
+ and len(value) == 7
+ and all(c in "0123456789ABCDEFabcdef" for c in value[1:])
+ )
+
+
+def is_valid_hue(value: str) -> bool:
+ """Validate if the string is a numeric Hue value (0โ360)."""
+ return value.isnumeric() and 0 <= float(value) <= 360
+
+
+class WallpaperSelector(Box):
+ CACHE_DIR = os.path.expanduser("~/.cache/modus/wallpapers")
+ SETTINGS_FILE = os.path.expanduser("~/dotfiles/hypr/scripts/settings.json")
+ SCHEMES = {
+ "TonalSpot": "tonalSpot",
+ "Expressive": "expressive",
+ "FruitSalad": "fruitSalad",
+ "Monochrome": "monochrome",
+ "Rainbow": "rainbow",
+ "Vibrant": "vibrant",
+ "Neutral": "neutral",
+ "Fidelity": "fidelity",
+ "Content": "content",
+ }
+
+ def __init__(self, **kwargs):
+ super().__init__(name="wallpapers", spacing=4, orientation="v", **kwargs)
+ self.launcher = kwargs["launcher"]
+
+ self.wallpapers_dir = os.path.expanduser("~/Pictures/wallpapers")
+ os.makedirs(self.CACHE_DIR, exist_ok=True)
+
+ self.files = [f for f in os.listdir(self.wallpapers_dir) if self._is_image(f)]
+ self.thumbnails = []
+ self.thumbnail_queue = []
+ self.executor = ThreadPoolExecutor(max_workers=4) # Shared executor
+
+ self.viewport = Gtk.IconView()
+ self.viewport.set_model(Gtk.ListStore(GdkPixbuf.Pixbuf, str))
+ self.viewport.set_pixbuf_column(0)
+ self.viewport.set_text_column(1)
+ self.viewport.set_item_width(0)
+ self.viewport.connect("item-activated", self.on_wallpaper_selected)
+
+ self.scrolled_window = ScrolledWindow(
+ name="scrolled-window",
+ spacing=10,
+ h_expand=True,
+ v_expand=True,
+ child=self.viewport,
+ )
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()),
+ )
+
+ self.scheme_dropdown = Gtk.ComboBoxText()
+ self.scheme_dropdown.set_name("scheme-dropdown")
+ self.scheme_dropdown.set_tooltip_text("Select color scheme")
+
+ for display_name, scheme_id in sorted(self.SCHEMES.items()):
+ self.scheme_dropdown.append(scheme_id, display_name)
+
+ self.scheme_dropdown.set_active_id("tonalSpot")
+ self.scheme_dropdown.connect("changed", self.on_scheme_changed)
+
+ initial_icon = "light_mode" if not self.check_dark_mode_state() else "dark_mode"
+ self.toggle_button = Button(
+ child=MaterialIcon(initial_icon),
+ name="toggle-launcher-button",
+ on_clicked=self.toggle_dark_mode,
+ )
+ self.custom_color_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ )
+ self.custom_color_entry.connect("activate", self.on_custom_color_submitted)
+
+ self.custom_color_box = Box(
+ name="custom-color-box",
+ spacing=10,
+ orientation="h",
+ children=[
+ Label(label="Custom Color:"),
+ self.custom_color_entry,
+ ],
+ )
+
+ self.dropdown_box = Box(
+ name="dropdown-box",
+ orientation="h",
+ children=[
+ self.scheme_dropdown,
+ MaterialIcon("keyboard_arrow_down"),
+ ],
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=10,
+ orientation="h",
+ children=[
+ self.search_entry,
+ self.dropdown_box,
+ self.custom_color_box,
+ self.toggle_button,
+ ],
+ )
+
+ self.add(self.header_box)
+ self.add(self.scrolled_window)
+ self._start_thumbnail_thread()
+ self.setup_file_monitor()
+ self.show_all()
+
+ def setup_file_monitor(self):
+ gfile = Gio.File.new_for_path(self.wallpapers_dir)
+ self.file_monitor = gfile.monitor_directory(Gio.FileMonitorFlags.NONE, None)
+ self.file_monitor.connect("changed", self.on_directory_changed)
+
+ def on_directory_changed(self, monitor, file, other_file, event_type):
+ file_name = file.get_basename()
+ if event_type == Gio.FileMonitorEvent.DELETED:
+ if file_name in self.files:
+ self.files.remove(file_name)
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache {cache_path}: {e}")
+ self.thumbnails = [(p, n) for p, n in self.thumbnails if n != file_name]
+ GLib.idle_add(self.arrange_viewport, self.search_entry.get_text())
+ elif event_type == Gio.FileMonitorEvent.CREATED:
+ if self._is_image(file_name) and file_name not in self.files:
+ self.files.append(file_name)
+ self.files.sort()
+ self.executor.submit(self._process_file, file_name)
+ elif event_type == Gio.FileMonitorEvent.CHANGED:
+ if self._is_image(file_name) and file_name in self.files:
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache for changed file {file_name}: {e}")
+ self.executor.submit(self._process_file, file_name)
+
+ def close_selector(self):
+ self.launcher.close()
+
+ def arrange_viewport(self, query: str = ""):
+ self.viewport.get_model().clear()
+ filtered_thumbnails = [
+ (thumb, name)
+ for thumb, name in self.thumbnails
+ if query.casefold() in name.casefold()
+ ]
+
+ filtered_thumbnails.sort(key=lambda x: x[1].lower())
+
+ for pixbuf, file_name in filtered_thumbnails:
+ self.viewport.get_model().append([pixbuf, file_name])
+
+ def toggle_dark_mode(self, *_):
+ GLib.spawn_command_line_async(
+ f"bash {get_relative_path('../../../assets/scripts/dark-theme.sh --toggle')}"
+ )
+ icon_name = "dark_mode" if not self.check_dark_mode_state() else "light_mode"
+ if self.toggle_button.get_child():
+ self.toggle_button.remove(self.toggle_button.get_child())
+ self.toggle_button.add(MaterialIcon(icon_name))
+ self.toggle_button.show_all()
+
+ def check_dark_mode_state(self):
+ result = exec_shell_command(
+ "gsettings get org.gnome.desktop.interface color-scheme"
+ )
+ return result.strip().replace("'", "") == "prefer-dark"
+
+ def on_wallpaper_selected(self, iconview, path):
+ model = iconview.get_model()
+ file_name = model[path][1]
+ full_path = os.path.join(self.wallpapers_dir, file_name)
+ selected_scheme = self.scheme_dropdown.get_active_id()
+ home_dir = GLib.get_home_dir()
+ command = (
+ f"python -O {home_dir}/dotfiles/hypr/scripts/wallpaper.py -I {full_path}"
+ )
+ GLib.spawn_command_line_async(command)
+ self.update_scheme(selected_scheme)
+
+ def on_scheme_changed(self, combo):
+ scheme_id = combo.get_active_id()
+ display_name = next(
+ name for name, id in self.SCHEMES.items() if id == scheme_id
+ )
+ print(f"Color scheme selected: {display_name} ({scheme_id})")
+ self.update_scheme(scheme_id)
+
+ home_dir = GLib.get_home_dir()
+ color_generator = os.path.join(home_dir, "dotfiles/material-colors/generate.py")
+ try:
+ command = f'python -O {color_generator} -R --scheme "{scheme_id}"'
+ GLib.spawn_command_line_async(command)
+ print(f"Applied color scheme: {display_name}")
+ except Exception as e:
+ print(f"Failed to apply color scheme: {e}")
+
+ def update_scheme(self, scheme: str):
+ try:
+ with open(self.SETTINGS_FILE, "r") as f:
+ settings = json.loads(f.read())
+
+ settings["generation-scheme"] = scheme
+
+ with open(self.SETTINGS_FILE, "w") as f:
+ json.dump(settings, f, indent=2)
+ except Exception as error:
+ print(f"Failed to update generation-scheme in settings.json: {error}")
+
+ def _start_thumbnail_thread(self):
+ thread = GLib.Thread.new("thumbnail-loader", self._preload_thumbnails, None)
+
+ def _preload_thumbnails(self, _data):
+ futures = [
+ self.executor.submit(self._process_file, file_name)
+ for file_name in self.files
+ ]
+ concurrent.futures.wait(futures)
+ GLib.idle_add(self._process_batch)
+
+ def _process_file(self, file_name):
+ full_path = os.path.join(self.wallpapers_dir, file_name)
+ cache_path = self._get_cache_path(file_name)
+ if not os.path.exists(cache_path):
+ try:
+ with Image.open(full_path) as img:
+ img.thumbnail((96, 96), Image.Resampling.BILINEAR)
+ img.save(cache_path, "PNG")
+ except Exception as e:
+ print(f"Error processing {file_name}: {e}")
+ return
+ self.thumbnail_queue.append((cache_path, file_name))
+ GLib.idle_add(self._process_batch)
+
+ def _process_batch(self):
+ batch = self.thumbnail_queue[:10]
+ del self.thumbnail_queue[:10]
+ for cache_path, file_name in batch:
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(cache_path)
+ self.thumbnails.append((pixbuf, file_name))
+ self.viewport.get_model().append([pixbuf, file_name])
+ except Exception as e:
+ print(f"Error loading thumbnail {cache_path}: {e}")
+ if self.thumbnail_queue:
+ GLib.idle_add(self._process_batch)
+ return False
+
+ def _get_cache_path(self, file_name: str) -> str:
+ file_hash = hashlib.md5(file_name.encode("utf-8")).hexdigest()
+ return os.path.join(self.CACHE_DIR, f"{file_hash}.png")
+
+ @staticmethod
+ def _is_image(file_name: str) -> bool:
+ return file_name.lower().endswith(
+ (".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp")
+ )
+
+ def on_custom_color_submitted(self, entry: Entry):
+ """Handle color submission."""
+ color = entry.get_text().strip()
+ if is_valid_hex_color(color) or is_valid_hue(color):
+ color_value = (
+ color if is_valid_hex_color(color) else self.hue_to_hex(float(color))
+ )
+ print(f"Applying custom color: {color_value}")
+ self.update_custom_color(color_value)
+ else:
+ print("Invalid color input. Please use a valid Hex or Hue.")
+
+ def update_custom_color(self, color: str):
+ """Update the custom color in settings and regenerate theme."""
+ try:
+ with open(self.SETTINGS_FILE, "r") as f:
+ settings = json.loads(f.read())
+
+ settings["custom-color"] = color
+
+ with open(self.SETTINGS_FILE, "w") as f:
+ json.dump(settings, f, indent=2)
+
+ home_dir = GLib.get_home_dir()
+ color_generator = os.path.join(
+ home_dir, "dotfiles/material-colors/generate.py"
+ )
+ command = f'python -O {color_generator} --color "{color}"'
+ GLib.spawn_command_line_async(command)
+ print(f"Custom color applied: {color}")
+ except Exception as e:
+ print(f"Failed to update custom color: {e}")
+
+ @staticmethod
+ def hue_to_hex(hue: float) -> str:
+ """Convert Hue to Hex color."""
+ hue = hue / 360.0
+ rgb = WallpaperSelector.hls_to_rgb(hue, 0.5, 1.0)
+ return f"#{int(rgb[0] * 255):02X}{int(rgb[1] * 255):02X}{int(rgb[2] * 255):02X}"
+
+ @staticmethod
+ def hls_to_rgb(h: float, l: float, s: float) -> tuple:
+ """Convert HLS to RGB color."""
+ if s == 0:
+ return l, l, l
+
+ def hue2rgb(p, q, t):
+ if t < 0:
+ t += 1
+ if t > 1:
+ t -= 1
+ if t < 1 / 6:
+ return p + (q - p) * 6 * t
+ if t < 1 / 2:
+ return q
+ if t < 2 / 3:
+ return p + (q - p) * (2 / 3 - t) * 6
+ return p
+
+ q = l * (1 + s) if l < 0.5 else l + s - l * s
+ p = 2 * l - q
+ r = hue2rgb(p, q, h + 1 / 3)
+ g = hue2rgb(p, q, h)
+ b = hue2rgb(p, q, h - 1 / 3)
+ return r, g, b
diff --git a/modules/launcher/components/dashboard.py b/modules/launcher/components/dashboard.py
new file mode 100644
index 0000000..d266e0e
--- /dev/null
+++ b/modules/launcher/components/dashboard.py
@@ -0,0 +1,242 @@
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.label import Label
+from snippets import MaterialIcon
+
+
+class Buttons(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="buttons",
+ spacing=4,
+ h_align="center",
+ v_align="start",
+ h_expand=True,
+ v_expand=True,
+ visible=True,
+ all_visible=True,
+ )
+
+ self.network_status_button = Button(
+ name="network-status-button",
+ h_expand=True,
+ child=Box(
+ h_align="start",
+ v_align="center",
+ spacing=10,
+ children=[
+ MaterialIcon("wifi"),
+ Box(
+ name="network-text",
+ orientation="v",
+ h_align="start",
+ v_align="center",
+ children=[
+ Box(
+ children=[
+ Label(
+ name="network-label",
+ label="Wi-Fi",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ Box(
+ children=[
+ Label(
+ name="network-ssid",
+ label="ARGOS_5GHz",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+
+ self.network_menu_button = Button(
+ name="network-menu-button",
+ child=MaterialIcon("chevron_right"),
+ )
+
+ self.network_button = Box(
+ name="network-button",
+ orientation="h",
+ h_align="fill",
+ v_align="center",
+ h_expand=True,
+ v_expand=True,
+ children=[
+ self.network_status_button,
+ self.network_menu_button,
+ ],
+ )
+
+ self.bluetooth_status_button = Button(
+ name="bluetooth-status-button",
+ h_expand=True,
+ child=Box(
+ h_align="start",
+ v_align="center",
+ spacing=10,
+ children=[
+ MaterialIcon("bluetooth"),
+ Box(
+ name="bluetooth-text",
+ orientation="v",
+ h_align="start",
+ v_align="center",
+ children=[
+ Box(
+ children=[
+ Label(
+ name="bluetooth-label",
+ label="Bluetooth",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ Box(
+ children=[
+ Label(
+ name="bluetooth-status",
+ label="Connected",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+
+ self.bluetooth_menu_button = Button(
+ name="bluetooth-menu-button",
+ child=MaterialIcon("chevron_right"),
+ )
+
+ self.bluetooth_button = Box(
+ name="bluetooth-button",
+ orientation="h",
+ h_align="fill",
+ v_align="center",
+ h_expand=True,
+ v_expand=True,
+ children=[
+ self.bluetooth_status_button,
+ self.bluetooth_menu_button,
+ ],
+ )
+
+ self.night_mode_button = Button(
+ name="night-mode-button",
+ child=Box(
+ h_align="start",
+ v_align="center",
+ spacing=10,
+ children=[
+ MaterialIcon("nightlight"),
+ Box(
+ name="night-mode-text",
+ orientation="v",
+ h_align="start",
+ v_align="center",
+ children=[
+ Box(
+ children=[
+ Label(
+ name="night-mode-label",
+ label="Night Mode",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ Box(
+ children=[
+ Label(
+ name="night-mode-status",
+ label="Enabled",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+
+ self.caffeine_button = Button(
+ name="caffeine-button",
+ child=Box(
+ h_align="start",
+ v_align="center",
+ spacing=10,
+ children=[
+ MaterialIcon("coffee"),
+ Box(
+ name="caffeine-text",
+ orientation="v",
+ h_align="start",
+ v_align="center",
+ children=[
+ Box(
+ children=[
+ Label(
+ name="caffeine-label",
+ label="Caffeine",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ Box(
+ children=[
+ Label(
+ name="caffeine-status",
+ label="Enabled",
+ justification="left",
+ ),
+ Box(h_expand=True),
+ ]
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+
+ self.add(self.network_button)
+ self.add(self.bluetooth_button)
+ self.add(self.night_mode_button)
+ self.add(self.caffeine_button)
+
+ self.show_all()
+
+
+class Dashboard(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="dashboard",
+ h_align="center",
+ v_align="start",
+ h_expand=True,
+ v_expand=True,
+ visible=True,
+ all_visible=True,
+ )
+
+ self.buttons = Buttons()
+
+ self.add(self.buttons)
+
+ self.show_all()
diff --git a/modules/launcher/components/emoji.py b/modules/launcher/components/emoji.py
new file mode 100644
index 0000000..731c108
--- /dev/null
+++ b/modules/launcher/components/emoji.py
@@ -0,0 +1,133 @@
+import subprocess
+from typing import Generator, List
+
+import ijson
+from fabric.utils import remove_handler, get_relative_path
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.label import Label
+from fabric.widgets.scrolledwindow import ScrolledWindow
+
+
+class Emoji(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="emoji-launcher",
+ all_visible=False,
+ visible=False,
+ **kwargs,
+ )
+
+ self.launcher = kwargs["launcher"]
+ self._arranger_handler: int = 0
+ self.emoji_manager = EmojiManager(self)
+ self.viewport = None
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ on_activate=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=10,
+ orientation="h",
+ children=[
+ self.search_entry,
+ ],
+ )
+
+ self.launcher_box = Box(
+ spacing=10,
+ orientation="v",
+ h_expand=True,
+ children=[self.header_box],
+ )
+
+ self.add(self.launcher_box)
+
+ def open_launcher(self):
+ if not self.viewport:
+ self.viewport = Box(name="viewport", spacing=4, orientation="v")
+ self.scrolled_window = ScrolledWindow(
+ name="scrolled-window",
+ spacing=10,
+ h_scrollbar_policy="never",
+ v_scrollbar_policy="never",
+ child=self.viewport,
+ )
+ self.launcher_box.add(self.scrolled_window)
+
+ self.viewport.children = []
+ self.emoji_manager.arrange_viewport()
+
+ self.viewport.show()
+ self.search_entry.grab_focus()
+
+ def close_launcher(self):
+ self.launcher.close()
+
+ def handle_search_input(self, text: str):
+ self.emoji_manager.arrange_viewport(text)
+
+
+class EmojiManager:
+ def __init__(self, launcher):
+ self.launcher = launcher
+ self.emoji_file_path = get_relative_path("../../../config/assets/emoji.json")
+
+ def load_emojis(self) -> Generator[tuple, None, None]:
+ try:
+ with open(self.emoji_file_path, "r") as file:
+ for emoji_str, item in ijson.kvitems(file, ""):
+ yield emoji_str, item["name"], item["slug"], item["group"]
+ except (ijson.JSONError, KeyError, OSError) as e:
+ print(f"Error loading emojis: {e}")
+ return
+
+ def query_emojis(self, query: str) -> List[tuple]:
+ query = query.lower()
+ return [
+ (emoji_str, name, slug, group)
+ for emoji_str, name, slug, group in self.load_emojis()
+ if query in name.lower() or query in slug.lower() or query in group.lower()
+ ][:48]
+
+ def copy_emoji(self, emoji: tuple):
+ subprocess.run(["wl-copy"], input=emoji[0].encode(), check=True)
+ self.launcher.close_launcher()
+
+ def bake_emoji_slot(self, emoji: tuple, **kwargs) -> Button:
+ return Button(
+ name="emoji-item",
+ child=Label(label=emoji[0], h_align="center"),
+ tooltip_text=emoji[1],
+ on_clicked=lambda *_: self.copy_emoji(emoji),
+ **kwargs,
+ )
+
+ def arrange_viewport(self, query: str = ""):
+ if not self.launcher.viewport:
+ return
+
+ (
+ remove_handler(self.launcher._arranger_handler)
+ if self.launcher._arranger_handler
+ else None
+ )
+ self.launcher.viewport.children = []
+
+ filtered_emojis = self.query_emojis(query)
+
+ row = Box(name="emoji-row", spacing=10, orientation="h")
+ for emoji in filtered_emojis:
+ row.add(self.bake_emoji_slot(emoji))
+ if len(row.children) >= 12:
+ self.launcher.viewport.add(row)
+ row = Box(name="emoji-row", spacing=10, orientation="h")
+
+ if row.children:
+ self.launcher.viewport.add(row)
diff --git a/modules/launcher/components/power.py b/modules/launcher/components/power.py
new file mode 100644
index 0000000..e00efa1
--- /dev/null
+++ b/modules/launcher/components/power.py
@@ -0,0 +1,88 @@
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from gi.repository import GLib
+
+from snippets import MaterialIcon
+
+
+class PowerMenu(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="powermenu",
+ orientation="h",
+ spacing=10,
+ v_align="center",
+ h_align="center",
+ v_expand=True,
+ h_expand=True,
+ visible=True,
+ **kwargs,
+ )
+
+ self.launcher = kwargs["launcher"]
+
+ self.btn_lock = Button(
+ name="powermenu-button",
+ child=MaterialIcon("lock", 45),
+ on_clicked=self.lock,
+ )
+
+ self.btn_suspend = Button(
+ name="powermenu-button",
+ child=MaterialIcon("sleep", 45),
+ on_clicked=self.suspend,
+ )
+
+ self.btn_logout = Button(
+ name="powermenu-button",
+ child=MaterialIcon("logout", 45),
+ on_clicked=self.logout,
+ )
+
+ self.btn_reboot = Button(
+ name="powermenu-button",
+ child=MaterialIcon("restart_alt", 45),
+ on_clicked=self.reboot,
+ )
+
+ self.btn_shutdown = Button(
+ name="powermenu-button",
+ child=MaterialIcon("power_settings_new", 45),
+ on_clicked=self.poweroff,
+ )
+
+ self.buttons = [
+ self.btn_lock,
+ self.btn_suspend,
+ self.btn_logout,
+ self.btn_reboot,
+ self.btn_shutdown,
+ ]
+
+ for button in self.buttons:
+ self.add(button)
+
+ self.show_all()
+
+ def close_menu(self):
+ self.launcher.close()
+
+ def lock(self, *_):
+ GLib.spawn_command_line_async("hyprlock --immediate")
+ self.close_menu()
+
+ def suspend(self, *_):
+ GLib.spawn_command_line_async("systemctl suspend")
+ self.close_menu()
+
+ def logout(self, *_):
+ GLib.spawn_command_line_async("hyprctl dispatch exit")
+ self.close_menu()
+
+ def reboot(self, *_):
+ GLib.spawn_command_line_async("systemctl reboot")
+ self.close_menu()
+
+ def poweroff(self, *_):
+ GLib.spawn_command_line_async("systemctl poweroff")
+ self.close_menu()
diff --git a/modules/launcher/components/sh.py b/modules/launcher/components/sh.py
new file mode 100644
index 0000000..5992ec8
--- /dev/null
+++ b/modules/launcher/components/sh.py
@@ -0,0 +1,138 @@
+import os
+import subprocess
+from typing import List
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.label import Label
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from snippets import MaterialIcon
+
+CACHE_DIR = os.getenv(
+ "XDG_CACHE_HOME", os.path.join(os.path.expanduser("~"), ".cache", "fabric")
+)
+BINS = os.path.join(CACHE_DIR, "binaries")
+
+
+class Sh(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ all_visible=False,
+ visible=False,
+ **kwargs,
+ )
+
+ self.launcher = kwargs["launcher"]
+ self._arranger_handler: int = 0
+ self.shell_command_manager = ShellCommandManager(self)
+ self.viewport = None
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ on_activate=lambda entry, *_: self.handle_search_input(entry.get_text()),
+ )
+
+ self.header_box = Box(
+ spacing=10,
+ orientation="h",
+ children=[self.search_entry, MaterialIcon("terminal")],
+ )
+
+ self.launcher_box = Box(
+ spacing=10,
+ orientation="v",
+ h_expand=True,
+ children=[self.header_box],
+ )
+
+ self.add(self.launcher_box)
+
+ def open_launcher(self):
+ if not self.viewport:
+ self.viewport = Box(name="viewport", spacing=10, orientation="v")
+ self.scrolled_window = ScrolledWindow(
+ spacing=10,
+ h_scrollbar_policy="never",
+ v_scrollbar_policy="never",
+ child=self.viewport,
+ )
+ self.launcher_box.add(self.scrolled_window)
+
+ self.viewport.children = []
+ self.shell_command_manager.show_shell_commands(self.viewport, "")
+
+ self.viewport.show()
+ self.search_entry.grab_focus()
+
+ def handle_search_input(self, text: str):
+ self.shell_command_manager.show_shell_commands(self.viewport, text)
+
+
+class ShellCommandManager:
+ def __init__(self, launcher):
+ self.launcher = launcher
+ self.binaries = set()
+ self.reload_binaries()
+
+ def reload_binaries(self):
+ paths = os.getenv("PATH", "").split(":")
+ self.binaries = set()
+
+ for path in paths:
+ self.binaries.update(self.list_binaries_in_path(path))
+
+ with open(BINS, "w") as f:
+ f.write("\n".join(self.binaries))
+
+ def list_binaries_in_path(self, path):
+ if not os.path.exists(path):
+ return []
+ try:
+ return [
+ entry
+ for entry in os.listdir(path)
+ if os.access(os.path.join(path, entry), os.X_OK)
+ ]
+ except OSError:
+ return []
+
+ def show_shell_commands(self, viewport, search_query: str):
+ if not search_query:
+ return
+
+ viewport.children = []
+
+ results = self.query_binaries(search_query)
+ self.display_results(viewport, results)
+
+ def query_binaries(self, filter_str: str) -> List[str]:
+ filter_str = filter_str.lower()
+ filtered_bins = (cmd for cmd in self.binaries if filter_str in cmd)
+ return list(dict.fromkeys(filtered_bins))[:16]
+
+ def display_results(self, viewport, results: List[str]):
+ for command in results:
+ button = Button(
+ child=Label(
+ label=command,
+ v_align="center",
+ h_align="start",
+ ),
+ on_clicked=lambda _, cmd=command: self.execute_command(cmd),
+ name="sh-item",
+ )
+ viewport.add(button)
+
+ def close_menu(self):
+ self.launcher.close()
+
+ def execute_command(self, cmd: str):
+ try:
+ output = subprocess.check_output(cmd, shell=True, text=True)
+ print(output)
+ except subprocess.CalledProcessError as e:
+ print(e.output)
+ finally:
+ self.close_menu()
diff --git a/modules/launcher/components/todo.py b/modules/launcher/components/todo.py
new file mode 100644
index 0000000..7cc569b
--- /dev/null
+++ b/modules/launcher/components/todo.py
@@ -0,0 +1,168 @@
+import json
+import os
+
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.label import Label
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from snippets import MaterialIcon
+
+
+class TodoManager(Box):
+ def __init__(self, **kwargs):
+ super().__init__(
+ name="todo-launcher",
+ all_visible=False,
+ visible=False,
+ **kwargs,
+ )
+
+ self._arranger_handler = 0
+ self.todo_manager = TodoListManager(self)
+ self.viewport = None
+
+ self.todo_entry = Entry(
+ name="todo-entry",
+ h_expand=True,
+ on_activate=lambda entry, *_: self.handle_add_todo(entry.get_text()),
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=10,
+ orientation="h",
+ children=[
+ self.todo_entry,
+ Button(
+ name="add-button",
+ child=MaterialIcon("add"),
+ tooltip_text="Add Todo",
+ on_clicked=lambda *_: self.handle_add_todo(
+ self.todo_entry.get_text()
+ ),
+ ),
+ ],
+ )
+
+ self.launcher_box = Box(
+ name="todo-launcher-box",
+ spacing=10,
+ orientation="v",
+ h_expand=True,
+ children=[self.header_box],
+ )
+
+ self.add(self.launcher_box)
+
+ def open_launcher(self):
+ if not self.viewport:
+ self.viewport = Box(name="viewport", spacing=4, orientation="v")
+ self.scrolled_window = ScrolledWindow(
+ name="todo-content",
+ spacing=10,
+ h_scrollbar_policy="never",
+ child=self.viewport,
+ )
+ self.launcher_box.add(self.scrolled_window)
+
+ self.viewport.children = []
+ self.todo_manager.arrange_viewport()
+
+ self.viewport.show()
+ self.todo_entry.grab_focus()
+
+ def handle_add_todo(self, text: str):
+ if text.strip():
+ self.todo_manager.add_todo(text)
+ self.todo_entry.set_text("")
+
+
+class TodoListManager:
+ def __init__(self, launcher):
+ self.launcher = launcher
+ self.todos = []
+ self.todo_file = os.path.expanduser("~/.local/share/fabric/todos.json")
+ self.load_todos()
+
+ def load_todos(self):
+ os.makedirs(os.path.dirname(self.todo_file), exist_ok=True)
+ try:
+ if os.path.exists(self.todo_file):
+ with open(self.todo_file, "r") as f:
+ self.todos = json.load(f)
+ except Exception as e:
+ print(f"Error loading todos: {e}")
+ self.todos = []
+
+ def save_todos(self):
+ try:
+ with open(self.todo_file, "w") as f:
+ json.dump(self.todos, f)
+ except Exception as e:
+ print(f"Error saving todos: {e}")
+
+ def add_todo(self, content: str):
+ todo = {"content": content, "completed": False, "id": len(self.todos)}
+ self.todos.append(todo)
+ self.save_todos()
+ self.arrange_viewport()
+
+ def toggle_todo(self, todo_id: int):
+ for todo in self.todos:
+ if todo["id"] == todo_id:
+ todo["completed"] = not todo["completed"]
+ break
+ self.save_todos()
+ self.arrange_viewport()
+
+ def delete_todo(self, todo_id: int):
+ self.todos = [todo for todo in self.todos if todo["id"] != todo_id]
+ self.save_todos()
+ self.arrange_viewport()
+
+ def bake_todo_slot(self, todo: dict) -> Box:
+ todo_box = Box(
+ name="todo-item",
+ spacing=10,
+ orientation="h",
+ h_expand=True,
+ )
+
+ checkbox = Button(
+ name="todo-checkbox",
+ child=MaterialIcon(
+ "check_box" if todo["completed"] else "check_box_outline_blank"
+ ),
+ on_clicked=lambda _, todo_id=todo["id"]: self.toggle_todo(todo_id),
+ )
+
+ label = Label(
+ label=todo["content"],
+ h_expand=True,
+ v_align="center",
+ h_align="start",
+ name="todo-label-completed" if todo["completed"] else "todo-label",
+ )
+
+ delete_button = Button(
+ name="delete-button",
+ child=MaterialIcon("delete"),
+ on_clicked=lambda _, todo_id=todo["id"]: self.delete_todo(todo_id),
+ )
+
+ todo_box.add(checkbox)
+ todo_box.add(label)
+ todo_box.add(delete_button)
+
+ return todo_box
+
+ def arrange_viewport(self):
+ if not self.launcher.viewport:
+ return
+
+ self.launcher.viewport.children = []
+
+ for todo in self.todos:
+ todo_slot = self.bake_todo_slot(todo)
+ self.launcher.viewport.add(todo_slot)
diff --git a/modules/launcher/components/wallpapers (copy 1).py b/modules/launcher/components/wallpapers (copy 1).py
new file mode 100644
index 0000000..f54c565
--- /dev/null
+++ b/modules/launcher/components/wallpapers (copy 1).py
@@ -0,0 +1,379 @@
+import hashlib
+import json
+import os
+from PIL import Image
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from gi.repository import GdkPixbuf, GLib, Gtk, Gio, Gdk
+from snippets import MaterialIcon
+from fabric.utils import exec_shell_command, get_relative_path
+import concurrent.futures
+from concurrent.futures import ThreadPoolExecutor
+from fabric.widgets.label import Label
+
+
+def is_valid_hex_color(value: str) -> bool:
+ """Validate if the string is a Hex color."""
+ return (
+ value.startswith("#")
+ and len(value) == 7
+ and all(c in "0123456789ABCDEFabcdef" for c in value[1:])
+ )
+
+
+def is_valid_hue(value: str) -> bool:
+ """Validate if the string is a numeric Hue value (0โ360)."""
+ return value.isnumeric() and 0 <= float(value) <= 360
+
+
+class WallpaperSelector(Box):
+ CACHE_DIR = os.path.expanduser("~/.cache/fabric/wallpapers")
+ SETTINGS_FILE = os.path.expanduser("~/dotfiles/hypr/scripts/.settings.json")
+
+ SCHEMES = {
+ "TonalSpot": "tonalSpot",
+ "Expressive": "expressive",
+ "FruitSalad": "fruitSalad",
+ "Monochrome": "monochrome",
+ "Rainbow": "rainbow",
+ "Vibrant": "vibrant",
+ "Neutral": "neutral",
+ "Fidelity": "fidelity",
+ "Content": "content",
+ }
+
+ def __init__(self, **kwargs):
+ super().__init__(name="wallpapers", spacing=5, orientation="v", **kwargs)
+ self.launcher = kwargs["launcher"]
+
+ self.wallpapers_dir = os.path.expanduser("~/Pictures/wallpapers")
+ os.makedirs(self.CACHE_DIR, exist_ok=True)
+
+ self.files = [f for f in os.listdir(self.wallpapers_dir) if self._is_image(f)]
+ self.thumbnails = []
+ self.thumbnail_queue = []
+ self.executor = ThreadPoolExecutor(max_workers=5) # Shared executor
+
+ self.viewport = Gtk.IconView()
+ self.viewport.set_model(Gtk.ListStore(GdkPixbuf.Pixbuf, str))
+ self.viewport.set_pixbuf_column(1)
+ self.viewport.set_text_column(2)
+ self.viewport.set_item_width(1)
+ self.viewport.connect("item-activated", self.on_wallpaper_selected)
+
+ self.scrolled_window = ScrolledWindow(
+ name="scrolled-window",
+ spacing=11,
+ h_expand=True,
+ v_expand=True,
+ child=self.viewport,
+ )
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()),
+ )
+
+ self.scheme_dropdown = Gtk.ComboBoxText()
+ self.scheme_dropdown.set_name("scheme-dropdown")
+ self.scheme_dropdown.set_tooltip_text("Select color scheme")
+
+ for display_name, scheme_id in sorted(self.SCHEMES.items()):
+ self.scheme_dropdown.append(scheme_id, display_name)
+
+ self.scheme_dropdown.set_active_id("tonalSpot")
+ self.scheme_dropdown.connect("changed", self.on_scheme_changed)
+
+ initial_icon = "light_mode" if not self.check_dark_mode_state() else "dark_mode"
+ self.toggle_button = Button(
+ child=MaterialIcon(initial_icon),
+ name="toggle-launcher-button",
+ on_clicked=self.toggle_dark_mode,
+ )
+
+ self.dropdown_box = Box(
+ name="dropdown-box",
+ orientation="h",
+ children=[
+ self.scheme_dropdown,
+ MaterialIcon("keyboard_arrow_down"),
+ ],
+ )
+ self.custom_color_entry = Entry(
+ name="custom-color-entry",
+ h_expand=True,
+ # notify_text=self.on_custom_color_changed,
+ )
+ self.custom_color_entry.connect("activate", self.on_custom_color_submitted)
+
+ self.color_preview = Box(
+ name="color-preview",
+ )
+ self.custom_color_box = Box(
+ name="custom-color-box",
+ spacing=10,
+ orientation="h",
+ children=[
+ Label(label="Custom Color:", xalign=0),
+ self.custom_color_entry,
+ self.color_preview,
+ ],
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=11,
+ orientation="h",
+ children=[
+ self.search_entry,
+ self.dropdown_box,
+ self.custom_color_box,
+ self.toggle_button,
+ ],
+ )
+
+ self.add(self.header_box)
+ self.add(self.scrolled_window)
+ self._start_thumbnail_thread()
+ self.setup_file_monitor()
+ self.show_all()
+
+ def setup_file_monitor(self):
+ gfile = Gio.File.new_for_path(self.wallpapers_dir)
+ self.file_monitor = gfile.monitor_directory(Gio.FileMonitorFlags.NONE, None)
+ self.file_monitor.connect("changed", self.on_directory_changed)
+
+ def on_directory_changed(self, monitor, file, other_file, event_type):
+ file_name = file.get_basename()
+ if event_type == Gio.FileMonitorEvent.DELETED:
+ if file_name in self.files:
+ self.files.remove(file_name)
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache {cache_path}: {e}")
+ self.thumbnails = [(p, n) for p, n in self.thumbnails if n != file_name]
+ GLib.idle_add(self.arrange_viewport, self.search_entry.get_text())
+ elif event_type == Gio.FileMonitorEvent.CREATED:
+ if self._is_image(file_name) and file_name not in self.files:
+ self.files.append(file_name)
+ self.files.sort()
+ self.executor.submit(self._process_file, file_name)
+ elif event_type == Gio.FileMonitorEvent.CHANGED:
+ if self._is_image(file_name) and file_name in self.files:
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache for changed file {file_name}: {e}")
+ self.executor.submit(self._process_file, file_name)
+
+ def close_selector(self):
+ self.launcher.close()
+
+ def arrange_viewport(self, query: str = ""):
+ self.viewport.get_model().clear()
+ filtered_thumbnails = [
+ (thumb, name)
+ for thumb, name in self.thumbnails
+ if query.casefold() in name.casefold()
+ ]
+
+ filtered_thumbnails.sort(key=lambda x: x[2].lower())
+
+ for pixbuf, file_name in filtered_thumbnails:
+ self.viewport.get_model().append([pixbuf, file_name])
+
+ def toggle_dark_mode(self, *_):
+ GLib.spawn_command_line_async(
+ f"bash {get_relative_path('../../../assets/scripts/dark-theme.sh --toggle')}"
+ )
+ icon_name = "dark_mode" if not self.check_dark_mode_state() else "light_mode"
+ if self.toggle_button.get_child():
+ self.toggle_button.remove(self.toggle_button.get_child())
+ self.toggle_button.add(MaterialIcon(icon_name))
+ self.toggle_button.show_all()
+
+ def check_dark_mode_state(self):
+ result = exec_shell_command(
+ "gsettings get org.gnome.desktop.interface color-scheme"
+ )
+ return result.strip().replace("'", "") == "prefer-dark"
+
+ def on_wallpaper_selected(self, iconview, path):
+ model = iconview.get_model()
+ file_name = model[path][2]
+ full_path = os.path.join(self.wallpapers_dir, file_name)
+ selected_scheme = self.scheme_dropdown.get_active_id()
+ home_dir = GLib.get_home_dir()
+ command = (
+ f"python -O {home_dir}/dotfiles/hypr/scripts/wallpaper.py -I {full_path}"
+ )
+ GLib.spawn_command_line_async(command)
+ self.update_scheme(selected_scheme)
+
+ def on_scheme_changed(self, combo):
+ scheme_id = combo.get_active_id()
+ display_name = next(
+ name for name, id in self.SCHEMES.items() if id == scheme_id
+ )
+ print(f"Color scheme selected: {display_name} ({scheme_id})")
+ self.update_scheme(scheme_id)
+
+ home_dir = GLib.get_home_dir()
+ color_generator = os.path.join(home_dir, "dotfiles/material-colors/generate.py")
+ try:
+ command = f'python -O {color_generator} -R --scheme "{scheme_id}"'
+ GLib.spawn_command_line_async(command)
+ print(f"Applied color scheme: {display_name}")
+ except Exception as e:
+ print(f"Failed to apply color scheme: {e}")
+
+ def update_scheme(self, scheme: str):
+ try:
+ with open(self.SETTINGS_FILE, "r") as f:
+ settings = json.loads(f.read())
+
+ settings["generation-scheme"] = scheme
+
+ with open(self.SETTINGS_FILE, "w") as f:
+ json.dump(settings, f, indent=3)
+ except Exception as error:
+ print(f"Failed to update generation-scheme in settings.json: {error}")
+
+ def _start_thumbnail_thread(self):
+ thread = GLib.Thread.new("thumbnail-loader", self._preload_thumbnails, None)
+
+ def _preload_thumbnails(self, _data):
+ futures = [
+ self.executor.submit(self._process_file, file_name)
+ for file_name in self.files
+ ]
+ concurrent.futures.wait(futures)
+ GLib.idle_add(self._process_batch)
+
+ def _process_file(self, file_name):
+ full_path = os.path.join(self.wallpapers_dir, file_name)
+ cache_path = self._get_cache_path(file_name)
+ if not os.path.exists(cache_path):
+ try:
+ with Image.open(full_path) as img:
+ img.thumbnail((96, 96), Image.Resampling.BILINEAR)
+ img.save(cache_path, "PNG")
+ except Exception as e:
+ print(f"Error processing {file_name}: {e}")
+ return
+ self.thumbnail_queue.append((cache_path, file_name))
+ GLib.idle_add(self._process_batch)
+
+ def _process_batch(self):
+ batch = self.thumbnail_queue[:10]
+ del self.thumbnail_queue[:10]
+ for cache_path, file_name in batch:
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(cache_path)
+ self.thumbnails.append((pixbuf, file_name))
+ self.viewport.get_model().append([pixbuf, file_name])
+ except Exception as e:
+ print(f"Error loading thumbnail {cache_path}: {e}")
+ if self.thumbnail_queue:
+ GLib.idle_add(self._process_batch)
+ return False
+
+ def _get_cache_path(self, file_name: str) -> str:
+ file_hash = hashlib.md5(file_name.encode("utf-8")).hexdigest()
+ return os.path.join(self.CACHE_DIR, f"{file_hash}.png")
+
+ # Custom Color Functions
+ # def on_custom_color_changed(self, entry: Entry, *_):
+ # """Live preview for color entry changes."""
+ # color = entry.get_text().strip()
+ # if is_valid_hex_color(color):
+ # self.color_preview.override_background_color(
+ # Gtk.StateFlags.NORMAL, Gdk.RGBA.from_string(color)
+ # )
+ # elif is_valid_hue(color):
+ # hex_color = self.hue_to_hex(float(color))
+ # self.color_preview.override_background_color(
+ # Gtk.StateFlags.NORMAL, Gdk.RGBA.from_string(hex_color)
+ # )
+ # else:
+ # self.color_preview.override_background_color(Gtk.StateFlags.NORMAL, None)
+
+ def on_custom_color_submitted(self, entry: Entry):
+ """Handle color submission."""
+ color = entry.get_text().strip()
+ if is_valid_hex_color(color) or is_valid_hue(color):
+ color_value = (
+ color if is_valid_hex_color(color) else self.hue_to_hex(float(color))
+ )
+ print(f"Applying custom color: {color_value}")
+ self.update_custom_color(color_value)
+ else:
+ print("Invalid color input. Please use a valid Hex or Hue.")
+
+ def update_custom_color(self, color: str):
+ """Update the custom color in settings and regenerate theme."""
+ try:
+ with open(self.SETTINGS_FILE, "r") as f:
+ settings = json.loads(f.read())
+
+ settings["custom-color"] = color
+
+ with open(self.SETTINGS_FILE, "w") as f:
+ json.dump(settings, f, indent=2)
+
+ home_dir = GLib.get_home_dir()
+ color_generator = os.path.join(
+ home_dir, "dotfiles/material-colors/generate.py"
+ )
+ command = f'python -O {color_generator} --color "{color}"'
+ GLib.spawn_command_line_async(command)
+ print(f"Custom color applied: {color}")
+ except Exception as e:
+ print(f"Failed to update custom color: {e}")
+
+ @staticmethod
+ def _is_image(file_name: str) -> bool:
+ return file_name.lower().endswith(
+ (".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp")
+ )
+
+ @staticmethod
+ def hue_to_hex(hue: float) -> str:
+ """Convert Hue to Hex color."""
+ hue = hue / 360.0
+ rgb = WallpaperSelector.hls_to_rgb(hue, 0.5, 1.0)
+ return f"#{int(rgb[0] * 255):02X}{int(rgb[1] * 255):02X}{int(rgb[2] * 255):02X}"
+
+ @staticmethod
+ def hls_to_rgb(h: float, l: float, s: float) -> tuple:
+ """Convert HLS to RGB color."""
+ if s == 0:
+ return l, l, l
+
+ def hue2rgb(p, q, t):
+ if t < 0:
+ t += 1
+ if t > 1:
+ t -= 1
+ if t < 1 / 6:
+ return p + (q - p) * 6 * t
+ if t < 1 / 2:
+ return q
+ if t < 2 / 3:
+ return p + (q - p) * (2 / 3 - t) * 6
+ return p
+
+ q = l * (1 + s) if l < 0.5 else l + s - l * s
+ p = 2 * l - q
+ r = hue2rgb(p, q, h + 1 / 3)
+ g = hue2rgb(p, q, h)
+ b = hue2rgb(p, q, h - 1 / 3)
+ return r, g, b
diff --git a/modules/launcher/components/wallpapers.py b/modules/launcher/components/wallpapers.py
new file mode 100644
index 0000000..bf05e60
--- /dev/null
+++ b/modules/launcher/components/wallpapers.py
@@ -0,0 +1,264 @@
+import hashlib
+import json
+import os
+from PIL import Image
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.entry import Entry
+from fabric.widgets.scrolledwindow import ScrolledWindow
+from gi.repository import GdkPixbuf, GLib, Gtk, Gio
+from snippets import MaterialIcon
+from fabric.utils import exec_shell_command, get_relative_path
+import concurrent.futures
+from concurrent.futures import ThreadPoolExecutor
+from snippets import WALLPAPERS_DIR
+
+
+class WallpaperSelector(Box):
+ CACHE_DIR = os.path.expanduser("~/.cache/modus/wallpapers")
+ SETTINGS_FILE = get_relative_path("../../../config/assets/settings.json")
+ SCHEMES = {
+ "TonalSpot": "tonalSpot",
+ "Expressive": "expressive",
+ "FruitSalad": "fruitSalad",
+ "Monochrome": "monochrome",
+ "Rainbow": "rainbow",
+ "Vibrant": "vibrant",
+ "Neutral": "neutral",
+ "Fidelity": "fidelity",
+ "Content": "content",
+ }
+
+ def __init__(self, **kwargs):
+ super().__init__(name="wallpapers", spacing=4, orientation="v", **kwargs)
+ self.launcher = kwargs["launcher"]
+
+ # self.wallpapers_dir = os.path.expanduser("~/Pictures/wallpapers")
+ os.makedirs(self.CACHE_DIR, exist_ok=True)
+
+ self.files = [f for f in os.listdir(WALLPAPERS_DIR) if self._is_image(f)]
+ self.thumbnails = []
+ self.thumbnail_queue = []
+ self.executor = ThreadPoolExecutor(max_workers=4) # Shared executor
+
+ self.viewport = Gtk.IconView()
+ self.viewport.set_model(Gtk.ListStore(GdkPixbuf.Pixbuf, str))
+ self.viewport.set_pixbuf_column(0)
+ self.viewport.set_text_column(1)
+ self.viewport.set_item_width(0)
+ self.viewport.connect("item-activated", self.on_wallpaper_selected)
+
+ self.scrolled_window = ScrolledWindow(
+ name="scrolled-window",
+ spacing=10,
+ h_expand=True,
+ v_expand=True,
+ child=self.viewport,
+ )
+
+ self.search_entry = Entry(
+ name="search-entry",
+ h_expand=True,
+ notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()),
+ )
+
+ self.scheme_dropdown = Gtk.ComboBoxText()
+ self.scheme_dropdown.set_name("scheme-dropdown")
+ self.scheme_dropdown.set_tooltip_text("Select color scheme")
+
+ for display_name, scheme_id in sorted(self.SCHEMES.items()):
+ self.scheme_dropdown.append(scheme_id, display_name)
+
+ self.scheme_dropdown.set_active_id("tonalSpot")
+ self.scheme_dropdown.connect("changed", self.on_scheme_changed)
+
+ # Set the initial icon based on dark mode state
+ initial_icon = "light_mode" if not self.check_dark_mode_state() else "dark_mode"
+ self.toggle_button = Button(
+ child=MaterialIcon(initial_icon),
+ name="toggle-launcher-button",
+ on_clicked=self.toggle_dark_mode,
+ )
+
+ self.dropdown_box = Box(
+ name="dropdown-box",
+ orientation="h",
+ children=[
+ self.scheme_dropdown,
+ MaterialIcon("keyboard_arrow_down"),
+ ],
+ )
+
+ self.header_box = Box(
+ name="header-box",
+ spacing=10,
+ orientation="h",
+ children=[self.search_entry, self.dropdown_box, self.toggle_button],
+ )
+
+ self.add(self.header_box)
+ self.add(self.scrolled_window)
+ self._start_thumbnail_thread()
+ self.setup_file_monitor()
+ self.show_all()
+
+ def setup_file_monitor(self):
+ gfile = Gio.File.new_for_path(WALLPAPERS_DIR)
+ self.file_monitor = gfile.monitor_directory(Gio.FileMonitorFlags.NONE, None)
+ self.file_monitor.connect("changed", self.on_directory_changed)
+
+ def on_directory_changed(self, monitor, file, other_file, event_type):
+ file_name = file.get_basename()
+ if event_type == Gio.FileMonitorEvent.DELETED:
+ if file_name in self.files:
+ self.files.remove(file_name)
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache {cache_path}: {e}")
+ self.thumbnails = [(p, n) for p, n in self.thumbnails if n != file_name]
+ GLib.idle_add(self.arrange_viewport, self.search_entry.get_text())
+ elif event_type == Gio.FileMonitorEvent.CREATED:
+ if self._is_image(file_name) and file_name not in self.files:
+ self.files.append(file_name)
+ self.files.sort()
+ self.executor.submit(self._process_file, file_name)
+ elif event_type == Gio.FileMonitorEvent.CHANGED:
+ if self._is_image(file_name) and file_name in self.files:
+ cache_path = self._get_cache_path(file_name)
+ if os.path.exists(cache_path):
+ try:
+ os.remove(cache_path)
+ except Exception as e:
+ print(f"Error deleting cache for changed file {file_name}: {e}")
+ self.executor.submit(self._process_file, file_name)
+
+ def close_selector(self):
+ self.launcher.close()
+
+ def arrange_viewport(self, query: str = ""):
+ self.viewport.get_model().clear()
+ filtered_thumbnails = [
+ (thumb, name)
+ for thumb, name in self.thumbnails
+ if query.casefold() in name.casefold()
+ ]
+
+ filtered_thumbnails.sort(key=lambda x: x[1].lower())
+
+ for pixbuf, file_name in filtered_thumbnails:
+ self.viewport.get_model().append([pixbuf, file_name])
+
+ def toggle_dark_mode(self, *_):
+ current_state = self.check_dark_mode_state()
+ new_mode = "dark" if not current_state else "light"
+
+ # Call the shell script with the --set argument
+ command = f"bash {get_relative_path('../../../config/dark-theme.sh')} --set {new_mode}"
+ GLib.spawn_command_line_async(command)
+
+ # Set the appropriate icon based on the mode
+ icon_name = "dark_mode" if new_mode == "dark" else "light_mode"
+
+ # Update button icon
+ if self.toggle_button.get_child():
+ self.toggle_button.remove(self.toggle_button.get_child())
+ self.toggle_button.add(MaterialIcon(icon_name))
+ self.toggle_button.show_all()
+
+ def check_dark_mode_state(self):
+ result = exec_shell_command(
+ "gsettings get org.gnome.desktop.interface color-scheme"
+ )
+ return result.strip().replace("'", "") == "prefer-dark"
+
+ def on_wallpaper_selected(self, iconview, path):
+ model = iconview.get_model()
+ file_name = model[path][1]
+ full_path = os.path.join(WALLPAPERS_DIR, file_name)
+ selected_scheme = self.scheme_dropdown.get_active_id()
+ wallpaper = get_relative_path("../../../config/wallpaper.py")
+ command = f"python -O {wallpaper} -I {full_path}"
+ GLib.spawn_command_line_async(command)
+ self.update_scheme(selected_scheme)
+
+ def on_scheme_changed(self, combo):
+ scheme_id = combo.get_active_id()
+ display_name = next(
+ name for name, id in self.SCHEMES.items() if id == scheme_id
+ )
+ print(f"Color scheme selected: {display_name} ({scheme_id})")
+ self.update_scheme(scheme_id)
+
+ color_generator = get_relative_path(
+ "../../../config/material-colors/generate.py"
+ )
+ try:
+ command = f'python -O {color_generator} -R --scheme "{scheme_id}"'
+ GLib.spawn_command_line_async(command)
+ print(f"Applied color scheme: {display_name}")
+ except Exception as e:
+ print(f"Failed to apply color scheme: {e}")
+
+ def update_scheme(self, scheme: str):
+ try:
+ with open(self.SETTINGS_FILE, "r") as f:
+ settings = json.loads(f.read())
+
+ settings["generation-scheme"] = scheme
+
+ with open(self.SETTINGS_FILE, "w") as f:
+ json.dump(settings, f, indent=2)
+ except Exception as error:
+ print(f"Failed to update generation-scheme in settings.json: {error}")
+
+ def _start_thumbnail_thread(self):
+ thread = GLib.Thread.new("thumbnail-loader", self._preload_thumbnails, None)
+
+ def _preload_thumbnails(self, _data):
+ futures = [
+ self.executor.submit(self._process_file, file_name)
+ for file_name in self.files
+ ]
+ concurrent.futures.wait(futures)
+ GLib.idle_add(self._process_batch)
+
+ def _process_file(self, file_name):
+ full_path = os.path.join(WALLPAPERS_DIR, file_name)
+ cache_path = self._get_cache_path(file_name)
+ if not os.path.exists(cache_path):
+ try:
+ with Image.open(full_path) as img:
+ img.thumbnail((96, 96), Image.Resampling.BILINEAR)
+ img.save(cache_path, "PNG")
+ except Exception as e:
+ print(f"Error processing {file_name}: {e}")
+ return
+ self.thumbnail_queue.append((cache_path, file_name))
+ GLib.idle_add(self._process_batch)
+
+ def _process_batch(self):
+ batch = self.thumbnail_queue[:10]
+ del self.thumbnail_queue[:10]
+ for cache_path, file_name in batch:
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(cache_path)
+ self.thumbnails.append((pixbuf, file_name))
+ self.viewport.get_model().append([pixbuf, file_name])
+ except Exception as e:
+ print(f"Error loading thumbnail {cache_path}: {e}")
+ if self.thumbnail_queue:
+ GLib.idle_add(self._process_batch)
+ return False
+
+ def _get_cache_path(self, file_name: str) -> str:
+ file_hash = hashlib.md5(file_name.encode("utf-8")).hexdigest()
+ return os.path.join(self.CACHE_DIR, f"{file_hash}.png")
+
+ @staticmethod
+ def _is_image(file_name: str) -> bool:
+ return file_name.lower().endswith(
+ (".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp")
+ )
diff --git a/modules/launcher/launcher.py b/modules/launcher/launcher.py
new file mode 100644
index 0000000..b1f9320
--- /dev/null
+++ b/modules/launcher/launcher.py
@@ -0,0 +1,163 @@
+from fabric.widgets.centerbox import CenterBox
+from fabric.widgets.stack import Stack
+from fabric.widgets.box import Box
+from fabric.widgets.wayland import WaylandWindow as Window
+from gi.repository import Gtk
+from modules.launcher.components import (
+ AppLauncher,
+ BluetoothConnections,
+ Cliphist,
+ Emoji,
+ PowerMenu,
+ Sh,
+ TodoManager,
+ WallpaperSelector,
+)
+
+
+class Launcher(Window):
+ def __init__(self, **kwargs):
+ super().__init__(
+ layer="top",
+ anchor="center",
+ visible=False,
+ all_visible=False,
+ **kwargs,
+ )
+
+ self.launcher = AppLauncher(launcher=self)
+ self.wallpapers = WallpaperSelector(launcher=self)
+ self.power = PowerMenu(launcher=self)
+ self.emoji = Emoji(launcher=self)
+ self.cliphist = Cliphist(launcher=self)
+ self.todo = TodoManager()
+ self.bluetooth = BluetoothConnections()
+ self.sh = Sh(launcher=self)
+
+ self.stack = Stack(
+ name="launcher-content",
+ v_expand=True,
+ h_expand=True,
+ transition_type="crossfade",
+ transition_duration=100,
+ children=[
+ self.launcher,
+ self.wallpapers,
+ self.power,
+ self.emoji,
+ self.cliphist,
+ self.todo,
+ self.bluetooth,
+ self.sh,
+ ],
+ )
+
+ self.launcher_box = CenterBox(
+ name="launcher",
+ orientation="v",
+ start_children=self.stack,
+ )
+
+ self.add(self.launcher_box)
+ self.show_all()
+ self.hide()
+ self.wallpapers.viewport.hide()
+ self.add_keybinding("Escape", lambda *_: self.close())
+
+ def close(self):
+ self.set_keyboard_mode("none")
+ self.hide()
+
+ for widget in [
+ self.launcher,
+ self.wallpapers,
+ self.power,
+ self.emoji,
+ self.cliphist,
+ self.todo,
+ self.bluetooth,
+ self.sh,
+ ]:
+ if widget == self.wallpapers:
+ self.wallpapers.viewport.hide()
+ self.wallpapers.viewport.set_property("name", None)
+
+ if hasattr(widget, "viewport") and widget.viewport:
+ widget.viewport.hide()
+
+ for style in [
+ "launcher",
+ "wallpapers",
+ "power",
+ "emoji",
+ "cliphist",
+ "todo",
+ "bluetooth",
+ "sh",
+ ]:
+ self.stack.remove_style_class(style)
+
+ return True
+
+ def open(self, widget):
+ self.set_keyboard_mode("exclusive")
+ self.show()
+
+ widgets = {
+ "launcher": self.launcher,
+ "wallpapers": self.wallpapers,
+ "power": self.power,
+ "emoji": self.emoji,
+ "cliphist": self.cliphist,
+ "todo": self.todo,
+ "bluetooth": self.bluetooth,
+ "sh": self.sh,
+ }
+
+ for w in widgets.values():
+ w.hide()
+ for style in widgets.keys():
+ self.stack.remove_style_class(style)
+
+ if widget in widgets:
+ self.stack.get_style_context().add_class(widget)
+ self.stack.set_visible_child(widgets[widget])
+ widgets[widget].show()
+
+ # if widget != "launcher":
+ # self.launcher.hide()
+
+ if widget != "wallpapers":
+ self.wallpapers.viewport.hide()
+ self.wallpapers.viewport.set_property("name", None)
+
+ if widget == "launcher":
+ self.launcher.open_launcher()
+ self.launcher.search_entry.set_text("")
+ self.launcher.search_entry.grab_focus()
+
+ elif widget == "wallpapers":
+ self.wallpapers.search_entry.set_text("")
+ self.wallpapers.search_entry.grab_focus()
+ self.wallpapers.viewport.show()
+ self.wallpapers.viewport.set_property("name", "wallpaper-icons")
+
+ elif widget == "emoji":
+ self.emoji.open_launcher()
+ self.emoji.search_entry.set_text("")
+ self.emoji.search_entry.grab_focus()
+
+ elif widget == "cliphist":
+ self.cliphist.open_launcher()
+ self.cliphist.search_entry.set_text("")
+ self.cliphist.search_entry.grab_focus()
+
+ elif widget == "todo":
+ self.todo.open_launcher()
+ self.todo.todo_entry.set_text("")
+ self.todo.todo_entry.grab_focus()
+
+ elif widget == "sh":
+ self.sh.open_launcher()
+ self.sh.search_entry.set_text("")
+ self.sh.search_entry.grab_focus()
diff --git a/modules/notification_popup.py b/modules/notification_popup.py
new file mode 100644
index 0000000..8835778
--- /dev/null
+++ b/modules/notification_popup.py
@@ -0,0 +1,303 @@
+import time
+
+import gi
+
+gi.require_version("GdkPixbuf", "2.0")
+
+from fabric.notifications import (
+ Notification,
+ NotificationAction,
+ NotificationCloseReason,
+ Notifications,
+)
+from fabric.utils import invoke_repeater
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.circularprogressbar import CircularProgressBar
+from fabric.widgets.image import Image
+from fabric.widgets.label import Label
+from fabric.widgets.overlay import Overlay
+from fabric.widgets.revealer import Revealer
+from fabric.widgets.wayland import WaylandWindow as Window
+from gi.repository import GdkPixbuf, GLib, GObject
+from snippets import Animator, CustomImage
+
+
+class AnimatedCircularProgressBar(CircularProgressBar):
+ def __init__(self, duration=0.6, bezier_curve=(0.34, 1.56, 0.64, 1.0), **kwargs):
+ super().__init__(**kwargs)
+
+ self.animator = (
+ Animator(
+ bezier_curve=bezier_curve,
+ duration=duration,
+ min_value=self.min_value,
+ max_value=self.value,
+ tick_widget=self,
+ notify_value=lambda p, *_: self.set_value(p.value),
+ )
+ .build()
+ .play()
+ .unwrap()
+ )
+
+ def animate_value(self, value: float):
+ self.animator.pause()
+ self.animator.min_value = self.value
+ self.animator.max_value = value
+ self.animator.play()
+ return
+
+
+class ActionButton(Button):
+ def __init__(
+ self, action: NotificationAction, action_number: int, total_actions: int
+ ):
+ self.action = action
+ super().__init__(
+ label=action.label,
+ h_expand=True,
+ on_clicked=self.on_clicked,
+ )
+ if action_number == 0:
+ self.add_style_class("start-action")
+ elif action_number == total_actions - 1:
+ self.add_style_class("end-action")
+ else:
+ self.add_style_class("middle-action")
+
+ def on_clicked(self, *_):
+ self.action.invoke()
+ self.action.parent.close("dismissed-by-user")
+
+
+class NotificationWidget(Box):
+ def __init__(self, notification: Notification, **kwargs):
+ super().__init__(
+ name="notification",
+ spacing=8,
+ orientation="v",
+ **kwargs,
+ )
+
+ self._notification = notification
+ self._timer = None
+ self.anim_parts = 20
+ self.anim_interval = self.get_timeout() / self.anim_parts
+ self.timeout_in_sec = self.get_timeout() / 1000
+ self.time = GLib.DateTime.new_from_unix_local(time.time()).format("%m/%d")
+ self.connect("button-press-event", self.on_button_press)
+
+ header_container = Box(spacing=8, orientation="h")
+ self.progress_timeout = AnimatedCircularProgressBar(
+ name="notification-circular-progress-bar",
+ size=30,
+ min_value=0,
+ max_value=1,
+ radius_color=True,
+ value=0,
+ )
+
+ header_container.children = (
+ self.get_icon(notification.app_icon, notification.app_name, 25),
+ Label(
+ markup=str(
+ self._notification.summary
+ if self._notification.summary
+ else notification.app_name
+ ),
+ h_align="start",
+ style="font-weight: 900;",
+ ellipsization="end",
+ ),
+ )
+
+ header_container.pack_end(
+ Box(
+ v_align="start",
+ children=(
+ Overlay(
+ child=self.progress_timeout,
+ overlays=Button(
+ image=Image(
+ icon_name="window-close-symbolic",
+ icon_size=16,
+ ),
+ style_classes="close-button",
+ on_clicked=lambda *_: self._notification.close(
+ "dismissed-by-user"
+ ),
+ ),
+ ),
+ ),
+ ),
+ False,
+ False,
+ 0,
+ )
+
+ body_container = Box(spacing=4, orientation="h")
+
+ if image_pixbuf := self._notification.image_pixbuf:
+ body_container.add(
+ Box(
+ v_expand=True,
+ v_align="center",
+ children=CustomImage(
+ pixbuf=image_pixbuf.scale_simple(
+ 64, 64, GdkPixbuf.InterpType.BILINEAR
+ ),
+ style_classes="image",
+ ),
+ )
+ )
+
+ body_container.add(
+ Label(
+ markup=self._notification.body,
+ line_wrap="word-char",
+ v_align="start",
+ ellipsization="end",
+ max_chars_width=40,
+ h_align="start",
+ )
+ )
+
+ actions_container = Box(
+ spacing=4,
+ orientation="h",
+ name="notification-action-buttons",
+ children=[
+ ActionButton(action, i, len(self._notification.actions))
+ for i, action in enumerate(self._notification.actions)
+ ],
+ h_expand=True,
+ )
+
+ self.add(header_container)
+ self.add(body_container)
+ self.add(actions_container)
+
+ # Destroy this widget once the notification is closed
+ self._notification.connect(
+ "closed",
+ lambda *_: (
+ parent.remove(self) if (parent := self.get_parent()) else None, # type: ignore
+ self.destroy(),
+ ),
+ invoke_repeater(
+ 5 * 1000,
+ lambda: self._notification.close("expired"),
+ initial_call=False,
+ ),
+ )
+
+ self.start_timer()
+
+ def start_timer(self):
+ self._timer = GObject.timeout_add(200, self.update_progress)
+
+ def update_progress(self):
+ self.progress_timeout.animate_value(
+ self.progress_timeout.value + 1 / self.anim_parts
+ )
+ if self.progress_timeout.value >= self.timeout_in_sec:
+ self.progress_timeout.value = self.timeout_in_sec
+ self.stop_timer()
+ return True # Continue the timer
+
+ def stop_timer(self):
+ if self._timer:
+ GObject.source_remove(self._timer)
+ self._timer = None
+
+ def get_icon(self, app_icon, app_name, size) -> Image:
+ app_name = (
+ app_name.lower().replace(" ", "-")
+ if isinstance(app_name, str)
+ else app_name
+ )
+ if isinstance(app_icon, str) and app_icon.strip():
+ if app_icon.startswith("file://") or app_icon.startswith("/"):
+ file_path = app_icon[7:] if app_icon.startswith("file://") else app_icon
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_path)
+ scaled_pixbuf = pixbuf.scale_simple(
+ size, size, GdkPixbuf.InterpType.BILINEAR
+ )
+ return Image(name="notification-icon", pixbuf=scaled_pixbuf)
+ except Exception as e:
+ print(f"DEBUG: Failed to load image from {file_path}: {e}")
+
+ if app_icon and not app_icon.startswith(("file://", "/")):
+ icon_name = app_icon
+ elif app_name and app_name.strip() not in ["notify-send", ""]:
+ icon_name = app_name.strip()
+ else:
+ icon_name = "dialog-information-symbolic"
+
+ return Image(name="notification-icon", icon_name=icon_name, icon_size=size)
+
+ def on_button_press(self, _, event):
+ if event.button != 1:
+ (self._notification.close("dismissed-by-user"),)
+
+ def get_timeout(self):
+ return (
+ self._notification.timeout if self._notification.timeout != -1 else 5 * 1000
+ )
+
+
+class NotificationRevealer(Revealer):
+ def __init__(self, notification: Notification, **kwargs):
+ self.notif_box = NotificationWidget(notification)
+ self._notification = notification
+ super().__init__(
+ child=Box(
+ style="margin: 12px;",
+ children=[self.notif_box],
+ ),
+ transition_duration=500,
+ transition_type="crossfade",
+ )
+
+ self.connect(
+ "notify::child-revealed",
+ lambda *_: self.destroy() if not self.get_child_revealed() else None,
+ )
+
+ self._notification.connect("closed", self.on_resolved)
+
+ def on_resolved(
+ self,
+ notification: Notification,
+ reason: NotificationCloseReason,
+ ):
+ self.set_reveal_child(False)
+
+
+class NotificationPopup(Window):
+ def __init__(self):
+ self._server = Notifications()
+ self.notifications = Box(
+ v_expand=True,
+ h_expand=True,
+ style="margin: 1px 0px 1px 1px;",
+ orientation="v",
+ spacing=5,
+ )
+ self._server.connect("notification-added", self.on_new_notification)
+
+ super().__init__(
+ anchor="bottom",
+ child=self.notifications,
+ layer="overlay",
+ all_visible=True,
+ visible=True,
+ exclusive=False,
+ )
+
+ def on_new_notification(self, fabric_notif, id):
+ new_box = NotificationRevealer(fabric_notif.get_notification_from_id(id))
+ self.notifications.add(new_box)
+ new_box.set_reveal_child(True)
diff --git a/modules/osd.py b/modules/osd.py
new file mode 100644
index 0000000..c2764cb
--- /dev/null
+++ b/modules/osd.py
@@ -0,0 +1,228 @@
+import time
+from typing import ClassVar, Literal
+from fabric.utils import invoke_repeater
+from fabric.widgets.box import Box
+from fabric.widgets.revealer import Revealer
+from fabric.widgets.scale import Scale, ScaleMark
+from fabric.widgets.wayland import WaylandWindow as Window
+from gi.repository import GObject
+from snippets import Animator, MaterialIcon
+from services import brightness, audio
+
+
+class AnimatedScale(Scale):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.animator = None # Lazily initialized
+
+ def animate_value(self, value: float):
+ if not self.animator:
+ self.animator = Animator(
+ bezier_curve=(0.34, 1.56, 0.64, 1.0),
+ duration=0.8,
+ min_value=self.min_value,
+ max_value=self.value,
+ tick_widget=self,
+ notify_value=lambda p, *_: self.set_value(p.value),
+ )
+ self.animator.pause()
+ self.animator.min_value = self.value
+ self.animator.max_value = value
+ self.animator.play()
+
+
+class BrightnessOSDContainer(Box):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs, orientation="h", spacing=12, name="osd")
+ self.brightness_service = brightness
+ self.icon = MaterialIcon(icon_name="brightness_7", size=20)
+ self.scale = AnimatedScale(
+ marks=(ScaleMark(value=i) for i in range(0, 101, 10)),
+ value=70,
+ min_value=0,
+ max_value=100,
+ increments=(1, 1),
+ orientation="h",
+ )
+
+ self.add(self.icon)
+ self.add(self.scale)
+ self.update_brightness()
+
+ self.scale.connect("value-changed", lambda *_: self.update_brightness())
+ self.brightness_service.connect("screen", self.on_brightness_changed)
+
+ def update_brightness(self) -> None:
+ current_brightness = self.brightness_service.screen_brightness
+ if current_brightness != 0:
+ normalized_brightness = self._normalize_brightness(current_brightness)
+ self.scale.animate_value(normalized_brightness)
+ self.update_icon(normalized_brightness)
+
+ def update_icon(self, brightness_percentage: float) -> None:
+ icon_name = self.get_brightness_icon(brightness_percentage)
+ self.icon.set_label(icon_name)
+
+ def on_brightness_changed(self, _sender: any, value: float, *_args) -> None:
+ normalized_brightness = self._normalize_brightness(value)
+ self.scale.animate_value(normalized_brightness)
+ self.update_icon(normalized_brightness)
+
+ def _normalize_brightness(self, brightness: float) -> float:
+ return (brightness / self.brightness_service.max_screen) * 100
+
+ def get_brightness_icon(self, brightness_percentage: float) -> str:
+ brightness_icons = [
+ "brightness_1",
+ "brightness_2",
+ "brightness_3",
+ "brightness_4",
+ "brightness_5",
+ "brightness_6",
+ "brightness_7",
+ ]
+ thresholds = [
+ 100 / (1.6 ** (len(brightness_icons) - i - 1))
+ for i in range(len(brightness_icons))
+ ]
+
+ for i, threshold in enumerate(thresholds):
+ if brightness_percentage < threshold:
+ return brightness_icons[i]
+
+ return brightness_icons[-1]
+
+
+class AudioOSDContainer(Box):
+ __gsignals__: ClassVar[dict] = {
+ "volume-changed": (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
+ }
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs, orientation="h", spacing=13, name="osd")
+ self.audio = audio
+ self.icon = MaterialIcon(icon_name="volume_up", size=20)
+ self.scale = AnimatedScale(
+ marks=(ScaleMark(value=i) for i in range(1, 100, 10)),
+ value=70,
+ min_value=0,
+ max_value=100,
+ increments=(1, 1),
+ orientation="h",
+ )
+
+ self.add(self.icon)
+ self.add(self.scale)
+ self.sync_with_audio()
+
+ self.scale.connect("value-changed", self.on_volume_changed)
+ self.audio.connect("notify::speaker", self.on_audio_speaker_changed)
+
+ def sync_with_audio(self):
+ if self.audio.speaker:
+ volume = round(self.audio.speaker.volume)
+ self.scale.set_value(volume)
+ self.update_icon(volume)
+
+ def on_volume_changed(self, *_):
+ if self.audio.speaker:
+ volume = self.scale.value
+ if 0 <= volume <= 100:
+ self.audio.speaker.set_volume(volume)
+ self.update_icon(volume)
+ self.emit("volume-changed")
+
+ def on_audio_speaker_changed(self, *_):
+ if self.audio.speaker:
+ self.audio.speaker.connect("notify::volume", self.update_volume)
+ self.update_volume()
+
+ def update_volume(self, *_):
+ if self.audio.speaker and not self.is_hovered():
+ volume = round(self.audio.speaker.volume)
+ self.scale.set_value(volume)
+ self.update_icon(volume)
+
+ def update_icon(self, volume):
+ icon_name = self._get_audio_icon_name(volume)
+ self.icon.set_label(icon_name)
+
+ def _get_audio_icon_name(self, volume: int) -> str:
+ if volume == 101:
+ return "sound_detection_loud_sound"
+ elif volume >= 67:
+ return "volume_up"
+ elif volume >= 34:
+ return "volume_down"
+ elif volume >= 1:
+ return "volume_mute"
+ else:
+ return "volume_off"
+
+
+class OSDContainer(Window):
+ def __init__(self, **kwargs):
+ self.audio_container = AudioOSDContainer()
+ self.brightness_container = BrightnessOSDContainer()
+
+ self.timeout = 1000
+
+ self.revealer = Revealer(
+ transition_type="slide-right",
+ transition_duration=200,
+ child_revealed=False,
+ )
+
+ self.main_box = Box(
+ orientation="v",
+ spacing=13,
+ children=[self.revealer],
+ )
+
+ super().__init__(
+ layer="overlay",
+ anchor="bottom",
+ child=self.main_box,
+ visible=False,
+ pass_through=True,
+ keyboard_mode="on-demand",
+ **kwargs,
+ )
+
+ self.last_activity_time = time.time()
+
+ self.audio_container.audio.connect("notify::speaker", self.show_audio)
+ self.brightness_container.brightness_service.connect(
+ "screen", self.show_brightness
+ )
+ self.audio_container.connect("volume-changed", self.show_audio)
+
+ invoke_repeater(100, self.check_inactivity, initial_call=True)
+
+ def show_audio(self, *_):
+ self.show_box(box_to_show="audio")
+ self.reset_inactivity_timer()
+
+ def show_brightness(self, *_):
+ self.show_box(box_to_show="brightness")
+ self.reset_inactivity_timer()
+
+ def show_box(self, box_to_show: Literal["audio", "brightness"]):
+ self.set_visible(True)
+ if box_to_show == "audio":
+ self.revealer.children = self.audio_container
+ elif box_to_show == "brightness":
+ self.revealer.children = self.brightness_container
+ self.revealer.set_reveal_child(True)
+ self.reset_inactivity_timer()
+
+ def start_hide_timer(self):
+ self.set_visible(False)
+
+ def reset_inactivity_timer(self):
+ self.last_activity_time = time.time()
+
+ def check_inactivity(self):
+ if time.time() - self.last_activity_time >= (self.timeout / 1000):
+ self.start_hide_timer()
+ return True
diff --git a/services/__init__.py b/services/__init__.py
new file mode 100644
index 0000000..b464ce6
--- /dev/null
+++ b/services/__init__.py
@@ -0,0 +1,9 @@
+from fabric.audio import Audio
+from .brightness import Brightness
+from .screen_record import ScreenRecorder
+from .wifi import *
+
+
+brightness = Brightness()
+audio = Audio()
+sc = ScreenRecorder()
diff --git a/services/__pycache__/__init__.cpython-313.pyc b/services/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..19785d6
Binary files /dev/null and b/services/__pycache__/__init__.cpython-313.pyc differ
diff --git a/services/__pycache__/brightness.cpython-313.pyc b/services/__pycache__/brightness.cpython-313.pyc
new file mode 100644
index 0000000..3875ffe
Binary files /dev/null and b/services/__pycache__/brightness.cpython-313.pyc differ
diff --git a/services/__pycache__/config.cpython-313.pyc b/services/__pycache__/config.cpython-313.pyc
new file mode 100644
index 0000000..a8f643b
Binary files /dev/null and b/services/__pycache__/config.cpython-313.pyc differ
diff --git a/services/__pycache__/screen_record.cpython-313.pyc b/services/__pycache__/screen_record.cpython-313.pyc
new file mode 100644
index 0000000..e7494e1
Binary files /dev/null and b/services/__pycache__/screen_record.cpython-313.pyc differ
diff --git a/services/__pycache__/wifi.cpython-313.pyc b/services/__pycache__/wifi.cpython-313.pyc
new file mode 100644
index 0000000..6c5ca64
Binary files /dev/null and b/services/__pycache__/wifi.cpython-313.pyc differ
diff --git a/services/brightness.py b/services/brightness.py
new file mode 100644
index 0000000..49e7040
--- /dev/null
+++ b/services/brightness.py
@@ -0,0 +1,115 @@
+import os
+import subprocess
+
+from fabric.core.service import Property, Service, Signal
+from fabric.utils import exec_shell_command, monitor_file
+from gi.repository import GLib
+from loguru import logger # Import loguru logger
+
+
+# Helper function to execute brightnessctl asynchronously
+def exec_brightnessctl_async(args: str):
+ # Executes brightnessctl command asynchronously, ensuring no resource leaks.
+ try:
+ # Use subprocess.Popen to run the command without blocking
+ process = subprocess.Popen(
+ f"brightnessctl {args}",
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+
+ # Wait for the process to complete
+ stdout, stderr = process.communicate()
+
+ if process.returncode != 0:
+ logger.error(f"Error executing brightnessctl: {stderr.decode().strip()}")
+ else:
+ logger.debug(
+ f"brightnessctl output: {stdout.decode().strip()}"
+ ) # Optional: Log the output
+ except Exception as e:
+ logger.exception(f"Exception in exec_brightnessctl_async: {e}")
+
+
+# Discover screen backlight device
+try:
+ screen_device = str(exec_shell_command("ls -w1 /sys/class/backlight")).split("\n")[
+ 0
+ ]
+except IndexError:
+ screen_device = None
+
+
+class NoBrightnessError(ImportError):
+ # Raised when brightness-related dependencies are missing.
+ def __init__(self, *args):
+ super().__init__(
+ "Brightness control not available or missing dependencies", *args
+ )
+
+
+class Brightness(Service):
+ # Service to manage screen brightness levels.
+
+ @Signal
+ def screen(self, value: int) -> None:
+ """Signal emitted when screen brightness changes."""
+ pass # Implement as needed for your application
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+
+ if not screen_device:
+ raise NoBrightnessError()
+
+ # Path for screen backlight control
+ self.screen_backlight_path = f"/sys/class/backlight/{screen_device}"
+
+ # Initialize maximum brightness level
+ self.max_screen = self._read_max_brightness(self.screen_backlight_path)
+
+ # Monitor screen brightness file
+ self.screen_monitor = monitor_file(f"{self.screen_backlight_path}/brightness")
+ self.screen_monitor.connect(
+ "changed",
+ lambda _, file, *args: self.emit(
+ "screen", round(int(file.load_bytes()[0].get_data()))
+ ),
+ )
+
+ # Log the initialization of the service
+ logger.info(f"Brightness service initialized for device: {screen_device}")
+
+ def _read_max_brightness(self, path: str) -> int:
+ # Reads the maximum brightness value from the specified path.
+ max_brightness_path = os.path.join(path, "max_brightness")
+ if os.path.exists(max_brightness_path):
+ with open(max_brightness_path) as f:
+ return int(f.read().strip())
+ return -1 # Return -1 if file doesn't exist, indicating an error.
+
+ @Property(int, "read-write")
+ def screen_brightness(self) -> int:
+ # Property to get or set the screen brightness.
+ brightness_path = os.path.join(self.screen_backlight_path, "brightness")
+ if os.path.exists(brightness_path):
+ with open(brightness_path) as f:
+ return int(f.read().strip())
+ logger.warning(f"Brightness file does not exist: {brightness_path}")
+ return -1 # Return -1 if file doesn't exist, indicating error.
+
+ @screen_brightness.setter
+ def screen_brightness(self, value: int):
+ # Setter for screen brightness property.
+ if not (0 <= value <= self.max_screen):
+ value = max(0, min(value, self.max_screen))
+
+ try:
+ exec_brightnessctl_async(f"--device '{screen_device}' set {value}")
+ self.emit("screen", int((value / self.max_screen) * 100))
+ logger.info(f"Set screen brightness to {value} (out of {self.max_screen})")
+ except GLib.Error as e:
+ logger.error(f"Error setting screen brightness: {e.message}")
+ except Exception as e:
+ logger.exception(f"Unexpected error setting screen brightness: {e}")
diff --git a/services/screen_record.py b/services/screen_record.py
new file mode 100644
index 0000000..7fbf6d5
--- /dev/null
+++ b/services/screen_record.py
@@ -0,0 +1,142 @@
+import datetime
+import subprocess
+
+from fabric.core.service import Property, Service, Signal
+from fabric.utils import exec_shell_command, exec_shell_command_async
+from gi.repository import Gio, GLib
+from loguru import logger
+
+
+class ScreenRecorder(Service):
+ @Signal
+ def recording(self, value: bool) -> None: ...
+
+ def __init__(self, **kwargs):
+ self.screenshot_path = GLib.get_home_dir() + "/Pictures/Screenshots/"
+ self.screenrecord_path = GLib.get_home_dir() + "/Videos/Screencasting/"
+
+ super().__init__(**kwargs)
+
+ def screenshot(self, fullscreen=False, save_copy=True):
+ time = datetime.datetime.today().strftime("%Y-%m-%d_%H-%M-%S")
+ file_path = self.screenshot_path + str(time) + ".png"
+ command = (
+ ["grimblast", "copysave", "screen", file_path]
+ if save_copy
+ else ["grimblast", "copyscreen"]
+ )
+ if not fullscreen:
+ command[2] = "area"
+ try:
+ subprocess.run(command, check=True)
+ self.send_screenshot_notification(
+ file_path=file_path if file_path else None,
+ )
+ except Exception as e:
+ logger.error(f"[SCREENSHOT] Failed to run command: {command}")
+
+ def screencast_start(self, fullscreen=False):
+ if self.is_recording:
+ logger.error(
+ "[SCREENRECORD] Another instance of wf-recorder is already running"
+ )
+ return
+ time = datetime.datetime.today().strftime("%Y-%m-%d_%H-%M-%S")
+ file_path = self.screenrecord_path + str(time) + ".mp4"
+ self._current_screencast_path = file_path
+ area = "" if fullscreen else f"-g '{exec_shell_command('slurp')}'"
+ command = f"wf-recorder --file={file_path} --pixel-format yuv420p {area}"
+ exec_shell_command_async(command)
+ self.emit("recording", True)
+
+ def screencast_stop(self):
+ exec_shell_command_async("killall -INT wf-recorder")
+ self.emit("recording", False)
+ self.send_screencast_notification(self._current_screencast_path)
+
+ def send_screencast_notification(self, file_path):
+ # TODO: Generate a thumbnail
+ # exec_shell_command_async(f"totem-video-thumbnailer {file_path} {FABRIC_CACHE}")
+
+ cmd = ["notify-send"]
+ cmd.extend(
+ [
+ "-A",
+ "files=Show in Files",
+ "-A",
+ "view=View",
+ "-i",
+ "camera-video-symbolic",
+ "-a",
+ "Fabric Screenshot Utility",
+ "Screencast Saved",
+ f"Saved Screencast at {file_path}",
+ ]
+ )
+
+ proc: Gio.Subprocess = Gio.Subprocess.new(cmd, Gio.SubprocessFlags.STDOUT_PIPE)
+
+ def do_callback(process: Gio.Subprocess, task: Gio.Task):
+ try:
+ _, stdout, stderr = process.communicate_utf8_finish(task)
+ except Exception:
+ logger.error(
+ f"[SCREENCAST] Failed read notification action with error {stderr}"
+ )
+ return
+
+ match stdout.strip("\n"):
+ case "files":
+ exec_shell_command_async(f"xdg-open {self.screenrecord_path}")
+ case "view":
+ exec_shell_command_async(f"xdg-open {file_path}")
+
+ proc.communicate_utf8_async(None, None, do_callback)
+
+ def send_screenshot_notification(self, file_path=None):
+ cmd = ["notify-send"]
+ cmd.extend(
+ [
+ "-A",
+ "files=Show in Files",
+ "-A",
+ "view=View",
+ "-A",
+ "edit=Edit",
+ "-i",
+ "camera-photo-symbolic",
+ "-a",
+ "Fabric Screenshot Utility",
+ "-h",
+ f"STRING:image-path:{file_path}",
+ "Screenshot Saved",
+ f"Saved Screenshot at {file_path}",
+ ]
+ if file_path
+ else ["Screenshot Sent to Clipboard"]
+ )
+
+ proc: Gio.Subprocess = Gio.Subprocess.new(cmd, Gio.SubprocessFlags.STDOUT_PIPE)
+
+ def do_callback(process: Gio.Subprocess, task: Gio.Task):
+ try:
+ _, stdout, stderr = process.communicate_utf8_finish(task)
+ except Exception:
+ logger.error(
+ f"[SCREENSHOT] Failed read notification action with error {stderr}"
+ )
+ return
+
+ match stdout.strip("\n"):
+ case "files":
+ exec_shell_command_async(f"xdg-open {self.screenshot_path}")
+ case "view":
+ exec_shell_command_async(f"xdg-open {file_path}")
+ case "edit":
+ exec_shell_command_async(f"swappy -f {file_path}")
+
+ proc.communicate_utf8_async(None, None, do_callback)
+
+ @Property(bool, "readable", default_value=False)
+ def is_recording(self):
+ return False if len(exec_shell_command("pidof wf-recorder")) == 0 else True
diff --git a/services/wifi.py b/services/wifi.py
new file mode 100644
index 0000000..b048f23
--- /dev/null
+++ b/services/wifi.py
@@ -0,0 +1,321 @@
+from typing import Any, List, Literal
+import gi
+from fabric.core.service import Property, Service, Signal
+from fabric.utils import bulk_connect
+from gi.repository import Gio
+from loguru import logger
+
+from fabric.utils import exec_shell_command_async
+
+from gi.repository.NM import DeviceEthernet, DeviceWifi
+
+try:
+ gi.require_version("NM", "1.0")
+ from gi.repository import NM
+except ValueError:
+ logger.error("Failed to start network manager")
+
+
+class Wifi(Service):
+ @Signal
+ def changed(self) -> None: ...
+
+ @Signal
+ def enabled(self) -> bool: ...
+
+ def __init__(self, client: NM.Client, device: NM.DeviceWifi, **kwargs):
+ self._client: NM.Client = client
+ self._device: NM.DeviceWifi = device
+ self._ap: NM.AccessPoint | None = None
+ self._ap_signal: int | None = None
+ super().__init__(**kwargs)
+
+ self._client.connect(
+ "notify::wireless-enabled",
+ lambda *args: self.notifier("enabled", args),
+ )
+ if self._device:
+ bulk_connect(
+ self._device,
+ {
+ "notify::active-access-point": lambda *args: self._activate_ap(),
+ "access-point-added": lambda *args: self.emit("changed"),
+ "access-point-removed": lambda *args: self.emit("changed"),
+ "state-changed": lambda *args: self.ap_update(),
+ },
+ )
+ self._activate_ap()
+
+ def ap_update(self):
+ self.emit("changed")
+ for sn in [
+ "enabled",
+ "internet",
+ "strength",
+ "frequency",
+ "access-points",
+ "ssid",
+ "state",
+ "icon-name",
+ ]:
+ self.notify(sn)
+
+ def _activate_ap(self):
+ if self._ap:
+ self._ap.disconnect(self._ap_signal)
+ self._ap = self._device.get_active_access_point()
+ if not self._ap:
+ return
+
+ self._ap_signal = self._ap.connect(
+ "notify::strength", lambda *args: self.ap_update()
+ ) # type: ignore
+
+ def toggle_wifi(self):
+ self._client.wireless_set_enabled(not self._client.wireless_get_enabled())
+
+ # def set_active_ap(self, ap):
+ # self._device.access
+
+ def scan(self):
+ self._device.request_scan_async(
+ None,
+ lambda device, result: [
+ device.request_scan_finish(result),
+ self.emit("changed"),
+ ],
+ )
+
+ def notifier(self, name: str, *args):
+ self.notify(name)
+ self.emit("changed")
+ return
+
+ @Property(bool, "read-write", default_value=False)
+ def enabled(self) -> bool: # type: ignore
+ return bool(self._client.wireless_get_enabled())
+
+ @enabled.setter
+ def enabled(self, value: bool):
+ self._client.wireless_set_enabled(value)
+
+ @Property(int, "readable")
+ def strength(self):
+ return self._ap.get_strength() if self._ap else -1
+
+ @Property(str, "readable")
+ def icon_name(self):
+ if not self._ap:
+ return "network-wireless-disabled-symbolic"
+
+ if self.internet == "activated":
+ return {
+ 80: "network-wireless-signal-excellent-symbolic",
+ 60: "network-wireless-signal-good-symbolic",
+ 40: "network-wireless-signal-ok-symbolic",
+ 20: "network-wireless-signal-weak-symbolic",
+ 00: "network-wireless-signal-none-symbolic",
+ }.get(
+ min(80, 20 * round(self._ap.get_strength() / 20)),
+ "network-wireless-no-route-symbolic",
+ )
+ if self.internet == "activating":
+ return "network-wireless-acquiring-symbolic"
+
+ return "network-wireless-offline-symbolic"
+
+ @Property(int, "readable")
+ def frequency(self):
+ return self._ap.get_frequency() if self._ap else -1
+
+ @Property(int, "readable")
+ def internet(self):
+ return {
+ NM.ActiveConnectionState.ACTIVATED: "activated",
+ NM.ActiveConnectionState.ACTIVATING: "activating",
+ NM.ActiveConnectionState.DEACTIVATING: "deactivating",
+ NM.ActiveConnectionState.DEACTIVATED: "deactivated",
+ }.get(
+ self._device.get_active_connection().get_state(),
+ "unknown",
+ )
+
+ @Property(object, "readable")
+ def access_points(self) -> List[object]:
+ points: list[NM.AccessPoint] = self._device.get_access_points()
+
+ def make_ap_dict(ap: NM.AccessPoint):
+ return {
+ "bssid": ap.get_bssid(),
+ # "address": ap.get_
+ "last_seen": ap.get_last_seen(),
+ "ssid": NM.utils_ssid_to_utf8(ap.get_ssid().get_data())
+ if ap.get_ssid()
+ else "Unknown",
+ "active-ap": self._ap,
+ "strength": ap.get_strength(),
+ "frequency": ap.get_frequency(),
+ "icon-name": {
+ 80: "network-wireless-signal-excellent-symbolic",
+ 60: "network-wireless-signal-good-symbolic",
+ 40: "network-wireless-signal-ok-symbolic",
+ 20: "network-wireless-signal-weak-symbolic",
+ 00: "network-wireless-signal-none-symbolic",
+ }.get(
+ min(80, 20 * round(ap.get_strength() / 20)),
+ "network-wireless-no-route-symbolic",
+ ),
+ }
+
+ return list(map(make_ap_dict, points))
+
+ @Property(str, "readable")
+ def ssid(self):
+ if not self._ap:
+ return "Disconnected"
+ ssid = self._ap.get_ssid().get_data()
+ return NM.utils_ssid_to_utf8(ssid) if ssid else "Unknown"
+
+ @Property(int, "readable")
+ def state(self):
+ return {
+ NM.DeviceState.UNMANAGED: "unmanaged",
+ NM.DeviceState.UNAVAILABLE: "unavailable",
+ NM.DeviceState.DISCONNECTED: "disconnected",
+ NM.DeviceState.PREPARE: "prepare",
+ NM.DeviceState.CONFIG: "config",
+ NM.DeviceState.NEED_AUTH: "need_auth",
+ NM.DeviceState.IP_CONFIG: "ip_config",
+ NM.DeviceState.IP_CHECK: "ip_check",
+ NM.DeviceState.SECONDARIES: "secondaries",
+ NM.DeviceState.ACTIVATED: "activated",
+ NM.DeviceState.DEACTIVATING: "deactivating",
+ NM.DeviceState.FAILED: "failed",
+ }.get(self._device.get_state(), "unknown")
+
+
+class Ethernet(Service):
+ @Signal
+ def changed(self) -> None: ...
+
+ @Signal
+ def enabled(self) -> bool: ...
+
+ @Property(int, "readable")
+ def speed(self) -> int:
+ return self._device.get_speed()
+
+ @Property(str, "readable")
+ def internet(self) -> str:
+ return {
+ NM.ActiveConnectionState.ACTIVATED: "activated",
+ NM.ActiveConnectionState.ACTIVATING: "activating",
+ NM.ActiveConnectionState.DEACTIVATING: "deactivating",
+ NM.ActiveConnectionState.DEACTIVATED: "deactivated",
+ }.get(
+ self._device.get_active_connection().get_state(),
+ "disconnected",
+ )
+
+ @Property(str, "readable")
+ def icon_name(self) -> str:
+ network = self.internet
+ if network == "activated":
+ return "network-wired-symbolic"
+
+ elif network == "activating":
+ return "network-wired-acquiring-symbolic"
+
+ elif self._device.get_connectivity != NM.ConnectivityState.FULL:
+ return "network-wired-no-route-symbolic"
+
+ return "network-wired-disconnected-symbolic"
+
+ def __init__(self, client: NM.Client, device: NM.DeviceEthernet, **kwargs) -> None:
+ super().__init__(**kwargs)
+ self._client: NM.Client = client
+ self._device: NM.DeviceEthernet = device
+
+ for pn in (
+ "active-connection",
+ "icon-name",
+ "internet",
+ "speed",
+ "state",
+ ):
+ self._device.connect(f"notify::{pn}", lambda *_: self.notifier(pn))
+
+ self._device.connect("notify::speed", lambda *_: print(_))
+
+ def notifier(self, pn):
+ self.notify(pn)
+ self.emit("changed")
+
+
+class NetworkClient(Service):
+ @Signal
+ def device_ready(self) -> None: ...
+
+ def __init__(self, **kwargs):
+ self._client: NM.Client | None = None
+ self.wifi_device: Wifi | None = None
+ self.ethernet_device: Ethernet | None = None
+ super().__init__(**kwargs)
+ NM.Client.new_async(
+ cancellable=None,
+ callback=self._init_network_client,
+ **kwargs,
+ )
+
+ def _init_network_client(self, client: NM.Client, task: Gio.Task, **kwargs):
+ self._client = client
+ wifi_device: NM.DeviceWifi | None = self._get_device(NM.DeviceType.WIFI) # type: ignore
+ ethernet_device: NM.DeviceEthernet | None = self._get_device(
+ NM.DeviceType.ETHERNET
+ )
+
+ if wifi_device:
+ self.wifi_device = Wifi(self._client, wifi_device)
+ self.emit("device-ready")
+
+ if ethernet_device:
+ self.ethernet_device = Ethernet(client=self._client, device=ethernet_device)
+ self.emit("device-ready")
+
+ self.notify("primary-device")
+
+ def _get_device(self, device_type) -> Any:
+ devices: List[NM.Device] = self._client.get_devices() # type: ignore
+ return next(
+ (
+ x
+ for x in devices
+ if x.get_device_type() == device_type
+ and x.get_active_connection() != None
+ ),
+ None,
+ )
+
+ def _get_primary_device(self) -> Literal["wifi", "wired"] | None:
+ if not self._client:
+ return None
+ return (
+ "wifi"
+ if "wireless"
+ in str(self._client.get_primary_connection().get_connection_type())
+ else "wired"
+ if "ethernet"
+ in str(self._client.get_primary_connection().get_connection_type())
+ else None
+ )
+
+ def connect_wifi_bssid(self, bssid):
+ # We are using nmcli here, idk im lazy
+ exec_shell_command_async(
+ f"nmcli device wifi connect {bssid}", lambda *args: print(args)
+ )
+
+ @Property(str, "readable")
+ def primary_device(self) -> Literal["wifi", "wired"] | None:
+ return self._get_primary_device()
+
diff --git a/snippets/__init__.py b/snippets/__init__.py
new file mode 100644
index 0000000..d4d3f96
--- /dev/null
+++ b/snippets/__init__.py
@@ -0,0 +1,26 @@
+from .animator import *
+from .custom_image import *
+from .icon import *
+import json
+import os
+from fabric.utils import get_relative_path
+
+
+def read_config():
+ config_path = get_relative_path("../config/assets/launcher.json")
+
+ with open(config_path, "r") as file:
+ # Load JSON data into a Python dictionary
+ data = json.load(file)
+ return data
+
+
+default_wallpapers_dir = get_relative_path("../assets/wallpaper")
+json_config_path = get_relative_path("../config/assets/config.json")
+
+if os.path.exists(json_config_path):
+ with open(json_config_path, "r") as f:
+ config = json.load(f)
+ WALLPAPERS_DIR = config.get("wallpapers_dir", default_wallpapers_dir)
+else:
+ WALLPAPERS_DIR = default_wallpapers_dir
diff --git a/snippets/__pycache__/__init__.cpython-313.pyc b/snippets/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..3e7b2ab
Binary files /dev/null and b/snippets/__pycache__/__init__.cpython-313.pyc differ
diff --git a/snippets/__pycache__/animator.cpython-313.pyc b/snippets/__pycache__/animator.cpython-313.pyc
new file mode 100644
index 0000000..70b6ba5
Binary files /dev/null and b/snippets/__pycache__/animator.cpython-313.pyc differ
diff --git a/snippets/__pycache__/config.cpython-313.pyc b/snippets/__pycache__/config.cpython-313.pyc
new file mode 100644
index 0000000..9409492
Binary files /dev/null and b/snippets/__pycache__/config.cpython-313.pyc differ
diff --git a/snippets/__pycache__/custom_image.cpython-313.pyc b/snippets/__pycache__/custom_image.cpython-313.pyc
new file mode 100644
index 0000000..d5773b9
Binary files /dev/null and b/snippets/__pycache__/custom_image.cpython-313.pyc differ
diff --git a/snippets/__pycache__/functions.cpython-313.pyc b/snippets/__pycache__/functions.cpython-313.pyc
new file mode 100644
index 0000000..a0bd12d
Binary files /dev/null and b/snippets/__pycache__/functions.cpython-313.pyc differ
diff --git a/snippets/__pycache__/icon.cpython-313.pyc b/snippets/__pycache__/icon.cpython-313.pyc
new file mode 100644
index 0000000..ef53c4a
Binary files /dev/null and b/snippets/__pycache__/icon.cpython-313.pyc differ
diff --git a/snippets/animator.py b/snippets/animator.py
new file mode 100644
index 0000000..1799ae6
--- /dev/null
+++ b/snippets/animator.py
@@ -0,0 +1,179 @@
+from typing import cast
+
+from fabric import Property, Service, Signal
+from gi.repository import GLib, Gtk
+
+
+class Animator(Service):
+ @Signal
+ def finished(self) -> None: ...
+
+ @Property(tuple[float, float, float, float], "read-write")
+ def bezier_curve(self) -> tuple[float, float, float, float]:
+ return self._bezier_curve
+
+ @bezier_curve.setter
+ def bezier_curve(self, value: tuple[float, float, float, float]):
+ self._bezier_curve = value
+ return
+
+ @Property(float, "read-write")
+ def value(self):
+ return self._value
+
+ @value.setter
+ def value(self, value: float):
+ self._value = value
+ return
+
+ @Property(float, "read-write")
+ def max_value(self):
+ return self._max_value
+
+ @max_value.setter
+ def max_value(self, value: float):
+ self._max_value = value
+ return
+
+ @Property(float, "read-write")
+ def min_value(self):
+ return self._min_value
+
+ @min_value.setter
+ def min_value(self, value: float):
+ self._min_value = value
+ return
+
+ @Property(bool, "read-write", default_value=False)
+ def playing(self):
+ return self._playing
+
+ @playing.setter
+ def playing(self, value: bool):
+ self._playing = value
+ return
+
+ @Property(bool, "read-write", default_value=False)
+ def repeat(self):
+ return self._repeat
+
+ @repeat.setter
+ def repeat(self, value: bool):
+ self._repeat = value
+ return
+
+ def __init__(
+ self,
+ bezier_curve: tuple[float, float, float, float],
+ duration: float,
+ min_value: float = 0.0,
+ max_value: float = 1.0,
+ repeat: bool = False,
+ tick_widget: Gtk.Widget | None = None,
+ **kwargs,
+ ):
+ super().__init__(**kwargs)
+ self._bezier_curve = (1, 0, 1, 1)
+ self._duration = 5
+ self._value = 0.0
+ self._min_value = 0.0
+ self._max_value = 1.0
+ self._repeat = False
+
+ self.bezier_curve = bezier_curve
+ self.duration = duration
+ self.value = min_value
+ self.min_value = min_value
+ self.max_value = max_value
+ self.repeat = repeat
+
+ self.playing = False
+ self._start_time = None
+ self._tick_handler = None
+ self._timeline_pos = 0
+ self._tick_widget = tick_widget
+
+ def do_get_time_now(self):
+ return GLib.get_monotonic_time() / 1_000_000
+
+ def do_lerp(self, start: float, end: float, time: float) -> float:
+ return start + (end - start) * time
+
+ def do_interpolate_cubic_bezier(self, time: float) -> float:
+ y_points = (0, self.bezier_curve[1], self.bezier_curve[3], 1)
+ return (
+ (1 - time) ** 3 * y_points[0]
+ + 3 * (1 - time) ** 2 * time * y_points[1]
+ + 3 * (1 - time) * time**2 * y_points[2]
+ + time**3 * y_points[3]
+ )
+
+ def do_ease(self, time: float) -> float:
+ return self.do_lerp(
+ self.min_value, self.max_value, self.do_interpolate_cubic_bezier(time)
+ )
+
+ def do_update_value(self, delta_time: float):
+ if not self.playing:
+ return
+
+ elapsed_time = delta_time - cast(float, self._start_time)
+
+ self._timeline_pos = min(1, elapsed_time / self.duration)
+
+ self.value = self.do_ease(self._timeline_pos)
+
+ if not self._timeline_pos >= 1:
+ return
+
+ if not self.repeat:
+ self.value = self.max_value
+ self.finished()
+ self.pause()
+ return
+
+ self._start_time = delta_time
+ self._timeline_pos = 0
+ return
+
+ def do_handle_tick(self, *_):
+ current_time = self.do_get_time_now()
+ self.do_update_value(current_time)
+ return True
+
+ def do_remove_tick_handlers(self):
+ if self._tick_handler:
+ if self._tick_widget:
+ self._tick_widget.remove_tick_callback(self._tick_handler)
+ else:
+ GLib.source_remove(self._tick_handler)
+ self._tick_handler = None
+ return
+
+ def play(self):
+ if self.playing:
+ return
+
+ self._start_time = self.do_get_time_now()
+
+ if not self._tick_handler:
+ if self._tick_widget:
+ self._tick_handler = self._tick_widget.add_tick_callback(
+ self.do_handle_tick
+ )
+ else:
+ self._tick_handler = GLib.timeout_add(16, self.do_handle_tick)
+
+ self.playing = True
+ return
+
+ def pause(self):
+ self.playing = False
+ return self.do_remove_tick_handlers()
+
+ def stop(self):
+ if not self._tick_handler:
+ self._timeline_pos = 0
+ self.playing = False
+ return
+ return self.do_remove_tick_handlers()
diff --git a/snippets/custom_image.py b/snippets/custom_image.py
new file mode 100644
index 0000000..1aae7f6
--- /dev/null
+++ b/snippets/custom_image.py
@@ -0,0 +1,39 @@
+import math
+from typing import cast
+
+import cairo
+from gi.repository import Gtk
+
+from fabric.widgets.image import Image
+
+
+class CustomImage(Image):
+ def do_render_rectangle(
+ self, cr: cairo.Context, width: int, height: int, radius: int = 0
+ ):
+ cr.move_to(radius, 0)
+ cr.line_to(width - radius, 0)
+ cr.arc(width - radius, radius, radius, -(math.pi / 2), 0)
+ cr.line_to(width, height - radius)
+ cr.arc(width - radius, height - radius, radius, 0, (math.pi / 2))
+ cr.line_to(radius, height)
+ cr.arc(radius, height - radius, radius, (math.pi / 2), math.pi)
+ cr.line_to(0, radius)
+ cr.arc(radius, radius, radius, math.pi, (3 * (math.pi / 2)))
+ cr.close_path()
+
+ def do_draw(self, cr: cairo.Context):
+ context = self.get_style_context()
+ width, height = self.get_allocated_width(), self.get_allocated_height()
+ cr.save()
+
+ self.do_render_rectangle(
+ cr,
+ width,
+ height,
+ cast(int, context.get_property("border-radius", Gtk.StateFlags.NORMAL)),
+ )
+ cr.clip()
+ Image.do_draw(self, cr)
+
+ cr.restore()
diff --git a/snippets/icon.py b/snippets/icon.py
new file mode 100644
index 0000000..86e77c0
--- /dev/null
+++ b/snippets/icon.py
@@ -0,0 +1,16 @@
+from fabric.widgets.label import Label
+
+
+def MaterialIcon(icon_name: str, size: int = 24, props=None):
+ label_props = {
+ "label": str(icon_name), # Directly use the provided icon name
+ "name": "material_icon",
+ "style": f"font-size: {size}px;", # Set font family for Material Icons
+ "h_align": "center", # Align horizontally
+ "v_align": "center", # Align vertically
+ }
+
+ if props:
+ label_props.update(props)
+
+ return Label(**label_props)
diff --git a/styles/bar.css b/styles/bar.css
new file mode 100644
index 0000000..97322e8
--- /dev/null
+++ b/styles/bar.css
@@ -0,0 +1,184 @@
+#bar {
+ background-color: @surface;
+ padding: 3px;
+}
+
+#bar label {
+ font-weight: bold;
+}
+
+#bar.hidden {
+ opacity: 0;
+ padding: 3px;
+ margin-bottom: -52px;
+ transition: all 0.5s cubic-bezier(0.5, 0.25, 0, 1);
+}
+
+/*
+ * โโ bar modules โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#start-container,
+#center-container,
+#end-container {
+ padding-top: 6px;
+ padding-bottom: 6px;
+ margin-left: 12px;
+ margin-right: 12px;
+}
+
+/*
+ * โโ workspace โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#workspaces {
+ border-radius: 100px;
+ font-style: normal;
+ background: @surfaceContainer;
+ padding: 0px 10px 0px 10px;
+}
+
+/*
+ * โโ Clock โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#datetime {
+ background-color: @surfaceContainer;
+ border-radius: 100px;
+ padding: 8px;
+}
+
+/*
+ * โโ battery โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#battery {
+ padding: 0 0 0 4px;
+}
+
+/*
+ * โโ tray โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#tray {
+ background-color: @surfaceContainer;
+ border-radius: 100px;
+ padding: 2px 10px 0px 10px;
+}
+
+#tray > button {
+ margin: 0px;
+ padding: 0px;
+}
+
+menu {
+ border: solid 1px @outlineVariant;
+ border-radius: 16px;
+ background-color: @surface;
+ padding: 6px;
+}
+
+menu > menuitem {
+ border-radius: 10px;
+ padding: 6px 10px;
+}
+
+menu > menuitem:hover {
+ background-color: @surfaceBright;
+}
+
+menu > menuitem:hover > label {
+ color: @onSurface;
+}
+
+/*
+ * โโ logo โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+#logo {
+ background-color: @surfaceContainer;
+ border-radius: 100px;
+ padding: 0px 10px 0px 10px;
+}
+
+#logo-name {
+ color: darker(@primary);
+}
+
+#logo:hover {
+ background-color: @surfaceBright;
+ box-shadow: 0px 3px 3px -2px rgba(0, 0, 0, 0.2);
+}
+
+/*
+ * โโ applets โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#applets {
+ background-color: @surfaceContainer;
+ border-radius: 100px;
+ padding: 2px 10px 2px 10px;
+ margin: 0px;
+}
+
+#applets .icon {
+ color: @onSurface;
+ font-weight: 900;
+}
+
+#applets > button {
+ color: @onSurface;
+ margin: 0px;
+ padding: 0px;
+}
+
+/*
+ * โโ taskbar โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#taskbar {
+ border-radius: 100px;
+ color: @onSurface;
+ background: @surfaceContainer;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+#taskbar > button.activated {
+ border-radius: 100px;
+ background: @surfaceVariant;
+}
+
+#taskbar > button:hover {
+ background: @surfaceBright;
+}
+
+#taskbar > button {
+ padding: 0px 4px;
+ margin: 4px 0px;
+ border-radius: 100px;
+ border: 0px;
+}
+
+#taskbar > button:last-child {
+ margin-right: 0px;
+}
+
+#progress {
+ color: lighter(@outlineVariant);
+ border: 1px solid @primary;
+}
+
+#recording-indicator {
+ padding: 6px 12px 6px 12px;
+ border-radius: 99px;
+}
+
+#recording-indicator {
+ animation: error 0.8s linear infinite alternate;
+}
+
+@keyframes error {
+ to {
+ background-color: @onError;
+ }
+}
diff --git a/styles/launcher.css b/styles/launcher.css
new file mode 100644
index 0000000..9daaeef
--- /dev/null
+++ b/styles/launcher.css
@@ -0,0 +1,327 @@
+/*
+ * โโ launcher โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#launcher {
+ margin: 18px;
+ border: 1px solid @outlineVariant;
+ background-color: @surface;
+ border-radius: 24px;
+ padding: 18px;
+ transition: all 0.5s cubic-bezier(0.5, 0.25, 0, 1);
+}
+
+#launcher entry {
+ transition: all 0.1s ease;
+ border-radius: 11px;
+ padding: 10px;
+ margin: 12px;
+ box-shadow: inset 0 0 0 1px @outlineVariant;
+}
+
+#launcher-content.wallpapers {
+ padding: 16px;
+ min-height: 420px;
+ min-width: 620px;
+}
+
+#launcer-content.cliphist {
+ min-height: 420px;
+}
+
+#launcher-content.bluetooth {
+ min-height: 464px;
+ min-width: 464px;
+}
+
+#launcher-content.power {
+ min-height: 52px;
+}
+
+#launcher-content {
+ min-width: 420px;
+}
+
+#app-launcher,
+#wallpapers,
+#todo,
+#bluetooth,
+#sh,
+#cliphist,
+#emoji,
+#powermenu {
+ transition: all 0.25s cubic-bezier(0.5, 0.25, 0, 1);
+}
+
+#toggle-launcher-button {
+ background-color: @secondaryContainer;
+ color: @onSecondaryContainer;
+ margin: 11px;
+ margin-left: 0px;
+ min-width: 54px;
+ min-height: 44px;
+ border-radius: 100%;
+}
+
+#clear-launcher-button {
+ background-color: @secondaryContainer;
+ color: @onSecondaryContainer;
+ margin: 11px;
+ margin-left: 0px;
+ min-width: 44px;
+ min-height: 44px;
+ border-radius: 100%;
+}
+
+/*
+ * โโ applauncher โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#launcher-app {
+ border-radius: 16px;
+ padding: 16px;
+ transition: padding 0.25s cubic-bezier(0.5, 0.25, 0, 1);
+}
+
+#launcher-app:hover image,
+#launcher-app:active image,
+#launcher-app:selected image,
+#launcher-app.selected image,
+#launcher-app:focus image {
+ -gtk-icon-shadow: 2px 2px @primary;
+}
+
+#launcher-app:hover,
+#launcher-app:active,
+#launcher-app.selected,
+#launcher-app:selected,
+#launcher-app:focus {
+ text-shadow: 2pt 2pt 2pt @primary;
+}
+
+#launcher-app-icon {
+ margin-right: 8px;
+}
+
+/*
+ * โโ wallpaper โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#wallpaper-icons:selected {
+ background-color: @surfaceBright;
+ border-radius: 8px;
+}
+
+#wallpaper-icons:hover {
+ background-color: @surfaceBright;
+ border-radius: 8px;
+}
+
+#dropdown-box {
+ background-color: @surface;
+ box-shadow: inset 0 0 0 1px @outlineVariant;
+ border-radius: 11px;
+ padding: 10px;
+ margin: 12px;
+}
+
+#scheme-dropdown {
+ font-weight: bold;
+}
+
+/*
+ * โโ emoji โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#launcher button#emoji-item {
+ border-radius: 11px;
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ padding: 0px;
+}
+
+#launcher button#emoji-item label {
+ font-size: 24px;
+}
+
+#launcher button#emoji-item:hover,
+#launcher button#emoji-item:focus {
+ text-shadow: 2px 2px 2px @primary;
+}
+
+/*
+ * โโ powermenu โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#powermenu-button {
+ border-radius: 20px;
+ padding: 20px;
+}
+
+#powermenu-button:hover,
+#powermenu-button:focus {
+ background-color: @surfaceBright;
+}
+
+#powermenu-button:active {
+ background-color: @primary;
+}
+
+/*
+ * โโ cliphist โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+#cliphist-history {
+ min-height: 420px;
+}
+
+#launcher button#clip-img-item {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ border-radius: 8px;
+ min-width: 70px;
+ min-height: 70px;
+}
+
+#launcher button#clip-img-item:hover,
+#launcher button#clip-img-item:focus {
+ box-shadow: 2px 2px 2px @primary;
+}
+
+#launcher button#clip-item {
+ border-radius: 11px;
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ padding: 6px;
+}
+
+#launcher button#clip-item {
+ font-size: 30px;
+}
+
+#launcher button#clip-item:hover,
+#launcher button#clip-item:focus {
+ text-shadow: 2px 2px 2px @primary;
+}
+
+/*
+ * โโ todo โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+#todo-content {
+ min-height: 250px;
+}
+
+#todo-launcher {
+ background-color: @surface;
+ padding: 10px;
+ border-radius: 8px;
+}
+
+#todo-item {
+ padding: 8px;
+ border-radius: 4px;
+ background-color: alpha(@surface, 0.8);
+}
+
+#todo-label {
+ color: @primary;
+}
+
+#todo-label-completed {
+ color: alpha(@outlineVariant, 0.5);
+ text-decoration: line-through;
+}
+
+#delete-button {
+ color: @error;
+}
+
+/*
+ * โโ sh runner โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#launcher button#sh-item {
+ border-radius: 11px;
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ padding: 0px;
+}
+
+#launcher button#sh-item {
+ font-size: 24px;
+}
+
+#launcher button#sh-item:hover,
+#launcher button#sh-item:focus {
+ text-shadow: 2px 2px 2px @primary;
+}
+
+/*
+ * โโ bluetooth โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#bluetooth-header {
+ background-color: @surfaceContainer;
+ padding: 4px;
+ border-radius: 20px;
+}
+
+#bluetooth-device {
+ background-color: @secondaryContainer;
+ border-radius: 16px;
+ padding: 4px;
+ margin-bottom: 4px;
+}
+
+#bluetooth-scan,
+#bluetooth-toggle {
+ background-color: @secondaryContainer;
+ margin-left: 0px;
+ min-width: 44px;
+ min-height: 44px;
+ border-radius: 100%;
+}
+
+#bluetooth-scan:hover,
+#bluetooth-toggle:hover {
+ background-color: @surfaceBright;
+}
+
+#bluetooth-scan label,
+#bluetooth-toggle label {
+ font-weight: bold;
+}
+
+#bluetooth-text,
+#bluetooth-section {
+ font-weight: bold;
+}
+
+#bluetooth-text {
+ color: @primary;
+}
+
+#bluetooth-connection {
+ font-size: 20px;
+}
+
+#bluetooth-connect {
+ background-color: @surface;
+ border-radius: 16px;
+ padding: 8px 16px;
+}
+
+#bluetooth-connect:hover {
+ background-color: @surfaceBright;
+}
+
+#bluetooth-paired,
+#bluetooth-available {
+ background-color: @surfaceContainer;
+ padding: 4px;
+ border-radius: 20px;
+ min-height: 200px;
+}
diff --git a/styles/main.css b/styles/main.css
new file mode 100644
index 0000000..a971d02
--- /dev/null
+++ b/styles/main.css
@@ -0,0 +1,69 @@
+@import url(../../.cache/material/colors.css);
+@import "./bar.css";
+@import "./notification.css";
+@import "./osd.css";
+@import "./launcher.css";
+
+* {
+ all: unset;
+ color: @foreground;
+ font-size: 16px;
+ font-family: "Product Sans", Roboto, "Font Awesome 6 Free", Helvetica, Arial,
+ sans-serif;
+}
+
+/*
+ * โโ corner โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#corner {
+ background-color: @surface;
+ border-radius: 0;
+}
+
+#corner-container {
+ min-width: 20px;
+ min-height: 20px;
+}
+
+/*
+ * โโ tooltip โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+tooltip {
+ background-color: @surfaceContainer;
+ border-radius: 10px;
+ padding: 6px 10px;
+ outline: none;
+ border: none;
+ box-shadow: none;
+ animation: tooltipShow 0.25s cubic-bezier(0.5, 0.25, 0, 1);
+}
+
+tooltip label {
+ color: @onSurface;
+ outline: none;
+ border: none;
+ box-shadow: none;
+ font-weight: normal;
+}
+
+@keyframes tooltipShow {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+/*
+ * โโ icon โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+*/
+
+#material_icon,
+#material_icon * {
+ all: unset;
+ font-family: "Material Symbols Outlined", "Material Symbols Sharp";
+}
diff --git a/styles/notification.css b/styles/notification.css
new file mode 100644
index 0000000..b1ba83c
--- /dev/null
+++ b/styles/notification.css
@@ -0,0 +1,60 @@
+#notification {
+ padding: 16px;
+ border: solid 1px @outlineVariant;
+ border-radius: 20px;
+ margin-bottom: 12px;
+ background-color: @surfaceContainerLow;
+ min-width: 350px;
+}
+
+.notification-header .summary {
+ font-size: 0.92rem;
+ font-weight: bold;
+}
+
+.notification-body .body {
+ color: darker(@foreground);
+ font-weight: 600;
+ font-size: 0.92rem;
+}
+
+#notification .close-button {
+ border-radius: 100px;
+}
+
+#notification .close-button:hover {
+ background: alpha(@foreground, 0.2);
+ transition: background 0.15s ease-in-out;
+ border-radius: 100px;
+}
+
+#notification-action-button button.start-action {
+ margin-left: 0;
+}
+
+#notification-action-button button.end-action {
+ margin-right: 0;
+}
+
+#notification-action-buttons button {
+ padding: 0.6rem;
+ font-weight: 600;
+ border-radius: 100px;
+ background-color: transparent;
+}
+#notification-action-buttons button:hover {
+ background-color: lighter(@outlineVariant);
+}
+
+#notification-icon {
+ margin-right: 5px;
+}
+
+.image {
+ border-radius: 30px;
+}
+
+#notification-circular-progress-bar {
+ border: solid 0px @outlineVariant;
+ color: transparent;
+}
diff --git a/styles/osd.css b/styles/osd.css
new file mode 100644
index 0000000..f86f4e2
--- /dev/null
+++ b/styles/osd.css
@@ -0,0 +1,42 @@
+#osd {
+ background: @surfaceContainer;
+ padding: 10px 4px 10px 4px;
+ border-radius: 14px;
+ margin-bottom: 16px;
+ min-width: 190px;
+}
+
+#osd scale {
+ min-width: 150px;
+}
+
+#osd slider {
+ color: @onPrimary;
+ background-color: @primary;
+ background-size: 20px 20px;
+ min-width: 5px;
+ min-height: 14px;
+ border-radius: 100px;
+ padding: 0px;
+ background-repeat: no-repeat;
+ background-position: center;
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: -16px;
+ margin-bottom: -16px;
+ box-shadow:
+ -4px 0px 0px 1px @surfaceContainer,
+ 4px 0px 0px 1px @surfaceContainer;
+}
+
+#osd trough {
+ background: @secondaryContainer;
+ min-height: 10px;
+ margin-right: 4px;
+ border-radius: 100px;
+}
+
+#osd highlight {
+ border-radius: 100px 0px 0px 100px;
+ background: @primary;
+}