diff --git a/README.md b/.github/README.md similarity index 100% rename from README.md rename to .github/README.md diff --git a/_locales/am/messages.json b/_locales/am/messages.json index 2132f13..731646d 100644 --- a/_locales/am/messages.json +++ b/_locales/am/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ar/messages.json b/_locales/ar/messages.json index 2132f13..731646d 100644 --- a/_locales/ar/messages.json +++ b/_locales/ar/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/bg/messages.json b/_locales/bg/messages.json index 2132f13..731646d 100644 --- a/_locales/bg/messages.json +++ b/_locales/bg/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/bn/messages.json b/_locales/bn/messages.json new file mode 100644 index 0000000..731646d --- /dev/null +++ b/_locales/bn/messages.json @@ -0,0 +1,95 @@ +{ + "areYouSureYouWantToExportTheData": { + "message": "Are you sure you want to export the data?" + }, + "areYouSureYouWantToImportTheData": { + "message": "Are you sure you want to import the data?" + }, + "black": { + "message": "Black" + }, + "cancel": { + "message": "Cancel" + }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, + "create": { + "message": "Create" + }, + "dark": { + "message": "Dark" + }, + "dataExportedSuccessfully": { + "message": "Data exported successfully" + }, + "dataImportedSuccessfully": { + "message": "Data imported successfully" + }, + "decryption": { + "message": "Decryption" + }, + "description": { + "message": "With the To-Do extension you get a simple popup to capture your ideas, goals and daily tasks." + }, + "encryption": { + "message": "Encryption" + }, + "export": { + "message": "Export" + }, + "icons": { + "message": "Icons" + }, + "import": { + "message": "Import" + }, + "language": { + "message": "Language" + }, + "light": { + "message": "Light" + }, + "lists": { + "message": "Lists" + }, + "myTasks": { + "message": "My tasks" + }, + "newList": { + "message": "New list" + }, + "newTask": { + "message": "New task" + }, + "noLists": { + "message": "No lists" + }, + "noTasks": { + "message": "No tasks" + }, + "ok": { + "message": "OK" + }, + "password": { + "message": "Password" + }, + "remove": { + "message": "Remove" + }, + "rename": { + "message": "Rename" + }, + "selectFile": { + "message": "Select file" + }, + "theme": { + "message": "Theme" + } +} \ No newline at end of file diff --git a/_locales/ca/messages.json b/_locales/ca/messages.json index 2132f13..731646d 100644 --- a/_locales/ca/messages.json +++ b/_locales/ca/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/cs/messages.json b/_locales/cs/messages.json index 2132f13..731646d 100644 --- a/_locales/cs/messages.json +++ b/_locales/cs/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/da/messages.json b/_locales/da/messages.json index 2132f13..731646d 100644 --- a/_locales/da/messages.json +++ b/_locales/da/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 6e565e9..7063f31 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Erstellen" }, @@ -35,6 +44,9 @@ "export": { "message": "Exportieren" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Importieren" }, diff --git a/_locales/el/messages.json b/_locales/el/messages.json index 2132f13..731646d 100644 --- a/_locales/el/messages.json +++ b/_locales/el/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 2132f13..731646d 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 2132f13..731646d 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/et/messages.json b/_locales/et/messages.json index 2132f13..731646d 100644 --- a/_locales/et/messages.json +++ b/_locales/et/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/fa/messages.json b/_locales/fa/messages.json index 2132f13..731646d 100644 --- a/_locales/fa/messages.json +++ b/_locales/fa/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/fi/messages.json b/_locales/fi/messages.json index 2132f13..731646d 100644 --- a/_locales/fi/messages.json +++ b/_locales/fi/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/fil/messages.json b/_locales/fil/messages.json index 2132f13..731646d 100644 --- a/_locales/fil/messages.json +++ b/_locales/fil/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 2132f13..731646d 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/gu/messages.json b/_locales/gu/messages.json index 2132f13..731646d 100644 --- a/_locales/gu/messages.json +++ b/_locales/gu/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/he/messages.json b/_locales/he/messages.json index 2132f13..731646d 100644 --- a/_locales/he/messages.json +++ b/_locales/he/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index 2132f13..731646d 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/hin/messages.json b/_locales/hin/messages.json new file mode 100644 index 0000000..731646d --- /dev/null +++ b/_locales/hin/messages.json @@ -0,0 +1,95 @@ +{ + "areYouSureYouWantToExportTheData": { + "message": "Are you sure you want to export the data?" + }, + "areYouSureYouWantToImportTheData": { + "message": "Are you sure you want to import the data?" + }, + "black": { + "message": "Black" + }, + "cancel": { + "message": "Cancel" + }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, + "create": { + "message": "Create" + }, + "dark": { + "message": "Dark" + }, + "dataExportedSuccessfully": { + "message": "Data exported successfully" + }, + "dataImportedSuccessfully": { + "message": "Data imported successfully" + }, + "decryption": { + "message": "Decryption" + }, + "description": { + "message": "With the To-Do extension you get a simple popup to capture your ideas, goals and daily tasks." + }, + "encryption": { + "message": "Encryption" + }, + "export": { + "message": "Export" + }, + "icons": { + "message": "Icons" + }, + "import": { + "message": "Import" + }, + "language": { + "message": "Language" + }, + "light": { + "message": "Light" + }, + "lists": { + "message": "Lists" + }, + "myTasks": { + "message": "My tasks" + }, + "newList": { + "message": "New list" + }, + "newTask": { + "message": "New task" + }, + "noLists": { + "message": "No lists" + }, + "noTasks": { + "message": "No tasks" + }, + "ok": { + "message": "OK" + }, + "password": { + "message": "Password" + }, + "remove": { + "message": "Remove" + }, + "rename": { + "message": "Rename" + }, + "selectFile": { + "message": "Select file" + }, + "theme": { + "message": "Theme" + } +} \ No newline at end of file diff --git a/_locales/hr/messages.json b/_locales/hr/messages.json index 2132f13..731646d 100644 --- a/_locales/hr/messages.json +++ b/_locales/hr/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json index 2132f13..731646d 100644 --- a/_locales/hu/messages.json +++ b/_locales/hu/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/id/messages.json b/_locales/id/messages.json index 2132f13..731646d 100644 --- a/_locales/id/messages.json +++ b/_locales/id/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 2132f13..731646d 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index 2132f13..731646d 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/kn/messages.json b/_locales/kn/messages.json index 2132f13..731646d 100644 --- a/_locales/kn/messages.json +++ b/_locales/kn/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index 2132f13..731646d 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/lt/messages.json b/_locales/lt/messages.json index 2132f13..731646d 100644 --- a/_locales/lt/messages.json +++ b/_locales/lt/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/lv/messages.json b/_locales/lv/messages.json index 2132f13..731646d 100644 --- a/_locales/lv/messages.json +++ b/_locales/lv/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ml/messages.json b/_locales/ml/messages.json index 2132f13..731646d 100644 --- a/_locales/ml/messages.json +++ b/_locales/ml/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/mr/messages.json b/_locales/mr/messages.json index 2132f13..731646d 100644 --- a/_locales/mr/messages.json +++ b/_locales/mr/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ms/messages.json b/_locales/ms/messages.json index 2132f13..731646d 100644 --- a/_locales/ms/messages.json +++ b/_locales/ms/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/nb_NO/messages.json b/_locales/nb_NO/messages.json new file mode 100644 index 0000000..731646d --- /dev/null +++ b/_locales/nb_NO/messages.json @@ -0,0 +1,95 @@ +{ + "areYouSureYouWantToExportTheData": { + "message": "Are you sure you want to export the data?" + }, + "areYouSureYouWantToImportTheData": { + "message": "Are you sure you want to import the data?" + }, + "black": { + "message": "Black" + }, + "cancel": { + "message": "Cancel" + }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, + "create": { + "message": "Create" + }, + "dark": { + "message": "Dark" + }, + "dataExportedSuccessfully": { + "message": "Data exported successfully" + }, + "dataImportedSuccessfully": { + "message": "Data imported successfully" + }, + "decryption": { + "message": "Decryption" + }, + "description": { + "message": "With the To-Do extension you get a simple popup to capture your ideas, goals and daily tasks." + }, + "encryption": { + "message": "Encryption" + }, + "export": { + "message": "Export" + }, + "icons": { + "message": "Icons" + }, + "import": { + "message": "Import" + }, + "language": { + "message": "Language" + }, + "light": { + "message": "Light" + }, + "lists": { + "message": "Lists" + }, + "myTasks": { + "message": "My tasks" + }, + "newList": { + "message": "New list" + }, + "newTask": { + "message": "New task" + }, + "noLists": { + "message": "No lists" + }, + "noTasks": { + "message": "No tasks" + }, + "ok": { + "message": "OK" + }, + "password": { + "message": "Password" + }, + "remove": { + "message": "Remove" + }, + "rename": { + "message": "Rename" + }, + "selectFile": { + "message": "Select file" + }, + "theme": { + "message": "Theme" + } +} \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index 2132f13..731646d 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/no/messages.json b/_locales/no/messages.json index 2132f13..731646d 100644 --- a/_locales/no/messages.json +++ b/_locales/no/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index 2132f13..731646d 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index 2132f13..731646d 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/pt_PT/messages.json b/_locales/pt_PT/messages.json index 2132f13..731646d 100644 --- a/_locales/pt_PT/messages.json +++ b/_locales/pt_PT/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ro/messages.json b/_locales/ro/messages.json index 2132f13..731646d 100644 --- a/_locales/ro/messages.json +++ b/_locales/ro/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 3669be0..6fc8d0a 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Отмена" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Создать" }, @@ -35,6 +44,9 @@ "export": { "message": "Экспорт" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Импорт" }, diff --git a/_locales/sk/messages.json b/_locales/sk/messages.json index 2132f13..731646d 100644 --- a/_locales/sk/messages.json +++ b/_locales/sk/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/sl/messages.json b/_locales/sl/messages.json index 2132f13..731646d 100644 --- a/_locales/sl/messages.json +++ b/_locales/sl/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/sr/messages.json b/_locales/sr/messages.json index 2132f13..731646d 100644 --- a/_locales/sr/messages.json +++ b/_locales/sr/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index 2132f13..731646d 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/sw/messages.json b/_locales/sw/messages.json index 2132f13..731646d 100644 --- a/_locales/sw/messages.json +++ b/_locales/sw/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/ta/messages.json b/_locales/ta/messages.json index 2132f13..731646d 100644 --- a/_locales/ta/messages.json +++ b/_locales/ta/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/te/messages.json b/_locales/te/messages.json index 2132f13..731646d 100644 --- a/_locales/te/messages.json +++ b/_locales/te/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/th/messages.json b/_locales/th/messages.json index 2132f13..731646d 100644 --- a/_locales/th/messages.json +++ b/_locales/th/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json new file mode 100644 index 0000000..731646d --- /dev/null +++ b/_locales/tr/messages.json @@ -0,0 +1,95 @@ +{ + "areYouSureYouWantToExportTheData": { + "message": "Are you sure you want to export the data?" + }, + "areYouSureYouWantToImportTheData": { + "message": "Are you sure you want to import the data?" + }, + "black": { + "message": "Black" + }, + "cancel": { + "message": "Cancel" + }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, + "create": { + "message": "Create" + }, + "dark": { + "message": "Dark" + }, + "dataExportedSuccessfully": { + "message": "Data exported successfully" + }, + "dataImportedSuccessfully": { + "message": "Data imported successfully" + }, + "decryption": { + "message": "Decryption" + }, + "description": { + "message": "With the To-Do extension you get a simple popup to capture your ideas, goals and daily tasks." + }, + "encryption": { + "message": "Encryption" + }, + "export": { + "message": "Export" + }, + "icons": { + "message": "Icons" + }, + "import": { + "message": "Import" + }, + "language": { + "message": "Language" + }, + "light": { + "message": "Light" + }, + "lists": { + "message": "Lists" + }, + "myTasks": { + "message": "My tasks" + }, + "newList": { + "message": "New list" + }, + "newTask": { + "message": "New task" + }, + "noLists": { + "message": "No lists" + }, + "noTasks": { + "message": "No tasks" + }, + "ok": { + "message": "OK" + }, + "password": { + "message": "Password" + }, + "remove": { + "message": "Remove" + }, + "rename": { + "message": "Rename" + }, + "selectFile": { + "message": "Select file" + }, + "theme": { + "message": "Theme" + } +} \ No newline at end of file diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index 2132f13..731646d 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/vi/messages.json b/_locales/vi/messages.json index 2132f13..731646d 100644 --- a/_locales/vi/messages.json +++ b/_locales/vi/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 2132f13..731646d 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index 2132f13..731646d 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -11,6 +11,15 @@ "cancel": { "message": "Cancel" }, + "changeColor": { + "message": "Change color" + }, + "changeIcon": { + "message": "Change icon" + }, + "color": { + "message": "Color" + }, "create": { "message": "Create" }, @@ -35,6 +44,9 @@ "export": { "message": "Export" }, + "icons": { + "message": "Icons" + }, "import": { "message": "Import" }, diff --git a/assets/data/color.js b/assets/data/color.js new file mode 100644 index 0000000..76c518e --- /dev/null +++ b/assets/data/color.js @@ -0,0 +1,12 @@ +/*-------------------------------------------------------------- +>>> COLOR +--------------------------------------------------------------*/ + +extension.color = [ + '#f6b465', + '#f56666', + '#7c66f5', + '#66c0f5', + '#66f5b3', + '#b1f566' +]; \ No newline at end of file diff --git a/assets/data/icons.js b/assets/data/icons.js new file mode 100644 index 0000000..f9d333e --- /dev/null +++ b/assets/data/icons.js @@ -0,0 +1,27 @@ +/*-------------------------------------------------------------- +>>> ICONS +--------------------------------------------------------------*/ + +extension.icons = { + folder: 'M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z', + home: 'M6 21q-.825 0-1.412-.587Q4 19.825 4 19v-9q0-.475.213-.9.212-.425.587-.7l6-4.5q.275-.2.575-.3.3-.1.625-.1t.625.1q.3.1.575.3l6 4.5q.375.275.588.7.212.425.212.9v9q0 .825-.587 1.413Q18.825 21 18 21h-4v-7h-4v7Z', + star: 'M8.3 20.125q-.575.45-1.175.025-.6-.425-.4-1.125L8.15 14.4l-3.625-2.575q-.6-.425-.362-1.125.237-.7.962-.7H9.6l1.45-4.8q.125-.35.388-.538.262-.187.562-.187.3 0 .562.187.263.188.388.538L14.4 10h4.475q.725 0 .963.7.237.7-.363 1.125L15.85 14.4l1.425 4.625q.2.7-.4 1.125-.6.425-1.175-.025L12 17.3Z', + smile: 'M15.5 11q.65 0 1.075-.425Q17 10.15 17 9.5q0-.65-.425-1.075Q16.15 8 15.5 8q-.65 0-1.075.425Q14 8.85 14 9.5q0 .65.425 1.075Q14.85 11 15.5 11Zm-7 0q.65 0 1.075-.425Q10 10.15 10 9.5q0-.65-.425-1.075Q9.15 8 8.5 8q-.65 0-1.075.425Q7 8.85 7 9.5q0 .65.425 1.075Q7.85 11 8.5 11Zm3.5 6.5q1.425 0 2.6-.637 1.175-.638 1.825-1.613.3-.45.088-.85-.213-.4-.663-.4-.175 0-.35.1t-.275.25q-.55.75-1.375 1.2-.825.45-1.85.45-1.025 0-1.85-.45-.825-.45-1.375-1.2-.1-.15-.287-.25-.188-.1-.363-.1-.425 0-.637.387-.213.388.062.813.675 1.025 1.85 1.663 1.175.637 2.6.637Zm0 4.5q-2.075 0-3.9-.788-1.825-.787-3.175-2.137-1.35-1.35-2.137-3.175Q2 14.075 2 12t.788-3.9q.787-1.825 2.137-3.175 1.35-1.35 3.175-2.138Q9.925 2 12 2t3.9.787q1.825.788 3.175 2.138 1.35 1.35 2.137 3.175Q22 9.925 22 12t-.788 3.9q-.787 1.825-2.137 3.175-1.35 1.35-3.175 2.137Q14.075 22 12 22Z', + pet: 'M4.5 12.125q-1.05 0-1.775-.725Q2 10.675 2 9.625q0-1.05.725-1.775.725-.725 1.775-.725 1.05 0 1.775.725Q7 8.575 7 9.625q0 1.05-.725 1.775-.725.725-1.775.725Zm4.5-4q-1.05 0-1.775-.725Q6.5 6.675 6.5 5.625q0-1.05.725-1.775Q7.95 3.125 9 3.125q1.05 0 1.775.725.725.725.725 1.775 0 1.05-.725 1.775-.725.725-1.775.725Zm6 0q-1.05 0-1.775-.725-.725-.725-.725-1.775 0-1.05.725-1.775.725-.725 1.775-.725 1.05 0 1.775.725.725.725.725 1.775 0 1.05-.725 1.775-.725.725-1.775.725Zm4.5 4q-1.05 0-1.775-.725Q17 10.675 17 9.625q0-1.05.725-1.775.725-.725 1.775-.725 1.05 0 1.775.725.725.725.725 1.775 0 1.05-.725 1.775-.725.725-1.775.725Zm-12.85 10q-1.125 0-1.887-.863Q4 20.4 4 19.225q0-1.3.888-2.275.887-.975 1.762-1.925.725-.775 1.25-1.688.525-.912 1.25-1.712.55-.65 1.275-1.075.725-.425 1.575-.425t1.575.4q.725.4 1.275 1.05.7.8 1.237 1.725.538.925 1.263 1.725.875.95 1.763 1.925.887.975.887 2.275 0 1.175-.762 2.037-.763.863-1.888.863-1.35 0-2.675-.225-1.325-.225-2.675-.225-1.35 0-2.675.225-1.325.225-2.675.225Z', + idea: 'M12 22q-.65 0-1.175-.312-.525-.313-.825-.838-.825 0-1.412-.587Q8 19.675 8 18.85V15.3q-1.475-.975-2.362-2.575-.888-1.6-.888-3.475 0-3.025 2.112-5.138Q8.975 2 12 2t5.137 2.112Q19.25 6.225 19.25 9.25q0 1.925-.887 3.5-.888 1.575-2.363 2.55v3.55q0 .825-.587 1.413-.588.587-1.413.587-.3.525-.825.838Q12.65 22 12 22Zm-2-3.15h4v-.9h-4Zm0-1.9h4V16h-4ZM11.25 14h1.5v-2.7l1.675-1.675q.225-.225.225-.525 0-.3-.225-.525-.225-.225-.525-.225-.3 0-.5.2L12 9.95l-1.375-1.375Q10.4 8.35 10.1 8.35q-.3 0-.525.225-.225.225-.225.525 0 .3.2.5l1.7 1.7Z', + forest: 'M15 22q-.825 0-1.412-.587Q13 20.825 13 20v-1h4v1q0 .825-.587 1.413Q15.825 22 15 22Zm-6 0q-.825 0-1.412-.587Q7 20.825 7 20v-2H1.825q-.6 0-.875-.525T1 16.45L3.85 12q-.6 0-.85-.538-.25-.537.1-1.037l5.075-7.25q.3-.425.825-.425.525 0 .825.425l5.075 7.25q.35.5.1 1.037-.25.538-.85.538L17 16.45q.275.425.013.988-.263.562-.838.562H11v2q0 .825-.587 1.413Q9.825 22 9 22Zm8.875-4q.25-.25.337-.837.088-.588-.212-1.063l-2.375-3.725q.375-.35.475-1.088.1-.737-.3-1.312l-3.175-4.55 1.55-2.25q.3-.425.825-.425.525 0 .825.425l5.075 7.25q.35.5.1 1.037-.25.538-.85.538L23 16.45q.325.5.05 1.025-.275.525-.875.525Z', + mail: 'M4 20q-.825 0-1.412-.587Q2 18.825 2 18V6q0-.825.588-1.412Q3.175 4 4 4h16q.825 0 1.413.588Q22 5.175 22 6v12q0 .825-.587 1.413Q20.825 20 20 20Zm8-7.175q.125 0 .262-.038.138-.037.263-.112L19.6 8.25q.2-.125.3-.312.1-.188.1-.413 0-.5-.425-.75T18.7 6.8L12 11 5.3 6.8q-.45-.275-.875-.013Q4 7.05 4 7.525q0 .25.1.437.1.188.3.288l7.075 4.425q.125.075.263.112.137.038.262.038Z', + call: 'M19.95 21q-3.225 0-6.287-1.438-3.063-1.437-5.425-3.8-2.363-2.362-3.8-5.425Q3 7.275 3 4.05q0-.45.3-.75t.75-.3H8.1q.35 0 .625.225t.325.575l.65 3.5q.05.35-.012.637-.063.288-.288.513L7 10.9q1.05 1.8 2.625 3.375T13.1 17l2.35-2.35q.225-.225.588-.338.362-.112.712-.062l3.45.7q.35.075.575.337.225.263.225.613v4.05q0 .45-.3.75t-.75.3Z', + hearth: 'm12 21-1.45-1.3q-3.925-3.5-6.238-6.088Q2 11.025 2 8.15 2 5.8 3.575 4.225 5.15 2.65 7.5 2.65q1.325 0 2.5.562 1.175.563 2 1.538.825-.975 2-1.538 1.175-.562 2.5-.562 2.35 0 3.925 1.575Q22 5.8 22 8.15q0 2.875-2.312 5.462Q17.375 16.2 13.45 19.7Z', + shopping: 'M7 22q-.825 0-1.412-.587Q5 20.825 5 20q0-.825.588-1.413Q6.175 18 7 18t1.412.587Q9 19.175 9 20q0 .825-.588 1.413Q7.825 22 7 22Zm10 0q-.825 0-1.412-.587Q15 20.825 15 20q0-.825.588-1.413Q16.175 18 17 18t1.413.587Q19 19.175 19 20q0 .825-.587 1.413Q17.825 22 17 22ZM6.15 6l2.4 5h7l2.75-5ZM5.2 4h14.75q.675 0 .925.5t-.025 1.05l-3.55 6.4q-.275.5-.725.775-.45.275-1.025.275H8.1L7 15h12v2H7q-1.125 0-1.7-.988-.575-.987-.05-1.962L6.6 11.6 3 4H1V2h3.25Zm3.35 7-2.4-5H18.3l-2.75 5Z', + money: 'M11.025 21v-2.15q-1.325-.3-2.287-1.15-.963-.85-1.413-2.4l1.85-.75q.375 1.2 1.113 1.825.737.625 1.937.625 1.025 0 1.738-.462.712-.463.712-1.438 0-.875-.55-1.388-.55-.512-2.55-1.162-2.15-.675-2.95-1.612-.8-.938-.8-2.288 0-1.625 1.05-2.525 1.05-.9 2.15-1.025V3h2v2.1q1.25.2 2.063.912.812.713 1.187 1.738l-1.85.8q-.3-.8-.85-1.2-.55-.4-1.5-.4-1.1 0-1.675.488-.575.487-.575 1.212 0 .825.75 1.3.75.475 2.6 1 1.725.5 2.613 1.587.887 1.088.887 2.513 0 1.775-1.05 2.7-1.05.925-2.6 1.15V21Z', + notify: 'M3 10q-.425 0-.712-.3Q2 9.4 2.05 9q.175-1.65.863-3.163.687-1.512 1.812-2.712.275-.275.7-.275.425 0 .725.3.275.275.275.675t-.275.725q-.875.95-1.412 2.062Q4.2 7.725 4.05 9q-.05.425-.337.712Q3.425 10 3 10Zm18 0q-.4 0-.7-.288-.3-.287-.35-.712-.15-1.275-.687-2.388Q18.725 5.5 17.85 4.55q-.275-.325-.275-.725 0-.4.3-.675.3-.3.712-.3.413 0 .688.275 1.125 1.2 1.813 2.712.687 1.513.862 3.163.05.4-.238.7-.287.3-.712.3ZM5 19q-.425 0-.713-.288Q4 18.425 4 18t.287-.712Q4.575 17 5 17h1v-7q0-2.075 1.25-3.688Q8.5 4.7 10.5 4.2v-.7q0-.625.438-1.062Q11.375 2 12 2t1.062.438q.438.437.438 1.062v.7q2 .5 3.25 2.112Q18 7.925 18 10v7h1q.425 0 .712.288.288.287.288.712t-.288.712Q19.425 19 19 19Zm7 3q-.825 0-1.412-.587Q10 20.825 10 20h4q0 .825-.587 1.413Q12.825 22 12 22Z', + food: 'M18 22q-.425 0-.712-.288Q17 21.425 17 21v-7h-1q-.825 0-1.412-.588Q14 12.825 14 12V7q0-2.075 1.463-3.537Q16.925 2 19 2v19q0 .425-.288.712Q18.425 22 18 22ZM8 22q-.425 0-.713-.288Q7 21.425 7 21v-8.15q-1.275-.35-2.137-1.4Q4 10.4 4 9V3q0-.425.287-.713Q4.575 2 5 2t.713.287Q6 2.575 6 3v6h1V3q0-.425.287-.713Q7.575 2 8 2t.713.287Q9 2.575 9 3v6h1V3q0-.425.288-.713Q10.575 2 11 2t.713.287Q12 2.575 12 3v6q0 1.4-.863 2.45-.862 1.05-2.137 1.4V21q0 .425-.287.712Q8.425 22 8 22Z', + handyman: 'M18.85 21.975q-.2 0-.375-.062-.175-.063-.325-.213l-5.3-5.3v-1l2.525-2.525h1l5.3 5.3q.15.15.213.325.062.175.062.375t-.062.375q-.063.175-.213.325L19.55 21.7q-.15.15-.325.213-.175.062-.375.062Zm0-2.375.725-.725-4.25-4.25-.725.725ZM5.125 22q-.2 0-.387-.075-.188-.075-.338-.225l-2.1-2.1q-.15-.15-.225-.338Q2 19.075 2 18.875t.075-.375q.075-.175.225-.325l5.3-5.3h2.125l.85-.85L6.45 7.9H5.025L2 4.875 4.825 2.05 7.85 5.075V6.5l4.125 4.125 2.9-2.9L13.8 6.65l1.4-1.4h-2.825l-.7-.7L15.225 1l.7.7v2.825l1.4-1.4 3.55 3.55q.45.425.663.975.212.55.212 1.125T21.538 9.9q-.213.55-.663 1L18.75 8.775l-1.4 1.4-1.05-1.05-5.175 5.175v2.1l-5.3 5.3q-.15.15-.325.225-.175.075-.375.075Zm0-2.4 4.25-4.25-.725-.725-4.25 4.25Z', + note: 'M10 21q-1.65 0-2.825-1.175Q6 18.65 6 17q0-1.65 1.175-2.825Q8.35 13 10 13q.575 0 1.062.137.488.138.938.413V5q0-.825.588-1.413Q13.175 3 14 3h2q.825 0 1.413.587Q18 4.175 18 5q0 .825-.587 1.412Q16.825 7 16 7h-2v10q0 1.65-1.175 2.825Q11.65 21 10 21Z', + movie: 'M5 21q-.425 0-.713-.288Q4 20.425 4 20V4q0-.425.287-.713Q4.575 3 5 3t.713.287Q6 3.575 6 4v1h2V4q0-.425.288-.713Q8.575 3 9 3h6q.425 0 .713.287Q16 3.575 16 4v1h2V4q0-.425.288-.713Q18.575 3 19 3t.712.287Q20 3.575 20 4v16q0 .425-.288.712Q19.425 21 19 21t-.712-.288Q18 20.425 18 20v-1h-2v1q0 .425-.287.712Q15.425 21 15 21H9q-.425 0-.712-.288Q8 20.425 8 20v-1H6v1q0 .425-.287.712Q5.425 21 5 21Zm1-4h2v-2H6Zm0-4h2v-2H6Zm0-4h2V7H6Zm10 8h2v-2h-2Zm0-4h2v-2h-2Zm0-4h2V7h-2Z', + car: 'M6 19v.525q0 .625-.425 1.05Q5.15 21 4.5 21q-.625 0-1.062-.438Q3 20.125 3 19.5V12l2.1-6q.15-.45.538-.725Q6.025 5 6.5 5h11q.475 0 .863.275.387.275.537.725l2.1 6v7.525q0 .625-.425 1.05Q20.15 21 19.5 21q-.625 0-1.062-.438Q18 20.125 18 19.5V19Zm-.2-9h12.4l-1.05-3H6.85Zm1.7 6q.625 0 1.062-.438Q9 15.125 9 14.5t-.438-1.062Q8.125 13 7.5 13t-1.062.438Q6 13.875 6 14.5t.438 1.062Q6.875 16 7.5 16Zm9 0q.625 0 1.062-.438Q18 15.125 18 14.5t-.438-1.062Q17.125 13 16.5 13t-1.062.438Q15 13.875 15 14.5t.438 1.062Q15.875 16 16.5 16Z', + school: 'M22 17q-.425 0-.712-.288Q21 16.425 21 16v-5.9l-8.025 4.375q-.225.125-.463.187-.237.063-.512.063t-.512-.063q-.238-.062-.463-.187L2.6 9.875q-.25-.125-.387-.363-.138-.237-.138-.512t.138-.512q.137-.238.387-.363l8.45-4.6q.225-.125.462-.188.238-.062.488-.062t.488.062q.237.063.462.188l9.525 5.2q.25.125.388.362.137.238.137.513V16q0 .425-.288.712Q22.425 17 22 17Zm-10 3.725q-.25 0-.488-.062-.237-.063-.462-.188l-5-2.7q-.5-.275-.775-.737Q5 16.575 5 16v-3.8l5.675 3.075q.325.175.65.312.325.138.675.138.35 0 .688-.15.337-.15.662-.325L19 12.2V16q0 .575-.275 1.038-.275.462-.775.737l-5 2.7q-.225.125-.462.188-.238.062-.488.062Z', + science: 'M5 21q-1.275 0-1.812-1.137-.538-1.138.262-2.113L9 11V5H8q-.425 0-.713-.288Q7 4.425 7 4t.287-.713Q7.575 3 8 3h8q.425 0 .712.287Q17 3.575 17 4t-.288.712Q16.425 5 16 5h-1v6l5.55 6.75q.8.975.262 2.113Q20.275 21 19 21Z', + sport: 'M12.7 21.2q-.275-.275-.275-.7 0-.425.275-.7l2.85-2.85-8.5-8.5L4.2 11.3q-.3.3-.7.287-.4-.012-.7-.312-.3-.3-.3-.713 0-.412.3-.712l.7-.7-.7-.7q-.3-.3-.3-.7 0-.4.3-.7l1.425-1.425L3.5 4.9q-.3-.3-.287-.713.012-.412.312-.712t.713-.3q.412 0 .712.3l.7.725 1.4-1.4q.3-.3.7-.3.4 0 .7.3l.725.725L9.9 2.8q.275-.275.7-.275.425 0 .7.275.275.275.275.7 0 .425-.275.7L8.45 7.05l8.5 8.5 2.85-2.85q.3-.3.713-.3.412 0 .712.3t.3.712q0 .413-.3.713l-.725.725.7.7q.3.3.3.7 0 .4-.3.7l-1.425 1.425.725.725q.3.3.3.7 0 .4-.3.7-.3.3-.712.3-.413 0-.713-.3l-.725-.7-1.4 1.4q-.3.3-.7.3-.4 0-.7-.3l-.725-.725-.725.725q-.275.275-.7.275-.425 0-.7-.275Z' +}; \ No newline at end of file diff --git a/ui/fonts/Roboto-Bold.ttf b/assets/fonts/Roboto-Bold.ttf similarity index 100% rename from ui/fonts/Roboto-Bold.ttf rename to assets/fonts/Roboto-Bold.ttf diff --git a/ui/fonts/Roboto-Medium.ttf b/assets/fonts/Roboto-Medium.ttf similarity index 100% rename from ui/fonts/Roboto-Medium.ttf rename to assets/fonts/Roboto-Medium.ttf diff --git a/ui/fonts/Roboto-Regular.ttf b/assets/fonts/Roboto-Regular.ttf similarity index 100% rename from ui/fonts/Roboto-Regular.ttf rename to assets/fonts/Roboto-Regular.ttf diff --git a/icons/128.png b/assets/icons/128.png similarity index 100% rename from icons/128.png rename to assets/icons/128.png diff --git a/icons/16.png b/assets/icons/16.png similarity index 100% rename from icons/16.png rename to assets/icons/16.png diff --git a/icons/32.png b/assets/icons/32.png similarity index 100% rename from icons/32.png rename to assets/icons/32.png diff --git a/icons/48.png b/assets/icons/48.png similarity index 100% rename from icons/48.png rename to assets/icons/48.png diff --git a/assets/satus/satus.css b/assets/satus/satus.css new file mode 100644 index 0000000..bad90b9 --- /dev/null +++ b/assets/satus/satus.css @@ -0,0 +1,1996 @@ +/*-------------------------------------------------------------- +# SCROLLBAR +--------------------------------------------------------------*/ + +:where([class^='satus'])::-webkit-scrollbar { + width: 4px; +} + +:where([class^='satus'])::-webkit-scrollbar:hover { + width: 8px; +} + +:where([class^='satus'])::-webkit-scrollbar-thumb { + background: rgba(var(--satus-light), .2); +} + +:where([class^='satus'])::-webkit-scrollbar-thumb:hover { + background: rgba(var(--satus-light), .3); +} +/*-------------------------------------------------------------- +# ANIMATIONS +--------------------------------------------------------------*/ + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + transform: translateX(-100%); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + transform: translateX(100%); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(-50%); + } +} + +@keyframes fadeOutRight { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(50%); + } +} + +@keyframes zoomIn { + from { + transform: scale(.8); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +@keyframes zoomOut { + from { + transform: scale(1); + opacity: 1; + } + to { + transform: scale(.8); + opacity: 0; + } +} +/*-------------------------------------------------------------- +>>> THEMES +--------------------------------------------------------------*/ + +body { + --satus-light: 0, 20, 82; + --satus-primary: #ff4158; + + --satus-alert-hue-error: 0; + --satus-alert-hue-success: 200; + + --satus-base-background: #f3f4f6; + --satus-base-foreground: #565e76; + + --satus-checkbox-background: #f3f4f6; + --satus-checkbox-border: #dcdfe5; + --satus-checkbox-foreground: rgb(255, 255, 255, .96); + + --satus-divider: rgba(var(--satus-light),.1); + + --satus-header-background: #fff; + --satus-header-foreground: inherit; + --satus-header-shadow: 0 1px 0 #dcdee5; + + --satus-layers-background: var(--satus-base-background); + --satus-layers-foreground: inherit; + + --satus-section-background: #fff; + --satus-section-border: #dcdee5; + + --satus-sidebar-background: #fff; + --satus-sidebar-foreground: inherit; + --satus-sidebar-shadow: #dcdee5; + + --satus-modal-foreground: inherit; + --satus-modal-background: #fff; + --satus-modal-shadow: 0 1px 4px #7d86a1; + + --satus-tabs-background: rgba(var(--satus-light), .04); + --satus-tabs-foreground: #fff; + + --satus-text-field-background: #edf0f2; + --satus-text-field-border: #dcdee5; + --satus-text-field-color: #7d8ba1; + --satus-text-field-selection: rgb(149, 166, 178, .35); + --satus-text-field-cursor: #fa0; + + --satus-switch-track: #e1e4ea; + --satus-switch-track--checked: var(--satus-primary); + --satus-switch-thumb: #fff; + + --satus-input-text-background: #e8e8e3; + --satus-input-text-border: #d6d6cd; + --satus-input-text-text: #848471; +} +/*-------------------------------------------------------------- +>>> NORMALIZE +--------------------------------------------------------------*/ + +:where([class^='satus']) { + box-sizing: border-box; +} + +:where([class^='satus'])[hidden]:not([hidden='false']) { + display: none; +} + +:where([class^='satus'])[transparent] { + opacity: 0; +} +/*-------------------------------------------------------------- +>>> MODAL +---------------------------------------------------------------- +# Container +# Scrim +# Surface +# Variants + # Vertical menu +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# CONTAINER +--------------------------------------------------------------*/ + +.satus-modal { + position: fixed; + z-index: 9; + top: 0; + left: 0; + display: flex; + width: 100vw; + height: 100vh; + justify-content: center; + align-items: center; +} + + +/*-------------------------------------------------------------- +# SCRIM +--------------------------------------------------------------*/ + +.satus-modal__scrim { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + animation: fadeIn 150ms linear forwards; + opacity: 0; + background: rgba(0, 0, 0, .16); + backdrop-filter: blur(8px); +} + +.satus-modal--closing .satus-modal__scrim { + animation: fadeOut 70ms linear forwards; +} + + +/*-------------------------------------------------------------- +# SURFACE +--------------------------------------------------------------*/ + +.satus-modal__surface { + display: flex; + overflow-y: auto; + flex-direction: column; + box-sizing: border-box; + width: 95%; + min-width: 240px; + max-width: 560px; + max-height: 80%; + margin: 8px; + padding: 12px 16px; + transform: scale(.8); + animation: zoomIn 150ms linear forwards; + animation-delay: 20ms; + opacity: 0; + color: var(--satus-modal-foreground); + border-radius: 3px; + background-color: var(--satus-modal-background); + box-shadow: var(--satus-modal-shadow); +} + +.satus-modal--closing .satus-modal__surface { + animation: zoomOut 70ms linear forwards; +} + +.satus-section--actions { + justify-content: flex-end; +} +.satus-section--actions > *:not(:first-child) { + margin-left: 8px; +} + + +/*-------------------------------------------------------------- +# VARIANTS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# VERTICAL MENU +--------------------------------------------------------------*/ + +.satus-modal--vertical-menu .satus-modal__surface { + position: absolute; + top: 8px; + right: 8px; + left: auto; + min-width: 180px; + max-width: 180px; + margin: 0; + padding: 8px 0; + transform-origin: right top; +} + +.satus-modal--vertical-menu .satus-modal__surface>[class^='satus']:where(:not(.satus-divider)) { + height: 36px; + padding: 0 16px; + border-radius: 0; +} + +.satus-modal--vertical-menu .satus-modal__surface>.satus-span { + font-size: 13px; + font-weight: 500; + margin: 6px 0; + padding: 0 12px; + height: auto; +} + +.satus-modal--vertical-menu .satus-modal__surface>.satus-tabs { + margin: 0 12px; + border-radius: 3px; + height: 26px; + padding: 0; +} + +.satus-modal--vertical-menu .satus-select svg, +.satus-modal--vertical-menu .satus-button svg { + margin: 0 14px 0 0; + opacity: .64; + flex: 0 0 18px; +} + +.satus-modal--vertical-menu .satus-button .satus-span { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.satus-modal--vertical-menu .satus-switch:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-modal--vertical-menu .satus-switch:focus { + background-color: rgba(var(--satus-light), .08); +} +/*-------------------------------------------------------------- +>>> GRID +--------------------------------------------------------------*/ + +.satus-grid { + display: flex; + align-items: stretch; + height: 100%; + padding: 8px; +} +/*-------------------------------------------------------------- +>>> TEXT FIELD +---------------------------------------------------------------- +# Parts + # Container + # Input + # +# Syntax highlighting + # Regular expression +--------------------------------------------------------------*/ + +.satus-text-field { + display: flex; + + min-width: 240px; + height: 36px; + + color: var(--satus-text-field-foreground, inherit); + border-radius: 4px; + background: var(--satus-text-field-background); + + align-items: center; + justify-content: space-between; +} + +.satus-text-field__container { + position: relative; + + overflow: hidden; + + height: 100%; + + flex: 1; +} + +.satus-text-field__textarea { + font: inherit; + + position: absolute; + z-index: 9; + top: 0; + left: 0; + + overflow: auto; + + width: 100%; + min-width: 0; + max-width: none; + height: 100%; + min-height: 0; + max-height: none; + margin: 0; + padding: 0 12px; + + white-space: pre; + + opacity: 0; + color: inherit; + border: none; + border-radius: 4px; + outline: none; + + appearance: none; + overflow-wrap: normal; +} + +.satus-text-field__display { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; +} + +.satus-text-field__line-numbers { + padding: 0 12px 0 0; + + opacity: .5; +} + +.satus-text-field__line-numbers>span { + font-size: inherit; + + display: block; + + width: 100%; + + text-align: right; +} + +.satus-text-field__pre { + font: inherit; + + display: flex; + + margin: 0; +} + +.satus-text-field__hidden-value { + font: inherit; + + position: absolute; + + overflow: auto; + + white-space: pre; + pointer-events: none; + + opacity: 0; + + overflow-wrap: normal; +} + +.satus-text-field__selection { + position: absolute; + top: 0; + left: 0; + + display: none; + + width: 0; + height: 22px; + margin: 6px 12px; + + border: 1px solid var(--satus-text-field-selection); + border-radius: 3px; + background: var(--satus-text-field-selection); +} + +.satus-text-field__cursor { + position: absolute; + top: 0; + left: 0; + + display: none; + + width: 2px; + height: 22px; + margin: -3px 0 0; + + animation: blink 1s step-end 8; + + background: var(--satus-text-field-cursor); +} + +.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__cursor, +.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__selection:not([disabled]) { + display: block; +} + +@keyframes blink { + + from, + to { + opacity: 1; + } + + 50% { + opacity: 0; + } +} + + +/*-------------------------------------------------------------- +# SYNTAX HIGHLIGHTING +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# REGULAR EXPRESSION +--------------------------------------------------------------*/ + +.satus-text-field__pre>.group { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); +} + +.satus-text-field__pre>.character-class { + color: #ffc247; + background-color: rgb(255, 170, 0, .16); +} + +.satus-text-field__pre>.quantifier { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); +} + +.satus-text-field__pre>.anchor { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); +} + +.satus-text-field__pre>.metasequence { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); +} + +.satus-text-field__pre>.text { + color: #c4c4d4; + background-color: rgb(196, 196, 212, .16); +} +/*-------------------------------------------------------------- +>>> CHART +--------------------------------------------------------------*/ + +.satus-chart { + font-size: 90%; + + position: relative; + + height: 128px; + margin: 4px 12px; + + color: rgba(var(--satus-light), .32); + border: 1px dashed rgba(var(--satus-light), .2); + border-top: unset; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} + +.satus-chart__labels { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; + + justify-content: space-between; + align-items: stretch; +} + +.satus-chart__section { + padding: 4px; + + flex: 1; +} + +.satus-chart__section:not(:last-child) { + border-right: 1px dashed rgba(var(--satus-light), .2); +} + + +.satus-chart__bars { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; + + justify-content: space-between; + align-items: stretch; +} + +.satus-chart__bar { + display: flex; + flex-direction: column; + + margin: 0 1px; + + flex: 1; + align-items: center; + justify-content: flex-end; +} + +.satus-chart__piece { + width: 100%; +} + +.satus-chart__piece:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +.satus-select { + position: relative; + + display: flex; + + cursor: pointer; + + align-items: center; + justify-content: space-between; +} + +.satus-select:hover { + background-color: var(--satus-hover); +} + +.satus-select__content { + display: flex; + + flex: 2; + overflow: hidden; + + align-items: center; +} + +.satus-select svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .64; +} + +.satus-select__content .satus-span { + overflow: hidden; + + text-overflow: ellipsis; +} + +.satus-select__value { + display: block; + overflow: hidden; + + flex: 1; + margin-left: 8px; + + text-align: right; + text-overflow: ellipsis; + + opacity: .64; +} + +.satus-select select { + font: inherit; + + position: absolute; + z-index: 1; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + padding: inherit; + + cursor: inherit; + + opacity: 0; + border: none; + outline: none; + + appearance: none; +} + +.satus-select:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-select:focus { + background-color: rgba(var(--satus-light), .08); +} + +.satus-select select::-webkit-scrollbar { + width: 4px; +} + +.satus-select select::-webkit-scrollbar:hover { + width: 8px; +} + +.satus-select select::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, .2); +} + +.satus-select select::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, .3); +} + +.satus-select option { + color: var(--satus-select-text); + background: var(--satus-select-background); +} +/*-------------------------------------------------------------- +>>> DIVIDER +--------------------------------------------------------------*/ + +.satus-divider { + height: 1px; + margin: 16px 0 12px; + background: var(--satus-divider); +} +/*-------------------------------------------------------------- +>>> SECTION +---------------------------------------------------------------- +# Variants + # Align start + # Align end + # Card +# Media +--------------------------------------------------------------*/ + +.satus-section { + display: flex; + + flex-wrap: wrap; +} + + +/*-------------------------------------------------------------- +# ALIGN START +--------------------------------------------------------------*/ + +.satus-section--align-start { + align-items: center; +} + +.satus-section--align-start>*:not(:last-child) { + margin-right: 8px; +} + + +/*-------------------------------------------------------------- +# ALIGN END +--------------------------------------------------------------*/ + +.satus-section--align-end { + align-items: center; + justify-content: flex-end; +} + +.satus-section--align-end>*:not(:first-child) { + margin-left: 8px; +} + + +/*-------------------------------------------------------------- +# CARD +--------------------------------------------------------------*/ + +.satus-section--card { + flex-direction: column; + + max-width: 900px; + margin: 12px; + padding: 8px 0; + + border: 1px solid var(--satus-section-border); + border-radius: 3px; + background: var(--satus-section-background); +} + +.satus-section--transparent-card { + max-width: 900px; + margin: 8px 12px; +} + +.satus-section--card[data-title], +.satus-section--transparent-card[data-title] +{ + position: relative; + + margin-top: 32px; +} + +.satus-section--card[data-title]::before, +.satus-section--transparent-card::before +{ + position: absolute; + top: -8px; + left: 0; + + content: attr(data-title); + transform: translateY(-100%); +} + + +.satus-section--transparent-card > [class^='satus'] { + width: 100%; +} + +.satus-section--card>[class^='satus']:not(.satus-list):not(.satus-section) { + display: flex; + + width: 100%; + min-height: 48px; + padding: 8px 12px; + + transition: background-color .18s cubic-bezier(.25, .8, .5, 1); + text-align: left; + + border-radius: 0; + + align-items: center; +} + +.satus-section--card>[class^='satus']:not(.satus-list):not(.satus-span):hover { + background-color: rgba(var(--satus-light), .06); +} + +.satus-section--card>.satus-button { + justify-content: flex-start; +} + +.satus-section--card>.satus-button>svg, +.satus-section--card>.satus-select>svg +{ + width: 20px; + margin: 0 14px 0 0; + + color: var(--satus-primary); +} + +.satus-section--card>.satus-span { + display: flex; + + align-items: center; +} + +.satus-section--transparent { + background: unset; + border: unset; + padding: 0; + border-radius: unset; +} + + +/*-------------------------------------------------------------- +# MEDIA +--------------------------------------------------------------*/ + +@media (min-width: 901px) { + .satus-section--card, + .satus-section--transparent-card { + margin-left: auto; + margin-right: auto; + } +} +/*-------------------------------------------------------------- +>>> BASE +--------------------------------------------------------------*/ + +.satus-base { + display: flex; + flex-direction: column; + + width: 100%; + height: 100%; + + color: var(--satus-base-foreground); + background: var(--satus-base-background); +} +/*-------------------------------------------------------------- +>>> ALERT +---------------------------------------------------------------- +# Media +--------------------------------------------------------------*/ + +.satus-alert { + display: flex; + min-height: 48px; + margin: 12px; + padding: 8px 12px; + border-radius: 3px; + align-items: center; + max-width: 900px; +} + +.satus-alert--error { + color: hsl(var(--satus-alert-hue-error), 56%, 64%); + border: 1px solid hsl(var(--satus-alert-hue-error), 56%, 28%); + background: hsl(var(--satus-alert-hue-error), 56%, 20%); +} + +.satus-alert--success { + color: hsl(var(--satus-alert-hue-success), 56%, 56%); + border: 1px solid hsl(var(--satus-alert-hue-success), 56%, 26%); + background: hsl(var(--satus-alert-hue-success), 56%, 18%); +} + + +/*-------------------------------------------------------------- +# MEDIA +--------------------------------------------------------------*/ + +@media (min-width: 901px) { + .satus-alert { + margin-left: auto; + margin-right: auto; + } +} +/*-------------------------------------------------------------- +>>> INPUT +--------------------------------------------------------------*/ + +.satus-input[type=text], +.satus-input[type=password] { + font: inherit; + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 0 8px; + color: var(--satus-input-text-foreground, inherit); + border: none; + outline: none; + background: none; + appearance: none; + font-size: 16px; + margin: 8px 0; + border: 1px solid var(--satus-input-text-border); + border-radius: 4px; + background-color: var(--satus-input-text-background); +} +/*-------------------------------------------------------------- +>>> MAIN +--------------------------------------------------------------*/ + +.satus-main { + display: flex; + background: var(--satus-base-background); + flex: 1 +} +/*-------------------------------------------------------------- +>>> SIDEBAR +--------------------------------------------------------------*/ + +.satus-sidebar { + z-index: 1; + display: flex; + flex-direction: column; + width: 56px; + padding: 12px 0; + color: var(--satus-sidebar-foreground); + background: var(--satus-sidebar-background); + box-shadow: 1px 0 0 var(--satus-sidebar-shadow) +} +/*-------------------------------------------------------------- +>>> LAYERS +--------------------------------------------------------------*/ + +.satus-layers { + position: relative; + + overflow: hidden; + + flex: 1; +} + +.satus-layers__layer { + position: absolute; + top: 0; + left: 0; + + overflow: auto; + + width: 100%; + height: 100%; + + color: var(--satus-layers-foreground); + background: var(--satus-layers-background); +} +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +.satus-list { + margin: 0; + + list-style: none; +} + +.satus-list__item { + display: flex; + + min-height: 48px; + padding: 0 16px; + + align-items: center; + justify-content: space-between; +} + +.satus-list__item>*:not(:first-child) { + margin-left: 8px; +} + +.satus-list__item>*:last-child { + font-size: 92%; + + text-align: right; + + opacity: .64; +} +/*-------------------------------------------------------------- +>>> COLOR PICKER: +---------------------------------------------------------------- +# Button +# Modal +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# BUTTON +--------------------------------------------------------------*/ + +.satus-color-picker { + font-size: inherit; + + position: relative; + + display: flex; + + box-sizing: border-box; + margin: 0; + + cursor: pointer; + + color: inherit; + border: none; + outline: none; + background-color: var(--satus-theme-button); + + justify-content: space-between; + -webkit-tap-highlight-color: transparent; + align-items: center; + -webkit-appearance: none; +} + +.satus-color-picker__value { + width: 22px; + height: 22px; + + border: 2px solid rgba(0, 0, 0, .16); + border-radius: 50%; +} + + +/*-------------------------------------------------------------- +# MODAL +--------------------------------------------------------------*/ + +.satus-modal--color-picker .satus-modal__surface { + padding: 8px; +} + +.satus-color-picker__palette { + position: relative; + + overflow: hidden; + + width: 100%; + height: 256px; + margin: 0 0 4px; + + border-radius: 5px; + background-color: #f00; +} + +.satus-color-picker__palette:before { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + content: ''; + + background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent); +} + +.satus-color-picker__cursor { + position: absolute; + + width: 5px; + height: 5px; + + transform: translate(-50%, -50%); + pointer-events: none; + + border: 1px solid #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #000; +} + +.satus-modal--color-picker .satus-modal__surface .satus-section--color { + margin: 8px 4px; + + align-items: center; +} + +.satus-color-picker__color { + width: 32px; + height: 32px; + margin: 0 16px 0 0; + + border: 2px solid rgba(0, 0, 0, .16); + border-radius: 50%; + background: #f00; +} + +.satus-slider.satus-color-picker__hue { + padding: 0; + + flex: 1; +} + +.satus-color-picker__hue .satus-slider__track-container { + height: 16px; + margin: 0; + + border-radius: 4px; + background-image: linear-gradient(90deg, #f00, #ff2a00, #f50, #ff7f00, #fa0, #ffd400, #ff0, #d4ff00, #af0, #80ff00, #5f0, #2bff00, #0f0, #00ff2b, #0f5, #00ff80, #0fa, #00ffd5, #0ff, #00d4ff, #0af, #007fff, #05f, #002bff, #00f, #2a00ff, #50f, #7f00ff, #a0f, #d400ff, #f0f, #ff00d4, #f0a, #ff0080, #f05, #ff002b, #f00); +} + +.satus-color-picker__hue .satus-slider__track-container::before { + display: none; +} + +.satus-color-picker__hue .satus-slider__track { + background: transparent; +} + +.satus-color-picker__hue .satus-slider__track::after { + width: 16px; + height: 16px; + + background: #fff; + box-shadow: 0 0 4px rgb(0, 0, 0, .64); +} +/*-------------------------------------------------------------- +>>> SPAN +--------------------------------------------------------------*/ + +.satus-span--title { + font-weight: 500; + overflow: hidden; + + white-space: nowrap; + text-overflow: ellipsis; + + flex: 1; +} +/*-------------------------------------------------------------- +>>> BUTTON +---------------------------------------------------------------- +# Base +# Basic +# Icon +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# BASE +--------------------------------------------------------------*/ + +.satus-button { + font: inherit; + + position: relative; + + display: inline-flex; + overflow: hidden; + + height: 36px; + padding: 8px; + + transition: background-color .3s cubic-bezier(.25, .8, .5, 1); + + color: inherit; + border: none; + border-radius: 6px; + outline: none; + background: transparent; + + appearance: none; + align-items: center; +} + +.satus-button:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-button:focus { + background-color: rgba(var(--satus-light), .08); +} + +.satus-button svg { + width: 100%; + max-width: 24px; + height: 100%; + max-height: 24px; +} + + +/*-------------------------------------------------------------- +# BASIC +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# ICON +--------------------------------------------------------------*/ + +.satus-button--icon { + width: 40px; + height: 40px; + + border-radius: 50%; +} + +.satus-button--icon svg { + width: 24px; + height: 24px; +} +/*-------------------------------------------------------------- +>>> HEADER +--------------------------------------------------------------*/ + +.satus-header { + z-index: 1; + + display: flex; + + height: 56px; + padding: 0 12px; + + color: var(--satus-header-foreground); + background: var(--satus-header-background); + box-shadow: var(--satus-header-shadow); + + justify-content: space-between; + align-items: center; +} +/*-------------------------------------------------------------- +>>> RADIO +--------------------------------------------------------------*/ + +.satus-radio { + position: relative; + display: flex; +} + +.satus-radio__input { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0; + margin: 0; + z-index: 9; +} + +.satus-radio__content { + flex: 1; + padding: 0 12px; +} + +.satus-radio__i { + width: 16px; + height: 16px; + border: 1px solid rgba(var(--satus-light),.64); + border-radius: 50%; + transition: 200ms; +} + +.satus-radio__input + .satus-radio__i::before { + width: 8px; + height: 8px; + margin: 3px; + border-radius: 50%; + background: var(--satus-primary); + content: ''; + display: block; + transform: scale(0); + transition: 200ms; +} + +.satus-radio__input:checked + .satus-radio__i { + border-color: var(--satus-primary); +} + +.satus-radio__input:checked + .satus-radio__i::before { + background: var(--satus-primary); + transform: scale(1); +} +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +.satus-slider { + display: flex; + + flex-wrap: wrap; +} + +.satus-slider__track-container { + position: relative; + + width: 100%; + height: 20px; + margin: 10px 0 -2px; +} + +.satus-slider__track-container::before { + position: absolute; + top: calc(50% - 1px); + left: 0; + + width: 100%; + height: 2px; + + content: ''; + + opacity: .24; + background: var(--satus-primary); +} + +.satus-slider__input { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + + opacity: 0; +} + +.satus-slider__track { + position: absolute; + top: calc(50% - 1px); + left: 0; + + width: 0; + height: 2px; + + background: var(--satus-primary); + pointer-events: none; +} + +.satus-slider__track::before { + position: absolute; + top: 50%; + right: 0; + transform: translate(50%, -50%); + display: block; + width: 16px; + height: 16px; + content: ''; + transition: width 200ms, height 200ms, opacity 200ms; + opacity: 0; + border-radius: 50%; + background: var(--satus-primary); +} + +.satus-slider__input:focus + .satus-slider__track::before { + width: 24px; + height: 24px; + opacity: .16; +} + +.satus-slider__input:active + .satus-slider__track::before { + width: 26px; + height: 26px; + opacity: .16; +} + +.satus-slider__track::after { + position: absolute; + top: 50%; + right: 0; + transform: translate(50%, -50%); + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: var(--satus-primary); + pointer-events: none; + transition: width 200ms, height 200ms, opacity 200ms; +} + +.satus-slider__input:active + .satus-slider__track::after +{ + width: 12px; + height: 12px; +} + + + + + +.satus-slider--row { + flex-wrap: nowrap; + justify-content: space-between; +} + +.satus-slider--row .satus-slider__track-container { + margin: 0 0 -2px 12px; + max-width: 50%; +} +/*-------------------------------------------------------------- +>>> TABS +--------------------------------------------------------------*/ + +.satus-tabs { + position: relative; + + display: flex; + + border: 2px solid var(--satus-tabs-background); + border-radius: 4px; + background: var(--satus-tabs-background); +} + +.satus-tabs::before { + position: absolute; + top: 0; + left: calc(calc(100% / var(--satus-tabs-count)) * var(--satus-tabs-current)); + + width: calc(100% / var(--satus-tabs-count)); + height: 100%; + + content: ''; + transition: left .25s; + + border-radius: 3px; + background: var(--satus-tabs-foreground); +} + +.satus-tabs__button { + font: inherit; + + position: relative; + z-index: 1; + + overflow: hidden; + + margin: 0; + padding: 0 8px; + + text-overflow: ellipsis; + + color: inherit; + border: none; + border-radius: 3px; + outline: none; + background: transparent; + + flex: 1; + appearance: none; +} +/*-------------------------------------------------------------- +>>> SHORTCUT: +---------------------------------------------------------------- +# +--------------------------------------------------------------*/ + +.satus-shortcut__value { + font-size: 11px; + + display: flex; + + margin-left: 16px; + + text-transform: uppercase; + + align-items: center; + flex: 1; + justify-content: flex-end; +} + +.satus-shortcut__actions { + display: flex; + + justify-content: flex-end; +} + +.satus-shortcut__actions .satus-button { + height: 32px; + margin: 8px 4px 0; + + border-radius: 8px; + background: rgba(0, 0, 0, .15); +} + +.satus-shortcut__actions .satus-button:hover { + background: rgba(0, 0, 0, .25); +} + +.satus-shortcut__primary { + display: flex; + + height: 64px; + margin: 0 0 12px; + padding: 16px; + + border-radius: 3px; + background: rgba(0, 0, 0, .16); + + align-items: center; +} + +.satus-shortcut__key { + display: flex; + + min-width: 32px; + height: 32px; + padding: 4px 8px; + + color: #242424; + border-radius: 4px; + background: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); + + align-items: center; + justify-content: center; +} + +.satus-shortcut__value>.satus-shortcut__key { + font-size: 14px; + + min-width: 24px; + height: 24px; +} + +.satus-shortcut__plus { + position: relative; + + width: 12px; + height: 12px; + margin: 8px; +} + +.satus-shortcut__plus::before { + position: absolute; + top: 0; + left: 5px; + + width: 2px; + height: 12px; + + content: ''; + + background-color: #aaa; +} + +.satus-shortcut__plus::after { + position: absolute; + top: 5px; + left: 0; + + width: 12px; + height: 2px; + + content: ''; + + background-color: #aaa; +} + +.satus-shortcut__mouse { + position: relative; + + display: flex; + + width: 28px; + height: 36px; + + border-radius: 50%; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + background: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); +} + +.satus-shortcut__value>.satus-shortcut__mouse { + width: 22px; + height: 28px; +} + +.satus-shortcut__mouse>div { + position: absolute; + top: 0; + left: calc(50% - 1px); + + width: 2px; + height: 11px; + + border-radius: 2px; + background: #ccc; +} + +.satus-shortcut__mouse::before { + position: absolute; + top: -16%; + right: 14%; + + width: 2px; + height: 60%; + + content: ''; + + background: #f96754; +} + +.satus-shortcut__mouse.false::before { + top: -6%; +} + +.satus-shortcut__mouse.false::after { + position: absolute; + top: -20%; + right: calc(14% - 4px); + + width: 0; + height: 0; + + content: ''; + + border-right: 5px solid transparent; + border-bottom: 8px solid #f96754; + border-left: 5px solid transparent; +} + +.satus-shortcut__mouse.true::after { + position: absolute; + top: 40%; + right: calc(14% - 4px); + + width: 0; + height: 0; + + content: ''; + + border-top: 8px solid #f96754; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.satus-shortcut__mouse.click::before { + position: absolute; + top: 0; + left: -1px; + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: #f96754; +} + +.satus-shortcut__mouse.middle::before { + position: absolute; + z-index: 1; + top: 0; + left: 50%; + + width: 10px; + height: 10px; + + content: ''; + transform: translateX(-50%); + + border-radius: 50%; + background: #f96754; +} + +.satus-shortcut__mouse.context::before { + position: absolute; + top: 0; + left: 15px; + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: #f96754; +} + +.satus-section_shortcut { + width: 100%; + margin: 8px 0 0; + + justify-content: flex-end; +} + +.satus-button_shortcut { + font-weight: 500; + + overflow: hidden; + + height: 28px; + min-height: 28px; + margin-right: 2px; + padding: 4px 8px; + + text-transform: uppercase; + + color: #f96754; + border-radius: 4px; +} +/*-------------------------------------------------------------- +>>> CHECKBOX +--------------------------------------------------------------*/ + +.satus-checkbox { + position: relative; + + display: flex; + + cursor: pointer; + + align-items: center; +} + +.satus-checkbox__input { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + padding: 0; + + opacity: 0; + border: none; + + appearance: none; +} + +.satus-checkbox__checkmark { + position: relative; + + display: flex; + + width: 16px; + min-width: 16px; + height: 16px; + min-height: 16px; + margin: 0 12px 0 0; + + content: ''; + + border: 1px solid var(--satus-checkbox-border); + border-radius: 3px; + background: var(--satus-checkbox-background); +} + +.satus-checkbox[data-value=true] .satus-checkbox__checkmark { + border-color: var(--satus-primary); + background: var(--satus-primary); +} + +.satus-checkbox[data-value=true] .satus-checkbox__checkmark::before { + position: absolute; + top: 3px; + left: 2px; + + width: 8px; + height: 4px; + + content: ''; + transform: rotate(-45deg); + + border: 2px solid var(--satus-checkbox-foreground); + border-top: none; + border-right: none; +} +/*-------------------------------------------------------------- +>>> SWITCH +---------------------------------------------------------------- +# Container +# Track +# Thumb +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# CONTAINER +--------------------------------------------------------------*/ + +.satus-switch { + font: inherit; + + display: flex; + + transition: background-color 75ms; + + color: inherit; + border: none; + outline: none; + background-color: transparent; + + justify-content: space-between; + align-items: center; +} + +.satus-switch:hover { + cursor: pointer; +} + +.satus-switch__content { + display: flex; + + align-items: center; +} + +.satus-switch__content>svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .64; +} + + +/*-------------------------------------------------------------- +# TRACK +--------------------------------------------------------------*/ + +.satus-switch>i { + width: 32px; + height: 18px; + + transition: background-color 150ms; + + border-radius: 18px; + background-color: var(--satus-switch-track); + + flex: 0 0 32px; +} + +.satus-section--card .satus-switch>i { + margin-left: 16px; +} + +.satus-switch[data-value='true']>i { + background-color: var(--satus-switch-track--checked); +} + + +/*-------------------------------------------------------------- +# THUMB +--------------------------------------------------------------*/ + +.satus-switch>i::before { + display: block; + + width: 14px; + height: 14px; + margin: 2px; + + content: ''; + transition: transform 150ms cubic-bezier(.4, 0, .2, 1); + + border-radius: 50%; + background-color: var(--satus-switch-thumb); + + will-change: transform; +} + +.satus-switch[data-value='true']>i::before { + transform: translateX(14px); +} +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ + +.satus-modal--contextmenu .satus-modal__scrim { + visibility: visible; + + transform: none; + animation: none; + + opacity: 1; + background: none; + + backdrop-filter: none; +} + +.satus-modal--contextmenu .satus-modal__surface { + position: absolute; + + visibility: visible; + + min-width: 200px; + max-width: 200px; + margin: 0; + padding: 4px 0; + + transform: none; + animation: none; + + opacity: 1; + border-radius: 4px; + box-shadow: 0 0 0 1px rgba(var(--satus-light), .1); +} + +.satus-modal--contextmenu .satus-modal__surface>* { + display: flex; + + height: 32px; + padding: 0 16px; + + align-items: center; +} + +.satus-modal--contextmenu .satus-modal__surface .satus-button svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .75; + + fill: none; + stroke: var(--satus-primary); + flex: 0 0 20px; +} + +.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span { + overflow: hidden; + + white-space: nowrap; + text-overflow: ellipsis; +} +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ + +.satus-sortable__chosen { + color: var(--satus-sortable-text) !important; + background-color: var(--satus-sortable-background) !important; +} + +.satus-sortable__ghost { + position: fixed !important; + z-index: 999 !important; + top: 0 !important; + left: 0 !important; + + pointer-events: none !important; + + opacity: .8 !important; + box-shadow: 0 1px 3px rgb(0, 0, 0, .2), 0 4px 8px rgb(0, 0, 0, .1), inset 0 0 0 1px rgb(0, 0, 0, .16) !important; + + will-change: transform !important; +} diff --git a/assets/satus/satus.js b/assets/satus/satus.js new file mode 100644 index 0000000..4794646 --- /dev/null +++ b/assets/satus/satus.js @@ -0,0 +1,3266 @@ +/*-------------------------------------------------------------- +>>> CORE +---------------------------------------------------------------- +# Global variable +# Animations duration +# Append +# Attr +# Camelize +# Snakelize +# Class +# Create element +# CSS +# Empty +# Element index +# Events +# Get property +# Is +# On +# Render +# Sort +# Storage + # Clear + # Get + # Import + # Set + # Remove + # On changed +# Localization +# Log +# Text +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GLOBAL VARIABLE +--------------------------------------------------------------*/ + +var satus = { + components: {}, + events: { + data: {} + }, + locale: { + data: {} + }, + storage: { + data: {}, + type: 'extension' + } +}; + + +/*-------------------------------------------------------------- +# ANIMATION DURATION +--------------------------------------------------------------*/ + +satus.getAnimationDuration = function (element) { + return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; +}; + + +/*-------------------------------------------------------------- +# APPEND +--------------------------------------------------------------*/ + +satus.append = function (child, parent) { + (parent || document.body).appendChild(child); +}; + + +/*-------------------------------------------------------------- +# ATTR +--------------------------------------------------------------*/ + +satus.attr = function (element, attributes) { + if (attributes) { + for (var name in attributes) { + var value = attributes[name]; + + if (satus.isFunction(value)) { + value = value(); + } + + if (element.namespaceURI) { + if (value === false) { + element.removeAttributeNS(null, name); + } else { + element.setAttributeNS(null, name, value); + } + } else { + if (value === false) { + element.removeAttribute(name); + } else { + element.setAttribute(name, value); + } + } + } + } +}; + + +/*-------------------------------------------------------------- +# CAMELIZE +--------------------------------------------------------------*/ + +satus.camelize = function (string) { + var result = ''; + + for (var i = 0, l = string.length; i < l; i++) { + var character = string[i]; + + if (character === '_' || character === '-') { + i++; + + result += string[i].toUpperCase(); + } else { + result += character; + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# SNAKELIZE +--------------------------------------------------------------*/ + +satus.snakelize = function (string) { + return string.replace(/([A-Z])/g, '-$1').toLowerCase(); +}; + + +/*-------------------------------------------------------------- +# CLASS +--------------------------------------------------------------*/ + +satus.class = function (element, className) { + if (className) { + element.classList.add(className); + } +}; + + +/*-------------------------------------------------------------- +# CLONE +--------------------------------------------------------------*/ + +satus.clone = function (item) { + var clone = item.cloneNode(true), + parent_css = window.getComputedStyle(item.parentNode), + css = window.getComputedStyle(item), + style = ''; + + for (var i = 0, l = css.length; i < l; i++) { + var property = css[i], + value = css.getPropertyValue(property); + + if (property === 'background-color') { + value = parent_css.getPropertyValue('background-color'); + } + + if (['box-shadow', 'left', 'top', 'bottom', 'right', 'opacity'].indexOf(property) === -1) { + style += property + ':' + value + ';'; + } + } + + + clone.setAttribute('style', style); + + return clone; +}; + + +/*-------------------------------------------------------------- +# CREATE ELEMENT +--------------------------------------------------------------*/ + +satus.createElement = function (tagName, componentName, namespaceURI) { + var camelizedTagName = this.camelize(tagName), + className = 'satus-' + (componentName || tagName), + element, + match = className.match(/__[^__]+/g); + + if (!namespaceURI) { + if (tagName === 'svg') { + namespaceURI = 'http://www.w3.org/2000/svg'; + } + } + + if (namespaceURI) { + element = document.createElementNS(namespaceURI, tagName); + } else if (this.components[camelizedTagName]) { + element = document.createElement('div'); + } else { + element = document.createElement(tagName); + } + + if (match && match.length > 1) { + className = className.slice(0, className.indexOf('__')) + match[match.length - 1]; + } + + element.componentName = componentName; + element.className = className; + + element.createChildElement = function (tagName, componentName, namespaceURI) { + var element = satus.createElement(tagName, this.componentName + '__' + (componentName || tagName), namespaceURI); + + this.appendChild(element); + + return element; + }; + + return element; +}; + + +/*-------------------------------------------------------------- +# CSS +--------------------------------------------------------------*/ + +satus.css = function (element, property) { + return window.getComputedStyle(element).getPropertyValue(property); +}; + + +/*-------------------------------------------------------------- +# CRYPT +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# DECRYPTION +--------------------------------------------------------------*/ + +satus.decrypt = async function (text, password) { + var iv = text.slice(0, 24).match(/.{2}/g).map(byte => parseInt(byte, 16)), + algorithm = { + name: 'AES-GCM', + iv: new Uint8Array(iv) + }; + + try { + var data = new TextDecoder().decode(await crypto.subtle.decrypt( + algorithm, + await crypto.subtle.importKey( + 'raw', + await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), + algorithm, + false, ['decrypt'] + ), + new Uint8Array(atob(text.slice(24)).match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) + )); + } catch (err) { + return false; + } + + return data; +}; + + +/*-------------------------------------------------------------- +# ENCRYPTION +--------------------------------------------------------------*/ + +satus.encrypt = async function (text, password) { + var iv = crypto.getRandomValues(new Uint8Array(12)), + algorithm = { + name: 'AES-GCM', + iv: iv + }; + + return Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') + btoa(Array.from(new Uint8Array(await crypto.subtle.encrypt( + algorithm, + await crypto.subtle.importKey('raw', await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), algorithm, false, ['encrypt']), + new TextEncoder().encode(text) + ))).map(byte => String.fromCharCode(byte)).join('')); +}; + + +/*-------------------------------------------------------------- +# DATA +--------------------------------------------------------------*/ + +satus.data = function (element, data) { + if (data) { + for (var key in data) { + var value = data[key]; + + if (satus.isFunction(value)) { + value = value(); + } + + element.dataset[key] = value; + } + } +}; + + +/*-------------------------------------------------------------- +# EMPTY +--------------------------------------------------------------*/ + +satus.empty = function (element, exclude = []) { + for (var i = element.childNodes.length - 1; i > -1; i--) { + var child = element.childNodes[i]; + + if (exclude.indexOf(child) === -1) { + child.remove(); + } + } +}; + + +/*-------------------------------------------------------------- +# ELEMENT INDEX +--------------------------------------------------------------*/ + +satus.elementIndex = function (element) { + return Array.prototype.slice.call(element.parentNode.children).indexOf(element); +}; + + +/*-------------------------------------------------------------- +# EVENTS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# ON +--------------------------------------------------------------*/ + +satus.events.on = function (type, handler) { + if (!this.data[type]) { + this.data[type] = []; + } + + this.data[type].push(handler); +}; + + +/*-------------------------------------------------------------- +# TRIGGER +--------------------------------------------------------------*/ + +satus.events.trigger = function (type, data) { + var handlers = this.data[type]; + + if (handlers) { + for (var i = 0, l = handlers.length; i < l; i++) { + handlers[i](data); + } + } +}; + + +/*-------------------------------------------------------------- +# FETCH +--------------------------------------------------------------*/ + +satus.fetch = function (url, success, error, type) { + fetch(url).then(function (response) { + if (response.ok) { + response[type || 'json']().then(success); + } else { + error(); + } + }).catch(function () { + error(success); + }); +}; + + +/*-------------------------------------------------------------- +# GET PROPERTY +--------------------------------------------------------------*/ + +satus.getProperty = function (object, string) { + var properties = string.split('.'); + + for (var i = 0, l = properties.length; i < l; i++) { + var property = properties[i]; + + console.log(object); + + if (object = object[property]) { + if (i === l - 1) { + return object; + } + } else { + return false; + } + } +}; + + +/*-------------------------------------------------------------- +# INDEX OF +--------------------------------------------------------------*/ + +satus.indexOf = function (child, parent) { + var index = 0; + + if (satus.isArray(parent)) { + index = parent.indexOf(child); + } else { + while ((child = child.previousElementSibling)) { + index++; + } + } + + return index; +}; + + +/*-------------------------------------------------------------- +# TO INDEX +--------------------------------------------------------------*/ + +satus.toIndex = function (index, child, parent) { + if (satus.isArray(parent)) { + parent.splice(index, 0, parent.splice(satus.indexOf(child, parent), 1)[0]) + } +}; + + +/*-------------------------------------------------------------- +# ISSET +--------------------------------------------------------------*/ + +satus.isset = function (target, is_object) { + if (is_object === true) { + var keys = target.split('.').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = keys.length; i < l; i++) { + if (satus.isset(target[keys[i]])) { + target = target[keys[i]]; + } else { + return undefined; + } + } + + return target; + } else { + if (target === null || target === undefined) { + return false; + } + } + + return true; +}; + + +/*-------------------------------------------------------------- +# IS +--------------------------------------------------------------*/ + +satus.isArray = function (target) { + if (Array.isArray(target)) { + return true; + } else { + return false; + } +}; + +satus.isBoolean = function (target) { + return target === false || target === true; +}; + +satus.isElement = function (target) { + return target instanceof Element || target instanceof HTMLDocument; +}; + +satus.isFunction = function (target) { + return typeof target === 'function'; +}; + +satus.isNodeList = function (target) { + return target instanceof NodeList; +}; + +satus.isNumber = function (target) { + if (typeof target === 'number' && isNaN(target) === false) { + return true; + } else { + return false; + } +}; + +satus.isObject = function (target) { + return target instanceof Object && target !== null; +}; + +satus.isString = function (target) { + if (typeof target === 'string') { + return true; + } else { + return false; + } +}; + + +/*-------------------------------------------------------------- +# ON +--------------------------------------------------------------*/ + +satus.on = function (element, listeners) { + if (listeners) { + for (var type in listeners) { + var listener = listeners[type]; + + if (type === 'selectionchange') { + element = document; + } + + if (satus.isFunction(listener)) { + element.addEventListener(type, listener); + } else if (satus.isArray(listener) || satus.isObject(listener)) { + element.addEventListener(type, function (event) { + var target = this.skeleton.on[event.type], + parent = this.parentNode; + + target.parentSkeleton = this.skeleton; + target.parentElement = this; + + while (parent.componentName !== 'layers' && parent.componentName !== 'base' && parent !== document.body && parent.parentNode) { + parent = parent.parentNode; + } + + if (parent.componentName === 'layers' && target.component !== 'modal') { + parent.open(target); + } else if (this.baseProvider && this.baseProvider.layers.length === 1 && target.component !== 'modal') { + satus.render(target, this.baseProvider.layers[0]); + } else { + satus.render(target, this.baseProvider); + } + }); + } else if (satus.isString(listener)) { + element.addEventListener(type, function () { + var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g), + target = this.baseProvider; + + for (var i = 0, l = match.length; i < l; i++) { + var key = match[i]; + + if (target.skeleton[key]) { + target = target.skeleton[key]; + } else { + if (typeof target[key] === 'function') { + target[key](); + } else { + target = target[key]; + } + } + + if (target.rendered) { + target = target.rendered; + } + } + }); + } + } + } +}; + + +/*-------------------------------------------------------------- +# PARENTIFY +--------------------------------------------------------------*/ + +satus.parentify = function (parentObject, exclude) { + for (var key in parentObject) { + if (exclude.indexOf(key) === -1) { + var child = parentObject[key]; + + child.parentObject = parentObject; + + if (typeof child === 'object' && child.component !== 'shortcut') { + this.parentify(child, exclude); + } + } + } +}; + + +/*-------------------------------------------------------------- +# PREPEND +--------------------------------------------------------------*/ + +satus.prepend = function (child, parent) { + if (this.isElement(child)) { + parent.prepend(child); + } else if (this.isObject(child)) { + this.render(child, parent, undefined, undefined, true); + } +}; + + +/*-------------------------------------------------------------- +# PROPERTIES +--------------------------------------------------------------*/ + +satus.properties = function (element, properties) { + if (properties) { + for (var key in properties) { + var property = properties[key]; + + if (['placeholder', 'title'].indexOf(key) !== -1) { + property = satus.locale.get(property); + } + + element[key] = property; + } + } +}; + + +/*-------------------------------------------------------------- +# REMOVE +--------------------------------------------------------------*/ + +satus.remove = function (child, parent) { + if (satus.isArray(parent)) { + parent.splice(satus.indexOf(child, parent), 1); + } +}; + + +/*-------------------------------------------------------------- +# RENDER +--------------------------------------------------------------*/ + +satus.render = function (skeleton, container, property, childrenOnly, prepend) { + var element; + + if (skeleton.component && childrenOnly !== true) { + var tagName = skeleton.component, + camelizedTagName = this.camelize(tagName), + namespaceURI = skeleton.namespaceURI; + + if (!namespaceURI) { + if (tagName === 'svg') { + namespaceURI = 'http://www.w3.org/2000/svg'; + } else if (skeleton.parentSkeleton && skeleton.parentSkeleton.namespaceURI) { + namespaceURI = skeleton.parentSkeleton.namespaceURI; + } + + skeleton.namespaceURI = namespaceURI; + } + + element = this.createElement(tagName, tagName, namespaceURI); + + skeleton.rendered = element; + element.skeleton = skeleton; + element.childrenContainer = element; + element.componentName = tagName; + + if (skeleton.variant) { + var variant = skeleton.variant; + + if (this.isFunction(variant)) { + variant = variant(); + } + + if (satus.isArray(variant)) { + for (var i = 0, l = variant.length; i < l; i++) { + element.className += ' satus-' + tagName + '--' + variant[i]; + } + } else { + element.className += ' satus-' + tagName + '--' + variant; + } + } + + if (skeleton.id) { + element.id = skeleton.id; + } + + if (container) { + element.baseProvider = container.baseProvider; + } + + this.attr(element, skeleton.attr); + this.style(element, skeleton.style); + this.data(element, skeleton.data); + this.class(element, skeleton.class); + this.properties(element, skeleton.properties); + this.on(element, skeleton.on); + + element.storage = (function () { + var parent = element, + key = skeleton.storage || property || false, + value; + + if (satus.isFunction(key)) { + key = key(); + } + + if (skeleton.storage !== false) { + if (key) { + value = satus.storage.get(key); + } + + if (skeleton.hasOwnProperty('value') && value === undefined) { + value = skeleton.value; + } + } + + return Object.defineProperties({}, { + key: { + get: function () { + return key; + }, + set: function (string) { + key = string; + } + }, + value: { + get: function () { + return value; + }, + set: function (val) { + value = val; + + if (skeleton.storage !== false) { + satus.storage.set(key, val); + } + + parent.dispatchEvent(new CustomEvent('change')); + } + } + }); + }()); + + if (this.components[camelizedTagName]) { + this.components[camelizedTagName](element, skeleton); + } + + this.text(element.childrenContainer, skeleton.text); + this.prepend(skeleton.before, element.childrenContainer); + + if (prepend) { + this.prepend(element, container); + } else { + this.append(element, container); + } + + if (skeleton.hasOwnProperty('parentSkeleton') === false && container) { + skeleton.parentSkeleton = container.skeleton; + } + + satus.events.trigger('render', element); + + element.dispatchEvent(new CustomEvent('render')); + + container = element.childrenContainer || element; + } + + if (!element || element.renderChildren !== false) { + for (var key in skeleton) { + var item = skeleton[key]; + + if (key !== 'parentSkeleton' && key !== 'parentElement' && key !== 'parentObject' && key !== 'before') { + if (item && item.component) { + item.parentSkeleton = skeleton; + + if (element) { + item.parentElement = element; + } + + this.render(item, container, key, undefined, prepend); + } + } + } + } + + return element; +}; + + +/*-------------------------------------------------------------- +# SORT +--------------------------------------------------------------*/ + +satus.sort = function (array, order, property) { + var type; + + if (property) { + type = typeof array[0][property]; + } else { + type = typeof array[0]; + } + + if (order !== 'desc') { + if (type === 'number') { + if (property) { + return array.sort(function (a, b) { + return a[property] - b[property]; + }); + } else { + return array.sort(function (a, b) { + return a - b; + }); + } + } else if (type === 'string') { + if (property) { + return array.sort(function (a, b) { + return a[property].localeCompare(b[property]); + }); + } else { + return array.sort(function (a, b) { + return a.localeCompare(b); + }); + } + } + } else { + if (type === 'number') { + if (property) { + return array.sort(function (a, b) { + return b[property] - a[property]; + }); + } else { + return array.sort(function (a, b) { + return b - a; + }); + } + } else if (type === 'string') { + if (property) { + return array.sort(function (a, b) { + return b[property].localeCompare(a[property]); + }); + } else { + return array.sort(function (a, b) { + return b.localeCompare(a); + }); + } + } + } +}; + + +/*-------------------------------------------------------------- +# STORAGE +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# CLEAR +--------------------------------------------------------------*/ + +satus.storage.clear = function (callback) { + this.data = {}; + + chrome.storage.local.clear(function () { + satus.events.trigger('storage-clear'); + + if (callback) { + callback(); + } + }); +}; + + +/*-------------------------------------------------------------- +# GET +--------------------------------------------------------------*/ + +satus.storage.get = function (key, callback) { + var target = this.data; + + if (typeof key !== 'string') { + return; + } + + key = key.split('/').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = key.length; i < l; i++) { + if (satus.isset(target[key[i]])) { + target = target[key[i]]; + } else { + return undefined; + } + } + + if (typeof target === 'function') { + return target(); + } else { + return target; + } +}; + + +/*-------------------------------------------------------------- +# IMPORT +--------------------------------------------------------------*/ + +satus.storage.import = function (keys, callback) { + var self = this; + + if (typeof keys === 'function') { + callback = keys; + + keys = undefined; + } + + chrome.storage.local.get(keys, function (items) { + for (var key in items) { + self.data[key] = items[key]; + } + + satus.log('STORAGE: data was successfully imported'); + + satus.events.trigger('storage-import'); + + if (callback) { + callback(items); + } + }); +}; + + +/*-------------------------------------------------------------- +# REMOVE +--------------------------------------------------------------*/ + +satus.storage.remove = function (key) { + delete this.data[key]; + + chrome.storage.local.remove(key, function () { + satus.events.trigger('storage-remove'); + }); +}; + + +/*-------------------------------------------------------------- +# SET +--------------------------------------------------------------*/ + +satus.storage.set = function (key, value, callback) { + var items = {}, + target = this.data; + + if (typeof key !== 'string') { + return; + } + + key = key.split('/').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = key.length; i < l; i++) { + var item = key[i]; + + if (i < l - 1) { + + if (target[item]) { + target = target[item]; + } else { + target[item] = {}; + + target = target[item]; + } + } else { + target[item] = value; + } + } + + for (var key in this.data) { + if (typeof this.data[key] !== 'function') { + items[key] = this.data[key]; + } + } + + chrome.storage.local.set(items, function () { + satus.events.trigger('storage-set'); + + if (callback) { + callback(); + } + }); +}; + + +/*-------------------------------------------------------------- +# ON CHANGED +--------------------------------------------------------------*/ + +satus.storage.onchanged = function (callback) { + chrome.storage.onChanged.addListener(function (changes) { + for (var key in changes) { + callback(key, changes[key].newValue); + } + }); +}; + + +/*-------------------------------------------------------------- +# LAST +--------------------------------------------------------------*/ + +satus.last = function (variable) { + if (this.isArray(variable) || this.isNodeList(variable) || variable instanceof HTMLCollection) { + return variable[variable.length - 1]; + } +}; + + +/*-------------------------------------------------------------- +# LOCALIZATION +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GET +--------------------------------------------------------------*/ + +satus.locale.get = function (string) { + return this.data[string] || string; +}; + + +/*-------------------------------------------------------------- +# IMPORT +---------------------------------------------------------------- +satus.locale.import(url, onload, onsuccess); +--------------------------------------------------------------*/ + +satus.locale.import = function (code, callback, path) { + var language = code || window.navigator.language; + + if (language.indexOf('en') === 0) { + language = 'en'; + } + + if (!path) { + path = '_locales/'; + } + + satus.fetch(chrome.runtime.getURL(path + language + '/messages.json'), function (response) { + for (var key in response) { + satus.locale.data[key] = response[key].message; + } + + satus.log('LOCALE: data was successfully imported'); + + if (callback) { + callback(); + } + }, function (success) { + satus.fetch(chrome.runtime.getURL(path + 'en/messages.json'), success, function () { + success(); + }); + }); +}; + + +/*-------------------------------------------------------------- +# LOG +--------------------------------------------------------------*/ + +satus.log = function () { + console.log.apply(null, arguments); +}; + + +/*-------------------------------------------------------------- +# STYLE +--------------------------------------------------------------*/ + +satus.style = function (element, object) { + if (object) { + for (var key in object) { + element.style[key] = object[key]; + } + } +}; + + +/*-------------------------------------------------------------- +# TEXT +--------------------------------------------------------------*/ + +satus.text = function (element, value) { + if (value) { + if (satus.isFunction(value)) { + value = value(); + } + + element.appendChild(document.createTextNode(this.locale.get(value))); + } +}; +/*-------------------------------------------------------------- +>>> MODAL +---------------------------------------------------------------- +# Confirm +--------------------------------------------------------------*/ + +satus.components.modal = function (component, skeleton) { + component.scrim = component.createChildElement('div', 'scrim'); + component.surface = component.createChildElement('div', 'surface'); + + component.close = function () { + var component = this; + + this.classList.add('satus-modal--closing'); + + setTimeout(function () { + component.remove(); + + component.dispatchEvent(new CustomEvent('close')); + }, Number(satus.css(this.surface, 'animation-duration').replace(/[^0-9.]/g, '')) * 1000); + }; + + component.scrim.addEventListener('click', function () { + this.parentNode.close(); + }); + + if (satus.isset(skeleton.content)) { + component.surface.content = component.surface.createChildElement('p', 'content'); + + if (satus.isObject(skeleton.content)) { + satus.render(skeleton.content, component.surface.content); + } else { + component.surface.content.textContent = satus.locale.get(skeleton.content); + } + } else { + component.childrenContainer = component.surface; + } + + if (satus.components.modal[skeleton.variant]) { + satus.components.modal[skeleton.variant](component, skeleton); + } +}; + + +/*-------------------------------------------------------------- +# CONFIRM +--------------------------------------------------------------*/ + +satus.components.modal.confirm = function (component, skeleton) { + component.surface.actions = satus.render({ + component: 'section', + variant: 'align-end' + }, component.surface); + + if (skeleton.buttons) { + for (var key in skeleton.buttons) { + var button = satus.render(skeleton.buttons[key], component.surface.actions); + + button.modalProvider = component; + } + } else { + satus.render({ + cancel: { + component: 'button', + text: 'cancel', + properties: { + modalProvider: component, + }, + on: { + click: function () { + this.modalProvider.dispatchEvent(new CustomEvent('cancel')); + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + properties: { + modalProvider: component, + }, + on: { + click: function () { + this.modalProvider.dispatchEvent(new CustomEvent('confirm')); + this.modalProvider.close(); + } + } + } + }, component.surface.actions); + } +}; +/*-------------------------------------------------------------- +>>> GRID +--------------------------------------------------------------*/ + +satus.components.grid = function (component, skeleton) { + console.log(component, skeleton); +}; +/*-------------------------------------------------------------- +>>> TEXT FIELD +--------------------------------------------------------------*/ + +satus.components.textField = function (component, skeleton) { + var container = component.createChildElement('div', 'container'), + input = container.createChildElement('textarea'), + display = container.createChildElement('div', 'display'), + line_numbers = display.createChildElement('div', 'line-numbers'), + pre = display.createChildElement('pre'), + selection = display.createChildElement('div', 'selection'), + cursor = display.createChildElement('div', 'cursor'), + hiddenValue = container.createChildElement('pre', 'hidden-value'); + + component.placeholder = skeleton.placeholder; + component.input = input; + component.display = display; + component.line_numbers = line_numbers; + component.pre = pre; + component.hiddenValue = hiddenValue; + component.selection = selection; + component.cursor = cursor; + component.syntax = { + current: 'text', + handlers: { + regex: function (value, target) { + var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, + char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g, + char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/, + quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/, + matches = value.match(regex_token); + + function create(type, string) { + var span = document.createElement('span'); + + span.className = type; + span.textContent = string; + + target.appendChild(span); + } + + for (var i = 0, l = matches.length; i < l; i++) { + var match = matches[i]; + + if (match[0] === '[') { + create('character-class', match); + } else if (match[0] === '(') { + create('group', match); + } else if (match[0] === ')') { + create('group', match); + } else if (match[0] === '\\' || match === '^') { + create('anchor', match); + } else if (quantifier.test(match)) { + create('quantifier', match); + } else if (match === '|' || match === '.') { + create('metasequence', match); + } else { + create('text', match); + } + } + } + }, + set: function (syntax) { + if (this.handlers[syntax]) { + this.current = syntax; + } else { + this.current = 'text'; + } + + pre.update(); + } + }; + component.focus = function () { + this.input.focus(); + }; + + if (satus.isset(skeleton.cols)) { + input.cols = skeleton.cols; + } + + if (satus.isset(skeleton.rows)) { + input.rows = skeleton.rows; + } + + Object.defineProperty(component, 'value', { + get: function () { + return this.input.value; + }, + set: function (value) { + this.input.value = value; + } + }); + + if (skeleton.syntax) { + component.syntax.set(skeleton.syntax); + } + + selection.setAttribute('disabled', ''); + + line_numbers.update = function () { + var component = this.parentNode.parentNode.parentNode, + count = component.input.value.split('\n').length; + + if (count !== this.children.length) { + satus.empty(this); + + for (var i = 1; i <= count; i++) { + var span = document.createElement('span'); + + span.textContent = i; + + this.appendChild(span); + } + } + + component.input.style.paddingLeft = this.offsetWidth + 'px'; + }; + + pre.update = function () { + var component = this.parentNode.parentNode.parentNode, + handler = component.syntax.handlers[component.syntax.current], + value = component.value || ''; + + for (var i = this.childNodes.length - 1; i > -1; i--) { + this.childNodes[i].remove(); + } + + if (handler) { + handler(value, this); + } else { + this.textContent = value; + } + + if (value.length === 0) { + var placeholder = component.placeholder; + + if (typeof placeholder === 'function') { + placeholder = component.placeholder(); + } else { + placeholder = satus.locale.get(placeholder); + } + + this.textContent = placeholder; + } + }; + + cursor.update = function () { + var component = this.parentNode.parentNode.parentNode, + input = component.input, + value = input.value, + rows_count = value.split('\n').length, + start = input.selectionStart, + end = input.selectionEnd, + rows = value.slice(0, start).split('\n'), + top = 0; + + this.style.animation = 'none'; + + if (input.selectionDirection === 'forward') { + component.hiddenValue.textContent = value.substring(0, end); + } else { + component.hiddenValue.textContent = value.substring(0, start); + } + + top = component.hiddenValue.offsetHeight; + + component.hiddenValue.textContent = satus.last(rows); + + top -= component.hiddenValue.offsetHeight; + + this.style.top = top + 'px'; + this.style.left = component.hiddenValue.offsetWidth + component.line_numbers.offsetWidth + 'px'; + + if (start === end) { + component.selection.setAttribute('disabled', ''); + } else { + component.selection.removeAttribute('disabled'); + + /*component.hiddenValue.textContent = value.substring(0, start); + + component.selection.style.left = component.hiddenValue.offsetWidth - input.scrollLeft + 'px'; + + component.hiddenValue.textContent = value.substring(start, end); + + component.selection.style.width = component.hiddenValue.offsetWidth + 'px';*/ + } + + this.style.animation = ''; + + component.hiddenValue.textContent = ''; + }; + + document.addEventListener('selectionchange', function (event) { + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + input.addEventListener('input', function () { + var component = this.parentNode.parentNode; + + component.storage.value = this.value; + + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + input.addEventListener('scroll', function (event) { + var component = this.parentNode.parentNode; + + component.display.style.top = -this.scrollTop + 'px'; + component.display.style.left = -this.scrollLeft + 'px'; + + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + component.addEventListener('change', function () { + this.line_numbers.update(); + this.pre.update(); + this.cursor.update(); + }); + + component.value = component.storage.value || ''; + + component.addEventListener('render', function () { + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + if (skeleton.on) { + for (var type in skeleton.on) { + input.addEventListener(type, function (event) { + this.parentNode.parentNode.dispatchEvent(new Event(event.type)); + }); + } + } +}; +/*-------------------------------------------------------------- +>>> CHART +---------------------------------------------------------------- +# Core + # Bar +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# CORE +--------------------------------------------------------------*/ + +satus.components.chart = function (component, skeleton) { + var type = skeleton.type; + + if (this.chart[type]) { + component.classList.add('satus-chart--' + type); + + this.chart[type](component, skeleton); + } +}; + + +/*-------------------------------------------------------------- +# BAR +--------------------------------------------------------------*/ + +satus.components.chart.bar = function (component, skeleton) { + var labels = skeleton.labels, + datasets = skeleton.datasets, + bars = []; + + if (satus.isFunction(labels)) { + labels = labels(); + } + + if (satus.isFunction(datasets)) { + datasets = datasets(); + } + + if (satus.isArray(labels)) { + var container = component.createChildElement('div', 'labels'); + + for (var i = 0, l = labels.length; i < l; i++) { + var label = labels[i], + section = container.createChildElement('div', 'section'); + + section.textContent = label; + } + } + + if (satus.isArray(datasets)) { + var container = component.createChildElement('div', 'bars'); + + for (var i = 0, l = datasets.length; i < l; i++) { + var dataset = datasets[i]; + + for (var j = 0, k = dataset.data.length; j < k; j++) { + if (!satus.isElement(bars[j])) { + bars.push(container.createChildElement('div', 'bar')); + } + + var piece = bars[j].createChildElement('div', 'piece'); + + piece.title = dataset.label; + piece.style.height = dataset.data[j] + '%'; + piece.style.backgroundColor = 'rgb(' + dataset.color.join(',') + ')'; + } + } + } +}; +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +satus.components.select = function (component, skeleton) { + var content = component.createChildElement('div', 'content'); + + component.childrenContainer = content; + component.valueElement = document.createElement('span'); + component.selectElement = document.createElement('select'); + + component.valueElement.className = 'satus-select__value'; + + component.appendChild(component.valueElement); + component.appendChild(component.selectElement); + + component.options = skeleton.options || []; + + if (satus.isFunction(component.options)) { + component.options = component.options(); + } + + for (var i = 0, l = component.options.length; i < l; i++) { + var option = document.createElement('option'); + + option.value = component.options[i].value; + + satus.text(option, component.options[i].text); + + component.selectElement.appendChild(option); + } + + Object.defineProperty(component, 'value', { + get() { + return this.selectElement.value; + }, + set(value) { + this.selectElement.value = value; + } + }); + + component.render = function () { + satus.empty(this.valueElement); + + if (this.selectElement.options[this.selectElement.selectedIndex]) { + satus.text(this.valueElement, this.selectElement.options[this.selectElement.selectedIndex].text); + } + + this.dataset.value = this.value; + }; + + component.selectElement.addEventListener('change', function () { + var component = this.parentNode; + + component.storage.value = this.value; + + component.render(); + }); + + component.value = component.storage.value || component.options[0].value; + + component.render(); +}; +/*-------------------------------------------------------------- +>>> DIVIDER +--------------------------------------------------------------*/ + +satus.components.divider = function () {}; +/*-------------------------------------------------------------- +>>> SECTION +--------------------------------------------------------------*/ + +satus.components.section = function (component, skeleton) { + if (satus.isString(skeleton.title)) { + component.dataset.title = satus.locale.get(skeleton.title); + } +}; +/*-------------------------------------------------------------- +>>> BASE +--------------------------------------------------------------*/ + +satus.components.base = function (component) { + component.baseProvider = component; + component.layers = []; +}; +/*-------------------------------------------------------------- +>>> ALERT +--------------------------------------------------------------*/ + +satus.components.alert = function (component, skeleton) {}; +/*-------------------------------------------------------------- +>>> TIME +--------------------------------------------------------------*/ + +satus.components.time = function (component, skeleton) { + var select_skeleton = Object.assign({}, skeleton); + + select_skeleton.component = 'select'; + select_skeleton.options = []; + + if (satus.isFunction(select_skeleton.hour12)) { + select_skeleton.hour12 = select_skeleton.hour12(); + } + + for (var i = 0, l = 24; i < l; i++) { + var hour = i, + value = i; + + if (select_skeleton.hour12 === true && i > 12) { + hour -= 12; + } + + if (hour < 10) { + hour = '0' + hour; + value = '0' + value; + } + + if (select_skeleton.hour12 === true) { + if (i > 12) { + hour += ':00 pm'; + } else { + hour += ':00 am'; + } + } else { + hour += ':00' + } + + select_skeleton.options.push({ + text: hour, + value: value + ':00' + }); + } + + satus.components.select(component, select_skeleton); + + component.classList.add('satus-select'); +}; +/*-------------------------------------------------------------- +>>> SIDEBAR +--------------------------------------------------------------*/ + +satus.components.sidebar = function (component, skeleton) {}; +/*-------------------------------------------------------------- +>>> LAYERS +--------------------------------------------------------------*/ + +satus.components.layers = function (component, skeleton) { + component.path = []; + component.renderChildren = false; + component.baseProvider.layers.push(component); + + component.back = function () { + if (this.path.length > 1) { + this.path.pop(); + + this.open(this.path[this.path.length - 1], false); + } + }; + + component.open = function (skeleton, history) { + var previous_layer = satus.last(this.querySelectorAll('.satus-layers__layer')), + layer = this.createChildElement('div', 'layer'); + + if (history !== false) { + if (previous_layer) { + previous_layer.style.animation = 'fadeOutLeft 100ms linear forwards'; + layer.style.animation = 'fadeInRight 100ms linear forwards'; + } + + this.path.push(skeleton); + } else { + previous_layer.style.animation = 'fadeOutRight 100ms linear forwards'; + layer.style.animation = 'fadeInLeft 100ms linear forwards'; + } + + if (previous_layer) { + setTimeout(function () { + previous_layer.remove(); + }, satus.getAnimationDuration(previous_layer)); + } + + layer.skeleton = skeleton; + layer.baseProvider = this.baseProvider; + + satus.render(skeleton, layer, undefined, skeleton.component === 'layers'); + + this.dispatchEvent(new Event('open')); + }; + + component.update = function () { + var layer = this.querySelector('.satus-layers__layer'); + + satus.empty(layer); + satus.render(layer.skeleton, layer); + }; + + component.open(skeleton); +}; +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +satus.components.list = function (component, skeleton) { + for (var i = 0, l = skeleton.items.length; i < l; i++) { + var li = component.createChildElement('div', 'item'), + item = skeleton.items[i]; + + for (var j = 0, k = item.length; j < k; j++) { + var child = item[j]; + + if (satus.isObject(child)) { + satus.render(child, li); + } else { + var span = li.createChildElement('span'); + + span.textContent = satus.locale.get(child); + } + } + } +}; +/*-------------------------------------------------------------- +>>> COLOR PICKER +--------------------------------------------------------------*/ + +satus.components.colorPicker = function (component, skeleton) { + var component_content = component.createChildElement('div', 'content'), + component_value = component.createChildElement('span', 'value'); + + component.childrenContainer = component_content; + component.valueElement = component_value; + + component.className = 'satus-button'; + + component.addEventListener('click', function () { + var rgb = this.rgb, + hsl = satus.color.rgbToHsl(rgb), + s = hsl[1] / 100, + l = hsl[2] / 100; + + s *= l < .5 ? l : 1 - l; + + var v = l + s; + + s = 2 * s / (l + s); + + satus.render({ + component: 'modal', + variant: 'color-picker', + value: hsl, + parentElement: this, + + palette: { + component: 'div', + class: 'satus-color-picker__palette', + style: { + 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' + }, + on: { + mousedown: function () { + var palette = this, + rect = this.getBoundingClientRect(), + cursor = this.children[0]; + + function mousemove(event) { + var hsl = palette.skeleton.parentSkeleton.storage.value, + x = event.clientX - rect.left, + y = event.clientY - rect.top, + s; + + x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); + y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); + + var v = 100 - y, + l = (2 - x / 100) * v / 2; + + hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); + hsl[2] = l; + + cursor.style.left = x + '%'; + cursor.style.top = y + '%'; + + palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + + event.preventDefault(); + } + + function mouseup() { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + }, + + cursor: { + component: 'div', + class: 'satus-color-picker__cursor', + style: { + 'left': s * 100 + '%', + 'top': 100 - v * 100 + '%' + } + } + }, + section: { + component: 'section', + variant: 'color', + + color: { + component: 'div', + class: 'satus-color-picker__color', + style: { + 'backgroundColor': 'rgb(' + this.rgb.join(',') + ')' + } + }, + hue: { + component: 'slider', + class: 'satus-color-picker__hue', + storage: false, + value: hsl[0], + max: 360, + on: { + change: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + hsl = modal.storage.value; + + hsl[0] = this.values[0]; + + this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + this.parentSkeletonNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentSkeleton; + + component.rgb = component.skeleton.value; + + component.storage.value = component.rgb; + + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + + modal.rendered.close(); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.skeleton.parentSkeleton.parentSkeleton.rendered.close(); + } + } + }, + ok: { + component: 'button', + text: 'OK', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentSkeleton; + + component.rgb = satus.color.hslToRgb(modal.storage.value); + + component.storage.value = component.rgb; + + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + + modal.rendered.close(); + } + } + } + } + }, this.baseProvider.layers[0]); + }); + + component.addEventListener('render', function () { + component.rgb = this.storage.value || [0, 100, 50]; + + component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + }); +}; + +satus.components.colorPicker = function (component, skeleton) { + component.childrenContainer = component.createChildElement('div', 'content'); + + component.color = (function (element) { + var array; + + Object.defineProperty(element, 'value', { + get: function () { + return array; + }, + set: function (value) { + array = value; + + this.parentNode.storage.value = array; + + element.style.backgroundColor = 'rgb(' + value.join(',') + ')'; + } + }); + + element.value = component.storage.value || component.skeleton.value || [0, 0, 0]; + + return element; + })(component.createChildElement('span', 'value')); + + component.addEventListener('click', function () { + var hsl = satus.color.rgbToHsl(this.color.value), + s = hsl[1] / 100, + l = hsl[2] / 100; + + s *= l < .5 ? l : 1 - l; + + var v = l + s; + + s = 2 * s / (l + s); + + satus.render({ + component: 'modal', + variant: 'color-picker', + value: hsl, + parentElement: this, + + palette: { + component: 'div', + class: 'satus-color-picker__palette', + style: { + 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' + }, + on: { + mousedown: function (event) { + if (event.button !== 0) { + return false; + } + + var palette = this, + rect = this.getBoundingClientRect(), + cursor = this.children[0]; + + function mousemove(event) { + var hsl = palette.skeleton.parentSkeleton.value, + x = event.clientX - rect.left, + y = event.clientY - rect.top, + s; + + x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); + y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); + + var v = 100 - y, + l = (2 - x / 100) * v / 2; + + hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); + hsl[2] = l; + + cursor.style.left = x + '%'; + cursor.style.top = y + '%'; + + palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + + event.preventDefault(); + } + + function mouseup() { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + }, + + cursor: { + component: 'div', + class: 'satus-color-picker__cursor', + style: { + 'left': s * 100 + '%', + 'top': 100 - v * 100 + '%' + } + } + }, + section: { + component: 'section', + variant: 'color', + + color: { + component: 'div', + class: 'satus-color-picker__color', + style: { + 'backgroundColor': 'rgb(' + this.color.value.join(',') + ')' + } + }, + hue: { + component: 'slider', + class: 'satus-color-picker__hue', + storage: false, + value: hsl[0], + max: 360, + on: { + input: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + hsl = modal.value; + + hsl[0] = this.storage.value; + + this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + this.parentNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentElement; + + component.color.value = component.skeleton.value || [0, 0, 0]; + + modal.rendered.close(); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.skeleton.parentSkeleton.parentSkeleton.rendered.close(); + } + } + }, + ok: { + component: 'button', + text: 'OK', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentElement; + + component.color.value = satus.color.hslToRgb(modal.value); + + modal.rendered.close(); + } + } + } + } + }, this.baseProvider.layers[0]); + }); +}; +/*-------------------------------------------------------------- +>>> RADIO +--------------------------------------------------------------*/ + +satus.components.radio = function (component, skeleton) { + component.nativeControl = component.createChildElement('input', 'input'); + + component.createChildElement('i'); + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.nativeControl.type = 'radio'; + + if (skeleton.group) { + component.storage.key = skeleton.group; + component.nativeControl.name = skeleton.group; + } + + if (skeleton.value) { + component.nativeControl.value = skeleton.value; + } + + component.storage.value = satus.storage.get(component.storage.key); + + if (satus.isset(component.storage.value)) { + component.nativeControl.checked = component.storage.value === skeleton.value; + } else if (skeleton.checked) { + component.nativeControl.checked = true; + } + + component.nativeControl.addEventListener('change', function () { + var component = this.parentNode; + + component.storage.value = this.value; + }); +}; +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +satus.components.slider = function (component, skeleton) { + var content = component.createChildElement('div', 'content'), + track_container = component.createChildElement('div', 'track-container'), + input = track_container.createChildElement('input', 'input'); + + component.childrenContainer = content; + component.input = input; + component.track = track_container.createChildElement('div', 'track'); + + input.type = 'range'; + input.min = skeleton.min || 0; + input.max = skeleton.max || 1; + input.step = skeleton.step || 1; + input.value = component.storage.value || skeleton.value || 0; + + input.addEventListener('input', function () { + var component = this.parentNode.parentNode; + + component.storage.value = Number(this.value); + + component.update(); + }); + + component.update = function () { + var input = this.input; + + this.track.style.width = 100 / (input.max - input.min) * (input.value - input.min) + '%'; + }; + + component.update(); + + if (skeleton.on) { + for (var type in skeleton.on) { + input.addEventListener(type, function (event) { + this.parentNode.parentNode.dispatchEvent(new Event(event.type)); + }); + } + } +}; +/*-------------------------------------------------------------- +>>> TABS +--------------------------------------------------------------*/ + +satus.components.tabs = function (component, skeleton) { + var tabs = skeleton.items, + value = skeleton.value; + + if (satus.isFunction(tabs)) { + tabs = tabs(); + } + + if (satus.isFunction(value)) { + value = value(); + } + + for (var i = 0, l = tabs.length; i < l; i++) { + var tab = tabs[i], + button = component.createChildElement('button'); + + button.addEventListener('click', function () { + var component = this.parentNode, + index = satus.elementIndex(this); + + component.value = index; + + component.style.setProperty('--satus-tabs-current', index); + }); + + satus.text(button, tab); + } + + component.style.setProperty('--satus-tabs-count', tabs.length); + component.style.setProperty('--satus-tabs-current', value || 0); +}; +/*-------------------------------------------------------------- +>>> SHORTCUT +--------------------------------------------------------------*/ + +satus.components.shortcut = function (component, skeleton) { + component.childrenContainer = component.createChildElement('div', 'content'); + component.valueElement = component.createChildElement('div', 'value'); + + component.className = 'satus-button'; + + component.render = function (parent) { + var self = this, + parent = parent || self.primary, + children = parent.children; + + satus.empty(parent); + + function createElement(name) { + var element = document.createElement('div'); + + element.className = 'satus-shortcut__' + name; + + parent.appendChild(element); + + return element; + } + + if (this.data.alt) { + createElement('key').textContent = 'Alt'; + } + + if (this.data.ctrl) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + createElement('key').textContent = 'Ctrl'; + } + + if (this.data.shift) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + createElement('key').textContent = 'Shift'; + } + + for (var code in this.data.keys) { + var key = this.data.keys[code].key, + arrows = ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft'], + index = arrows.indexOf(key); + + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + if (index !== -1) { + createElement('key').textContent = ['↑', '→', '↓', '←'][index]; + } else if (key === ' ') { + createElement('key').textContent = '␣'; + } else if (key) { + createElement('key').textContent = key.toUpperCase(); + } + } + + if (this.data.wheel) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' ' + (this.data.wheel > 0); + } + + if (this.data.click) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' click'; + } + + if (this.data.middle) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' middle'; + } + + if (this.data.context) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' context'; + } + }; + + component.keydown = function (event) { + event.preventDefault(); + event.stopPropagation(); + + component.data = { + alt: event.altKey, + ctrl: event.ctrlKey, + shift: event.shiftKey, + keys: {} + }; + + if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) { + component.data.keys[event.keyCode] = { + code: event.code, + key: event.key + }; + } + + component.data.wheel = 0; + + component.render(); + + return false; + }; + + if (skeleton.wheel !== false) { + component.mousewheel = function (event) { + event.stopPropagation(); + + if ( + ( + component.data.wheel === 0 && + ( + Object.keys(component.data.keys).length === 0 && + component.data.alt === false && + component.data.ctrl === false && + component.data.shift === false + ) + ) || + component.data.wheel < 0 && event.deltaY > 0 || + component.data.wheel > 0 && event.deltaY < 0) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.wheel = event.deltaY < 0 ? -1 : 1; + + component.render(); + + return false; + }; + } + + component.addEventListener('click', function () { + satus.render({ + component: 'modal', + properties: { + parent: this + }, + on: { + close: function () { + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + }, + + primary: { + component: 'div', + class: 'satus-shortcut__primary', + on: { + render: function () { + component.primary = this; + + if (component.skeleton.mouseButtons === true) { + this.addEventListener('mousedown', function (event) { + if ( + component.data.click && event.button === 0 || + component.data.middle && event.button === 1 + ) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.click = false; + component.data.middle = false; + component.data.context = false; + + if (event.button === 0) { + component.data.click = true; + + component.render(); + } else if (event.button === 1) { + component.data.middle = true; + + component.render(); + } + }); + + this.addEventListener('contextmenu', function (event) { + event.preventDefault(); + event.stopPropagation(); + + if (component.data.context) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.context = true; + component.data.middle = false; + component.data.click = false; + + component.render(); + + return false; + }); + } + + component.render(); + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var component = this.parentNode.parentNode.parentNode.parent; + + component.data = component.skeleton.value || {}; + + component.render(component.valueElement); + + satus.storage.remove(component.storage); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + component.data = satus.storage.get(component.storage) || component.skeleton.value || {}; + + component.render(component.valueElement); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + }, + save: { + component: 'button', + text: 'save', + on: { + click: function () { + component.storage.value = component.data; + + component.render(component.valueElement); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + } + } + }, this.baseProvider); + + window.addEventListener('keydown', this.keydown); + window.addEventListener('wheel', this.mousewheel); + }); + + component.data = component.storage.value || { + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0 + }; + + component.render(component.valueElement); +}; +/*-------------------------------------------------------------- +>>> CHECKBOX +--------------------------------------------------------------*/ + +satus.components.checkbox = function (component, skeleton) { + component.input = component.createChildElement('input'); + component.input.type = 'checkbox'; + + component.checkmark = component.createChildElement('div', 'checkmark'); + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.dataset.value = component.storage.value || skeleton.value; + component.input.checked = component.storage.value || skeleton.value; + + component.input.addEventListener('change', function () { + var component = this.parentNode; + + if (this.checked === true) { + component.storage.value = true; + component.dataset.value = 'true'; + } else { + component.storage.value = false; + component.dataset.value = 'false'; + } + }); +}; +/*-------------------------------------------------------------- +>>> SWITCH +--------------------------------------------------------------*/ + +satus.components.switch = function (component, skeleton) { + var value = component.storage.value || skeleton.value; + + if (satus.isFunction(value)) { + value = value(); + } + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.createChildElement('i'); + + component.dataset.value = value; + + component.addEventListener('click', function () { + if (this.dataset.value === 'true') { + this.dataset.value = 'false'; + this.storage.value = false; + } else { + this.dataset.value = 'true'; + this.storage.value = true; + } + }, true); +}; +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ + +satus.events.on('render', function (component) { + if (component.skeleton.contextMenu) { + component.addEventListener('contextmenu', function (event) { + var base = this.baseProvider, + base_rect = base.getBoundingClientRect(), + x = event.clientX - base_rect.left, + y = event.clientY - base_rect.top, + modal = satus.render({ + component: 'modal', + variant: 'contextmenu', + parentSkeleton: this.skeleton, + baseProvider: base + }, base); + + if (base_rect.width - x < 200) { + x = base_rect.width - x; + + if (x + 200 > base_rect.width) { + x = 0; + } + + modal.childrenContainer.style.right = x + 'px'; + } else { + modal.childrenContainer.style.left = x + 'px'; + } + + modal.childrenContainer.style.top = y + 'px'; + + this.skeleton.contextMenu.parentSkeleton = this.skeleton; + + satus.render(this.skeleton.contextMenu, modal.childrenContainer); + + event.preventDefault(); + event.stopPropagation(); + + return false; + }); + } +}); +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ + +satus.events.on('render', function (component) { + if (component.skeleton.sortable === true) { + component.addEventListener('mousedown', function (event) { + if (event.button !== 0) { + return false; + } + + var component = this, + rect = this.getBoundingClientRect(), + x = event.clientX, + y = event.clientY, + offset_x = event.clientX - rect.left, + offset_y = event.clientY - rect.top, + ghost = satus.clone(this), + children = this.parentNode.children, + appended = false; + + ghost.classList.add('satus-sortable__ghost'); + + function mousemove(event) { + if (appended === false && (Math.abs(event.clientX - x) > 4 || Math.abs(event.clientY - y) > 4)) { + appended = true; + + component.classList.add('satus-sortable__chosen'); + + component.baseProvider.appendChild(ghost); + } + + ghost.style.transform = 'translate(' + (event.clientX - offset_x) + 'px, ' + (event.clientY - offset_y) + 'px)'; + } + + function mouseup(event) { + component.classList.remove('satus-sortable__chosen'); + ghost.remove(); + + window.removeEventListener('mousemove', mousemove, true); + window.removeEventListener('mouseup', mouseup, true); + + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; + + if (child !== component) { + child.removeEventListener('mouseover', siblingMouseOver); + } + } + + component.dispatchEvent(new CustomEvent('sort')); + + event.stopPropagation(); + + return false; + } + + window.addEventListener('mousemove', mousemove, { + passive: true, + capture: true + }); + + window.addEventListener('mouseup', mouseup, { + passive: true, + capture: true + }); + + function siblingMouseOver(event) { + var parent = this.parentNode, + y = event.layerY / (this.offsetHeight / 100); + + if (y < 50 && this.previousSibling !== component || y >= 50 && this.nextSibling === component) { + parent.insertBefore(component, this); + } else { + parent.insertBefore(component, this.nextSibling); + } + } + + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; + + if (child !== component) { + child.addEventListener('mouseover', siblingMouseOver); + } + } + + event.stopPropagation(); + event.preventDefault(); + + return false; + }); + } +}); +/*-------------------------------------------------------------- +>>> MANIFEST +--------------------------------------------------------------*/ + +satus.manifest = function () { + var object = {}; + + if (this.isset('chrome.runtime.getManifest')) { + object = chrome.runtime.getManifest(); + } + + return object; +}; +/*-------------------------------------------------------------- +>>> COLOR: +---------------------------------------------------------------- +# String to array +# RGB to HSL +# HUE to RGB +# HSL to RGB +--------------------------------------------------------------*/ + +satus.color = {}; + + +/*-------------------------------------------------------------- +# STRING TO ARRAY +--------------------------------------------------------------*/ + +satus.color.stringToArray = function (string) { + var match = string.match(/[0-9.]+/g); + + if (match) { + for (var i = 0, l = match.length; i < l; i++) { + match[i] = parseFloat(match[i]); + } + } + + return match; +}; + + +/*-------------------------------------------------------------- +# RGB TO HSL +--------------------------------------------------------------*/ + +satus.color.rgbToHsl = function (array) { + var r = array[0] / 255, + g = array[1] / 255, + b = array[2] / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = 0, + s = 0, + l = (min + max) / 2; + + if (min === max) { + h = 0; + s = 0; + } else { + var delta = max - min; + + s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); + + if (max === r) { + h = (g - b) / delta + (g < b ? 6 : 0); + } else if (max === g) { + h = (b - r) / delta + 2; + } else if (max === b) { + h = (r - g) / delta + 4; + } + + h /= 6; + } + + h *= 360; + s *= 100; + l *= 100; + + if (array.length === 3) { + return [h, s, l]; + } else { + return [h, s, l, array[3]]; + } +}; + + +/*-------------------------------------------------------------- +# HUE TO RGB +--------------------------------------------------------------*/ + +satus.color.hueToRgb = function (array) { + var t1 = array[0], + t2 = array[1], + hue = array[2]; + + if (hue < 0) { + hue += 6; + } + + if (hue >= 6) { + hue -= 6; + } + + if (hue < 1) { + return (t2 - t1) * hue + t1; + } else if (hue < 3) { + return t2; + } else if (hue < 4) { + return (t2 - t1) * (4 - hue) + t1; + } else { + return t1; + } +}; + + +/*-------------------------------------------------------------- +# HSL TO RGB +--------------------------------------------------------------*/ + +satus.color.hslToRgb = function (array) { + var h = array[0] / 360, + s = array[1] / 100, + l = array[2] / 100, + r, g, b; + + if (s == 0) { + r = g = b = l; + } else { + var hue2rgb = function (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; + }; + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +}; +/*-------------------------------------------------------------- +>>> USER +---------------------------------------------------------------- +# OS + # Name + # Bitness +# Browser + # Name + # Version + # Platform + # Manifest + # Languages + # Cookies + # Flash + # Java + # Audio + # Video + # WebGL +# Device + # Screen + # RAM + # GPU + # Cores + # Touch + # Connection +--------------------------------------------------------------*/ + +satus.user = { + browser: {}, + device: {}, + os: {} +}; + +/*-------------------------------------------------------------- +# OS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# NAME +--------------------------------------------------------------*/ + +satus.user.os.name = function () { + var app_version = navigator.appVersion; + + if (app_version.indexOf('Win') !== -1) { + if (app_version.match(/(Windows 10.0|Windows NT 10.0)/)) { + return 'Windows 10'; + } else if (app_version.match(/(Windows 8.1|Windows NT 6.3)/)) { + return 'Windows 8.1'; + } else if (app_version.match(/(Windows 8|Windows NT 6.2)/)) { + return 'Windows 8'; + } else if (app_version.match(/(Windows 7|Windows NT 6.1)/)) { + return 'Windows 7'; + } else if (app_version.match(/(Windows NT 6.0)/)) { + return 'Windows Vista'; + } else if (app_version.match(/(Windows NT 5.1|Windows XP)/)) { + return 'Windows XP'; + } else { + return 'Windows'; + } + } else if (app_version.indexOf('(iPhone|iPad|iPod)') !== -1) { + return 'iOS'; + } else if (app_version.indexOf('Mac') !== -1) { + return 'macOS'; + } else if (app_version.indexOf('Android') !== -1) { + return 'Android'; + } else if (app_version.indexOf('OpenBSD') !== -1) { + return 'OpenBSD'; + } else if (app_version.indexOf('SunOS') !== -1) { + return 'SunOS'; + } else if (app_version.indexOf('Linux') !== -1) { + return 'Linux'; + } else if (app_version.indexOf('X11') !== -1) { + return 'UNIX'; + } +}; + + +/*-------------------------------------------------------------- +# BITNESS +--------------------------------------------------------------*/ + +satus.user.os.bitness = function () { + if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { + return '64-bit'; + } else { + return '32-bit'; + } +}; + + +/*-------------------------------------------------------------- +# BROWSER +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# NAME +--------------------------------------------------------------*/ + +satus.user.browser.name = function () { + var user_agent = navigator.userAgent; + + if (user_agent.indexOf('Opera') !== -1) { + return 'Opera'; + } else if (user_agent.indexOf('Vivaldi') !== -1) { + return 'Vivaldi'; + } else if (user_agent.indexOf('Edge') !== -1) { + return 'Edge'; + } else if (user_agent.indexOf('Chrome') !== -1) { + return 'Chrome'; + } else if (user_agent.indexOf('Safari') !== -1) { + return 'Safari'; + } else if (user_agent.indexOf('Firefox') !== -1) { + return 'Firefox'; + } else if (user_agent.indexOf('MSIE') !== -1) { + return 'IE'; + } +}; + + +/*-------------------------------------------------------------- +# VERSION +--------------------------------------------------------------*/ + +satus.user.browser.version = function () { + var browser_name = satus.user.browser.name(), + browser_version = navigator.userAgent.match(new RegExp(browser_name + '/([0-9.]+)')); + + return browser_version[1]; +}; + + +/*-------------------------------------------------------------- +# PLATFORM +--------------------------------------------------------------*/ + +satus.user.browser.platform = function () { + return navigator.platform; +}; + + +/*-------------------------------------------------------------- +# MANIFEST +--------------------------------------------------------------*/ + +satus.user.browser.manifest = function () { + return chrome.runtime.getManifest() || {}; +}; + + +/*-------------------------------------------------------------- +# LANGUAGES +--------------------------------------------------------------*/ + +satus.user.browser.languages = function () { + return navigator.languages; +}; + + +/*-------------------------------------------------------------- +# COOKIES +--------------------------------------------------------------*/ + +satus.user.browser.cookies = function () { + if (document.cookie) { + var random_cookie = 'ta{t`nX6cMXK,Wsc'; + + document.cookie = random_cookie; + + if (document.cookie.indexOf(random_cookie) !== -1) { + return true; + } + } + + return false; +}; + + +/*-------------------------------------------------------------- +# FLASH +--------------------------------------------------------------*/ + +satus.user.browser.flash = function () { + try { + if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { + return true; + } + } catch (error) { + if (navigator.mimeTypes['application/x-shockwave-flash']) { + return true; + } + } + + return false; +}; + + +/*-------------------------------------------------------------- +# JAVA +--------------------------------------------------------------*/ + +satus.user.browser.java = function () { + if (satus.isFunction(navigator.javaEnabled) && navigator.javaEnabled()) { + return true; + } else { + return false; + } +}; + + +/*-------------------------------------------------------------- +# AUDIO +--------------------------------------------------------------*/ + +satus.user.browser.audio = function () { + var audio = document.createElement('audio'), + types = { + mp3: 'audio/mpeg', + mp4: 'audio/mp4', + aif: 'audio/x-aiff' + }, + result = []; + + if (satus.isFunction(audio.canPlayType)) { + for (var key in types) { + var can_play_type = audio.canPlayType(types[key]); + + if (can_play_type !== '') { + result.push(key); + } + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# VIDEO +--------------------------------------------------------------*/ + +satus.user.browser.video = function () { + var video = document.createElement('video'), + types = { + ogg: 'video/ogg; codecs="theora"', + h264: 'video/mp4; codecs="avc1.42E01E"', + webm: 'video/webm; codecs="vp8, vorbis"', + vp9: 'video/webm; codecs="vp9"', + hls: 'application/x-mpegURL; codecs="avc1.42E01E"' + }, + result = []; + + if (satus.isFunction(video.canPlayType)) { + for (var key in types) { + var can_play_type = video.canPlayType(types[key]); + + if (can_play_type !== '') { + result.push(key); + } + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# WEBGL +--------------------------------------------------------------*/ + +satus.user.browser.webgl = function () { + var cvs = document.createElement('canvas'), + ctx = cvs.getContext('webgl'); + + return ctx && ctx instanceof WebGLRenderingContext; +}; + + +/*-------------------------------------------------------------- +# HARDWARE +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# SCREEN +--------------------------------------------------------------*/ + +satus.user.device.screen = function () { + if (screen) { + return screen.width + 'x' + screen.height; + } +}; + + +/*-------------------------------------------------------------- +# RAM +--------------------------------------------------------------*/ + +satus.user.device.ram = function () { + if ('deviceMemory' in navigator) { + return navigator.deviceMemory + ' GB'; + } +}; + + +/*-------------------------------------------------------------- +# GPU +--------------------------------------------------------------*/ + +satus.user.device.gpu = function () { + var cvs = document.createElement('canvas'), + ctx = cvs.getContext('webgl'); + + if ( + ctx && + ctx instanceof WebGLRenderingContext && + 'getParameter' in ctx && + 'getExtension' in ctx + ) { + var info = ctx.getExtension('WEBGL_debug_renderer_info'); + + if (info) { + return ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); + } + } +}; + + +/*-------------------------------------------------------------- +# CORES +--------------------------------------------------------------*/ + +satus.user.device.cores = function () { + return navigator.deviceConcurrency; +}; + + +/*-------------------------------------------------------------- +# TOUCH +--------------------------------------------------------------*/ + +satus.user.device.touch = function () { + var result = {}; + + if ( + window.hasOwnProperty('ontouchstart') || + window.DocumentTouch && document instanceof window.DocumentTouch || + navigator.maxTouchPoints > 0 || + window.navigator.msMaxTouchPoints > 0 + ) { + result.touch = true; + result.maxTouchPoints = navigator.maxTouchPoints; + } + + return result; +}; + + +/*-------------------------------------------------------------- +# CONNECTION +--------------------------------------------------------------*/ + +satus.user.device.connection = function () { + var result = {}; + + if (typeof navigator.connection === 'object') { + result.type = navigator.connection.effectiveType || null; + + if (navigator.connection.downlink) { + result.speed = navigator.connection.downlink + ' Mbps'; + } + } + + return result; +}; +/*-------------------------------------------------------------- +# SEARCH +--------------------------------------------------------------*/ + +satus.search = function (query, object, callback) { + var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker'], + threads = 0, + results = {}, + excluded = [ + 'baseProvider', + 'childrenContainer', + 'parentElement', + 'parentObject', + 'parentSkeleton', + 'rendered', + 'namespaceURI' + ]; + + query = query.toLowerCase(); + + function parse(items, parent) { + threads++; + + for (var key in items) { + if (excluded.indexOf(key) === -1) { + var item = items[key]; + + if (item.component) { + //console.log(key, item.component); + + if (elements.indexOf(item.component) !== -1 && key.indexOf(query) !== -1) { + results[key] = Object.assign({}, item); + } + } + + if (typeof item === 'object') { + parse(item, items); + } + } + } + + threads--; + + if (threads === 0) { + callback(results); + } + } + + parse(object); +}; diff --git a/background.js b/background.js new file mode 100644 index 0000000..7fe8c64 --- /dev/null +++ b/background.js @@ -0,0 +1,13 @@ +/*-------------------------------------------------------------- +>>> BACKGROUND +--------------------------------------------------------------*/ + +chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { + var action = message.action; + + if (action === 'options-page-connected') { + sendResponse({ + isPopup: sender.hasOwnProperty('tab') === false + }); + } +}); \ No newline at end of file diff --git a/manifest.json b/manifest.json index ed6adee..98e6c6e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,24 +1,27 @@ { - "manifest_version": 2, - "name": "ToDo", - "description": "__MSG_description__", - "version": "3.1", - "default_locale": "en", - "icons": { - "16": "icons/16.png", - "32": "icons/32.png", - "48": "icons/48.png", - "128": "icons/128.png" - }, - "browser_action": { - "default_popup": "ui/popup.html" - }, - "options_page": "ui/options.html", - "optional_permissions": [ - "downloads" - ], - "offline_enabled": true, - "permissions": [ - "storage" - ] -} + "manifest_version": 3, + "name": "ToDo", + "description": "__MSG_description__", + "version": "3.4", + "default_locale": "en", + "icons": { + "16": "assets/icons/16.png", + "32": "assets/icons/32.png", + "48": "assets/icons/48.png", + "128": "assets/icons/128.png" + }, + "background": { + "service_worker": "background.js" + }, + "action": { + "default_popup": "options-page/index.html" + }, + "options_page": "options-page/index.html", + "optional_permissions": [ + "downloads" + ], + "permissions": [ + "storage" + ], + "offline_enabled": true +} \ No newline at end of file diff --git a/options-page/functions.js b/options-page/functions.js new file mode 100644 index 0000000..0866a60 --- /dev/null +++ b/options-page/functions.js @@ -0,0 +1,712 @@ +/*-------------------------------------------------------------- +>>> FUNCTIONS +---------------------------------------------------------------- +# Export settings +# Import settings +# Update lists +# Update tasks +# Update data +# Encryption +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# EXPORT SETTINGS +--------------------------------------------------------------*/ + +extension.exportSettings = function () { + if (location.href.indexOf('action=export-settings') !== -1) { + satus.render({ + component: 'modal', + variant: 'confirm', + content: 'areYouSureYouWantToExportTheData', + buttons: { + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + try { + var blob = new Blob([JSON.stringify(satus.storage.data)], { + type: 'application/json;charset=utf-8' + }); + + chrome.permissions.request({ + permissions: ['downloads'] + }, function (granted) { + if (granted) { + chrome.downloads.download({ + url: URL.createObjectURL(blob), + filename: 'user-agent.json', + saveAs: true + }, function () { + setTimeout(function () { + close(); + }, 1000); + }); + } + }); + } catch (error) { + console.error(error); + } + } + } + } + } + }, extension.skeleton.rendered); + } +}; + + +/*-------------------------------------------------------------- +# IMPORT SETTINGS +--------------------------------------------------------------*/ + +extension.importSettings = function () { + if (location.href.indexOf('action=import-settings') !== -1) { + satus.render({ + component: 'modal', + variant: 'confirm', + content: 'areYouSureYouWantToImportTheData', + buttons: { + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + var input = document.createElement('input'); + + input.type = 'file'; + + input.addEventListener('change', function () { + var file_reader = new FileReader(); + + file_reader.onload = function () { + var data = JSON.parse(this.result); + + for (var key in data) { + satus.storage.set(key, data[key]); + } + + setTimeout(function () { + chrome.runtime.sendMessage({ + action: 'import-settings' + }); + + setTimeout(function () { + close(); + }, 128); + }, 256); + }; + + file_reader.readAsText(this.files[0]); + }); + + input.click(); + } + } + } + } + }, extension.skeleton.rendered); + } +}; + + +/*-------------------------------------------------------------- +# UPDATE LISTS +--------------------------------------------------------------*/ + +extension.updateLists = function () { + var layer = satus.last(extension.skeleton.main.layers.rendered.children), + section = { + component: 'section', + variant: 'card' + }; + + if (extension.lists.length === 0) { + section.span = { + component: 'span', + text: 'noLists', + style: { + 'display': 'flex', + 'alignItems': 'center' + } + }; + } + + for (var i = 0, l = extension.lists.length; i < l; i++) { + var list = extension.lists[i]; + + section['list_' + i] = { + component: 'button', + variant: 'folder', + attr: { + title: list.name + }, + text: list.name, + before: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': list.color || extension.color[0] + }, + + path: { + component: 'path', + attr: { + 'd': extension.icons[list.icon] || extension.icons['folder'] + } + } + }, + list: list, + sortable: true, + contextMenu: { + rename: { + component: 'button', + text: 'rename', + on: { + click: function () { + var modal = this.parentNode.parentNode; + + satus.render({ + component: 'modal', + parentSkeleton: modal.skeleton.parentSkeleton, + + title: { + component: 'span', + text: 'rename' + }, + input: { + component: 'input', + type: 'text', + attr: { + 'autofocus': true, + 'value': modal.skeleton.parentSkeleton.list.name + }, + on: { + render: function () { + this.focus(); + this.select(); + }, + keydown: function (event) { + if (event.key === 'Enter') { + this.parentNode.parentNode.skeleton.actions.ok.rendered.click(); + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + modal.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode, + item = modal.skeleton.parentSkeleton; + + item.list.name = modal.skeleton.input.rendered.value; + + extension.updateData(); + + extension.updateLists(); + + modal.close(); + } + } + } + } + }, modal.baseProvider); + + modal.close(); + } + } + }, + changeIcon: { + component: 'button', + text: 'changeIcon', + on: { + click: function () { + var modal = this.parentNode.parentNode; + + satus.render({ + component: 'modal', + parentSkeleton: modal.skeleton, + + label: { + component: 'span', + text: 'icons' + }, + grid: { + component: 'section', + variant: 'grid', + style: { + margin: '12px 0 6px', + justifyContent: 'center' + }, + on: { + render: function () { + var list = this.skeleton.parentSkeleton.parentSkeleton.parentSkeleton.list; + + for (var key in extension.icons) { + var skeleton = { + component: 'button', + data: { + key: key + }, + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + list = modal.parentSkeleton.parentSkeleton.list; + + list.icon = this.dataset.key; + + extension.updateData(); + + extension.updateLists(); + + modal.rendered.close(); + } + }, + + svg: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'currentColor' + }, + + path: { + component: 'path', + attr: { + 'd': extension.icons[key] + } + } + } + }; + + if ( + satus.isset(list.icon) === false && key === 'folder' || + list.icon === key + ) { + skeleton.svg.attr.fill = 'var(--satus-primary)'; + } + + satus.render(skeleton, this); + } + } + } + } + }, modal.baseProvider); + + modal.close(); + } + } + }, + changeColor: { + component: 'button', + text: 'changeColor', + on: { + click: function () { + var modal = this.parentNode.parentNode; + + satus.render({ + component: 'modal', + parentSkeleton: modal.skeleton, + + label: { + component: 'span', + text: 'color' + }, + grid: { + component: 'section', + variant: 'grid', + style: { + margin: '12px 0 6px', + justifyContent: 'center' + }, + on: { + render: function () { + var list = this.skeleton.parentSkeleton.parentSkeleton.parentSkeleton.list; + + for (var color of extension.color) { + var skeleton = { + component: 'button', + data: { + color + }, + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + list = modal.parentSkeleton.parentSkeleton.list; + + list.color = this.dataset.color; + + extension.updateData(); + + extension.updateLists(); + + modal.rendered.close(); + } + }, + + circle: { + component: 'span', + style: { + width: '20px', + height: '20px', + backgroundColor: color, + borderRadius: '50%' + } + } + }; + + /*if ( + satus.isset(list.color) === false && color === list.color[0] || + list.color === color + ) { + skeleton.svg.attr.fill = 'var(--satus-primary)'; + }*/ + + satus.render(skeleton, this); + } + } + } + } + }, modal.baseProvider); + + modal.close(); + } + } + }, + remove: { + component: 'button', + text: 'remove', + on: { + click: function () { + var modal = this.parentNode.parentNode, + parent = modal.skeleton.parentSkeleton; + + satus.remove(parent.list, extension.lists); + + extension.updateData(); + + extension.updateLists(); + + modal.close(); + } + } + } + }, + on: { + click: { + component: 'section', + variant: 'card', + tasks: list.tasks, + on: { + render: function () { + extension.updateTasks(this.skeleton.tasks); + } + } + }, + sort: function () { + var index = satus.indexOf(this); + + satus.toIndex(index, this.skeleton.list, extension.lists); + + extension.updateData(); + } + } + }; + } + + satus.empty(layer); + + satus.render(section, layer); +}; + + +/*-------------------------------------------------------------- +# UPDATE TASKS +--------------------------------------------------------------*/ + +extension.updateTasks = function (tasks) { + var path = extension.skeleton.main.layers.rendered.path, + section = path[path.length - 1].rendered; + + satus.empty(section); + + if (tasks.length === 0) { + satus.render({ + component: 'span', + text: 'noTasks', + style: { + 'display': 'flex', + 'alignItems': 'center' + } + }, section); + } + + for (var i = 0, l = tasks.length; i < l; i++) { + var task = tasks[i]; + + satus.render({ + component: 'checkbox', + attr: { + title: task.name + }, + text: [task.name], + value: task.value, + storage: false, + tasks: tasks, + task: task, + contextMenu: { + rename: { + component: 'button', + text: 'rename', + on: { + click: function () { + var modal = this.parentNode.parentNode; + + satus.render({ + component: 'modal', + parentSkeleton: modal.skeleton.parentSkeleton, + + title: { + component: 'span', + text: 'rename' + }, + input: { + component: 'input', + type: 'text', + attr: { + 'autofocus': true, + 'value': modal.skeleton.parentSkeleton.task.name + }, + on: { + render: function () { + this.focus(); + this.select(); + }, + keydown: function (event) { + if (event.key === 'Enter') { + this.parentNode.parentNode.skeleton.actions.ok.rendered.click(); + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + modal.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode, + item = modal.skeleton.parentSkeleton; + + item.task.name = modal.skeleton.input.rendered.value; + + extension.updateData(); + + extension.updateTasks(item.tasks); + + modal.close(); + } + } + } + } + }, modal.baseProvider); + + modal.close(); + } + } + }, + remove: { + component: 'button', + text: 'remove', + on: { + click: function () { + var path = extension.skeleton.main.layers.rendered.path, + layer = path[path.length - 1], + modal = this.parentNode.parentNode, + parent = modal.skeleton.parent; + + satus.remove(parent.task, parent.tasks); + + extension.updateData(); + + extension.updateTasks(parent.tasks); + + modal.close(); + } + } + } + }, + sortable: true, + on: { + change: function () { + console.log(this.skeleton.task); + this.skeleton.task.value = this.storage.value; + + extension.updateData(); + }, + sort: function () { + var index = satus.indexOf(this); + + satus.toIndex(index, this.skeleton.task, this.skeleton.tasks); + + extension.updateData(); + } + } + }, section); + } +}; + + +/*-------------------------------------------------------------- +# UPDATE DATA +--------------------------------------------------------------*/ + +extension.updateData = function () { + if (satus.storage.get('encrypted') === true && extension.password) { + extension.encr(); + } else { + satus.storage.set('lists', extension.lists); + } +}; + + +/*-------------------------------------------------------------- +# ENCRYPTION +--------------------------------------------------------------*/ + +extension.crypt = function (mode, data, callback, component) { + satus.render({ + component: 'modal', + parentSkeleton: component ? component.skeleton : undefined, + on: { + close: function () { + if (this.skeleton.parentSkeleton) { + var component = this.skeleton.parentSkeleton.parentSkeleton.encrypted.rendered; + + if (satus.storage.get('encrypted') === true) { + component.dataset.value = 'true'; + } else { + component.dataset.value = 'false'; + } + } + } + }, + + title: { + component: 'span', + text: mode ? 'encryption' : 'decryption' + }, + input: { + component: 'input', + attr: { + type: 'password' + }, + on: { + render: function () { + this.focus(); + }, + keydown: async function (event) { + if (event.key === 'Enter') { + this.parentNode.parentNode.skeleton.actions.ok.rendered.click(); + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + ok: { + component: 'button', + text: 'ok', + on: { + click: async function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + input = modal.input.rendered, + result = false; + + if (input.value.length > 1) { + if (mode) { + result = await satus.encrypt(data, input.value); + extension.password = input.value; + } else { + result = JSON.parse(await satus.decrypt(data, input.value)); + extension.password = input.value; + } + + if (result) { + callback(mode, result); + + modal.rendered.close(); + } else { + input.classList.add('error'); + } + } else { + input.classList.add('error'); + } + } + } + } + } + }, document.querySelector('.satus-base')); +}; + +extension.encr = async function (callback) { + satus.storage.set('lists', await satus.encrypt(JSON.stringify(extension.lists), extension.password)); + satus.storage.set('encrypted', true); + satus.storage.remove('data'); + + if (callback) { + callback(); + } +}; \ No newline at end of file diff --git a/options-page/index.css b/options-page/index.css new file mode 100644 index 0000000..a00dccc --- /dev/null +++ b/options-page/index.css @@ -0,0 +1,205 @@ +/*-------------------------------------------------------------- +>>> USER INTERFACE +---------------------------------------------------------------- +# Fonts +# Themes +# Header +# Layers + Folder +# Create +# Tab +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# FONTS +--------------------------------------------------------------*/ + +@font-face { + font-family: Roboto; + + src: url(../assets/fonts/Roboto-Regular.ttf); +} + +@font-face { + font-family: Roboto; + font-weight: 500; + + src: url(../assets/fonts/Roboto-Medium.ttf); +} + +@font-face { + font-family: Roboto; + font-weight: 700; + + src: url(../assets/fonts/Roboto-Bold.ttf); +} + + +/*-------------------------------------------------------------- +# THEMES +--------------------------------------------------------------*/ + +body { + --satus-light: 0, 0, 0; + --satus-primary: #f6b465; + --satus-header-background: #fff; + --satus-header-shadow: 0 0 3px rgba(var(--satus-light), .1), inset 0 -1px 0 rgba(var(--satus-light), .1); + --satus-header-foreground: #848471; + --satus-base-background: #f6f6f4; + --satus-base-foreground: #848471; + --satus-section-card-background: #fff; + --satus-section-card-border: rgba(var(--satus-light), .1); + --satus-modal-background: #f6f6f4; + --satus-modal-border: rgba(var(--satus-light), .1); + --satus-modal-text: #848471; + --satus-tabs-background: #e8e8e3; + --satus-tabs-foreground: #fff; +} + +body[theme='dark'] { + --satus-light: 255, 255, 255; + --satus-primary: #8f8f8f; + --satus-base-background: #000; + --satus-base-foreground: #ccc; + --satus-switch-background: rgba(var(--satus-light), .08); + --satus-header-background: #1f1f1f; + --satus-header-border: rgba(var(--satus-light), .08); + --satus-header-foreground: #ccc; + --satus-layers-background: #000; + --satus-layers-foreground: #ccc; + --satus-section-background: #1e1e1e; + --satus-section-border: rgba(var(--satus-light), .08); + --satus-modal-background: #212121; + --satus-modal-border: rgba(var(--satus-light), .08); + --satus-modal-shadow: 0 1px 4px rgba(var(--satus-light), .08); + --satus-modal-foreground: #ccc; + --satus-hover: rgba(var(--satus-light), .05); + --satus-input-text-background: #333; + --satus-input-text-border: #525252; + --satus-input-text-foreground: #ccc; + --satus-switch-track: #111; + --satus-switch-track--active: var(--satus-primary); + --satus-switch-thumb: #ddd; + --satus-tooltip: rgba(var(--satus-light), .4); + --satus-sortable-ghost: rgba(var(--satus-light), .8); + --satus-sortable-background: rgba(var(--satus-light), .1); + --satus-sortable-foreground: #fff; + --satus-divider: rgba(var(--satus-light), .08); + --satus-tabs-background: #111; + --satus-tabs-foreground: #2e2e2e; + --satus-tabs-border: #2f2f2f; + --satus-checkbox--background: rgb(var(--satus-light), .08); + --satus-checkbox--border: #2f2f2f; + --satus-checkbox--mark: #fff; + --satus-alert-error-background: #501616; + --satus-alert-error-border: #6f1f1f; + --satus-alert-error-color: #cf7777; +} + + +/*-------------------------------------------------------------- +# HEADER +--------------------------------------------------------------*/ + +.satus-header .satus-section--align-start { + max-width: calc(100% - 40px); +} + + +/*-------------------------------------------------------------- +# LAYERS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# FOLDER +--------------------------------------------------------------*/ + +.satus-button--folder { + display: flex; + + align-items: center; +} + +.satus-button.satus-button--folder>svg { + width: 20px; + min-width: 20px; + margin: -2px 16px 0 0; +} + +.satus-button--folder>.satus-span { + display: block; + overflow: hidden; + + white-space: nowrap; + text-overflow: ellipsis; +} + + +/*-------------------------------------------------------------- +# CREATE +--------------------------------------------------------------*/ + +.satus-button--create { + position: fixed; + right: 16px; + bottom: 16px; + + width: 56px; + height: 56px; + + color: #fff; + border-radius: 50%; + background: linear-gradient(135deg, #f8d266, #f17953); + box-shadow: 0 2px 1px 1px rgb(230, 109, 70, .7), 0 3px 5px rgb(0, 0, 0, .35); +} + +.satus-button--create::before { + position: absolute; + top: calc(50% - 1px); + left: calc(50% - 7px); + + width: 14px; + height: 2px; + + content: ''; + + background: currentColor; +} + +.satus-button--create::after { + position: absolute; + top: calc(50% - 7px); + left: calc(50% - 1px); + + width: 2px; + height: 14px; + + content: ''; + + background: currentColor; +} + + +/*-------------------------------------------------------------- +# TAB +--------------------------------------------------------------*/ + +body[tab] { + overflow: hidden; + + width: 100vw; + height: 100vh; +} + +body[tab] .satus-base { + width: 100%; + height: 100%; +} + +body[tab] .satus-alert { + display: none; +} + +.satus-modal__surface { + max-width: 290px; +} \ No newline at end of file diff --git a/options-page/index.html b/options-page/index.html new file mode 100644 index 0000000..9f6980a --- /dev/null +++ b/options-page/index.html @@ -0,0 +1,27 @@ + + +
+ + +