diff --git a/_locales/am/messages.json b/_locales/am/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/am/messages.json +++ b/_locales/am/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/ar/messages.json b/_locales/ar/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/ar/messages.json +++ b/_locales/ar/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/bg/messages.json b/_locales/bg/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/bg/messages.json +++ b/_locales/bg/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/bn/messages.json b/_locales/bn/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/bn/messages.json +++ b/_locales/bn/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/ca/messages.json b/_locales/ca/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/ca/messages.json +++ b/_locales/ca/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/cs/messages.json b/_locales/cs/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/cs/messages.json +++ b/_locales/cs/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/da/messages.json b/_locales/da/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/da/messages.json +++ b/_locales/da/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/de/messages.json b/_locales/de/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/el/messages.json b/_locales/el/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/el/messages.json +++ b/_locales/el/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/es/messages.json b/_locales/es/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/et/messages.json b/_locales/et/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/et/messages.json +++ b/_locales/et/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/fa/messages.json b/_locales/fa/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/fa/messages.json +++ b/_locales/fa/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/fi/messages.json b/_locales/fi/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/fi/messages.json +++ b/_locales/fi/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/fil/messages.json b/_locales/fil/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/fil/messages.json +++ b/_locales/fil/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/gu/messages.json b/_locales/gu/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/gu/messages.json +++ b/_locales/gu/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/he/messages.json b/_locales/he/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/he/messages.json +++ b/_locales/he/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/hin/messages.json b/_locales/hin/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/hin/messages.json +++ b/_locales/hin/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/hr/messages.json b/_locales/hr/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/hr/messages.json +++ b/_locales/hr/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/hu/messages.json +++ b/_locales/hu/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/id/messages.json b/_locales/id/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/id/messages.json +++ b/_locales/id/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/it/messages.json b/_locales/it/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/kn/messages.json b/_locales/kn/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/kn/messages.json +++ b/_locales/kn/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/lt/messages.json b/_locales/lt/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/lt/messages.json +++ b/_locales/lt/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/lv/messages.json b/_locales/lv/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/lv/messages.json +++ b/_locales/lv/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/ml/messages.json b/_locales/ml/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/ml/messages.json +++ b/_locales/ml/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/mr/messages.json b/_locales/mr/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/mr/messages.json +++ b/_locales/mr/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/ms/messages.json b/_locales/ms/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/ms/messages.json +++ b/_locales/ms/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/nb_NO/messages.json b/_locales/nb_NO/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/nb_NO/messages.json +++ b/_locales/nb_NO/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/no/messages.json b/_locales/no/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/no/messages.json +++ b/_locales/no/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/pt_PT/messages.json b/_locales/pt_PT/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/pt_PT/messages.json +++ b/_locales/pt_PT/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/ro/messages.json b/_locales/ro/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/ro/messages.json +++ b/_locales/ro/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/sk/messages.json b/_locales/sk/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/sk/messages.json +++ b/_locales/sk/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/sl/messages.json b/_locales/sl/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/sl/messages.json +++ b/_locales/sl/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/sr/messages.json b/_locales/sr/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/sr/messages.json +++ b/_locales/sr/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/sw/messages.json b/_locales/sw/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/sw/messages.json +++ b/_locales/sw/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/ta/messages.json b/_locales/ta/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/ta/messages.json +++ b/_locales/ta/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/te/messages.json b/_locales/te/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/te/messages.json +++ b/_locales/te/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/th/messages.json b/_locales/th/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/th/messages.json +++ b/_locales/th/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/vi/messages.json b/_locales/vi/messages.json index 9e26dfe..025a5f6 100644 --- a/_locales/vi/messages.json +++ b/_locales/vi/messages.json @@ -1 +1,71 @@ -{} \ No newline at end of file +{ + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Cancel" + }, + "characters": { + "message": "characters" + }, + "closeFile": { + "message": "Close file" + }, + "column": { + "message": "Column" + }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, + "file": { + "message": "File" + }, + "help": { + "message": "Help" + }, + "line": { + "message": "Line" + }, + "lines": { + "message": "lines" + }, + "newFile": { + "message": "New file" + }, + "openFile": { + "message": "Open file..." + }, + "quit": { + "message": "Quit" + }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, + "saveAs": { + "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" + } +} \ No newline at end of file diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index d9ba4e4..025a5f6 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -1,26 +1,71 @@ { + "areYouSureYouWantToDeleteTheFile": { + "message": "Are you sure you want to delete the file?" + }, "bytes": { "message": "Bytes" }, + "cancel": { + "message": "Cancel" + }, "characters": { - "message": "Characters" + "message": "characters" + }, + "closeFile": { + "message": "Close file" }, "column": { "message": "Column" }, + "delete": { + "message": "Delete" + }, + "deleteFile": { + "message": "Delete file" + }, + "edit": { + "message": "Edit" + }, "file": { "message": "File" }, + "help": { + "message": "Help" + }, "line": { "message": "Line" }, + "lines": { + "message": "lines" + }, "newFile": { "message": "New file" }, + "openFile": { + "message": "Open file..." + }, "quit": { "message": "Quit" }, + "redo": { + "message": "Redo" + }, + "rename": { + "message": "Rename" + }, + "reportABug": { + "message": "Report a bug" + }, + "save": { + "message": "Save" + }, "saveAs": { "message": "Save as..." + }, + "selected": { + "message": "selected" + }, + "undo": { + "message": "Undo" } } \ No newline at end of file diff --git a/icons/128.png b/icons/128.png index 60645db..483c75d 100644 Binary files a/icons/128.png and b/icons/128.png differ diff --git a/icons/16.png b/icons/16.png index 3bddb3e..ba267fb 100644 Binary files a/icons/16.png and b/icons/16.png differ diff --git a/icons/32.png b/icons/32.png index 4dfbbca..6c76283 100644 Binary files a/icons/32.png and b/icons/32.png differ diff --git a/icons/48.png b/icons/48.png index 91efea7..2d4f150 100644 Binary files a/icons/48.png and b/icons/48.png differ diff --git a/manifest.json b/manifest.json index 74ea21c..5b32fc1 100644 --- a/manifest.json +++ b/manifest.json @@ -4,10 +4,16 @@ "description": "", "version": "2.0", "default_locale": "en", + "icons": { + "16": "icons/16.png", + "32": "icons/32.png", + "48": "icons/48.png", + "128": "icons/128.png" + }, "action": { - "default_popup": "popup.html" + "default_popup": "ui/popup.html" }, - "options_page": "options.html", + "options_page": "ui/options.html", "offline_enabled": true, "optional_permissions": [ "downloads" diff --git a/script.js b/script.js deleted file mode 100644 index 84fd7a8..0000000 --- a/script.js +++ /dev/null @@ -1,152 +0,0 @@ -/*-------------------------------------------------------------- ->>> TEXT EDITOR ----------------------------------------------------------------- -# ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# ---------------------------------------------------------------*/ - -var skeleton = { - component: 'base', - - menubar: { - component: 'menubar', - items: [ - [{ - component: 'button', - text: 'file' - }, - { - component: 'button', - text: 'newFile' - }, - { - component: 'button', - text: 'saveAs' - }, - { - component: 'button', - text: 'quit' - } - ] - ] - }, - main: { - component: 'main', - - textarea: { - component: 'textarea', - on: { - input: function () { - var section_align_end = skeleton.footer.section_align_end, - characters = this.value.length, - bytes = new Blob([this.value]).size; - - section_align_end.characters.value.rendered.textContent = characters; - section_align_end.bytes.value.rendered.textContent = bytes; - }, - selectionchange: function () { - var textarea = skeleton.main.textarea.rendered, - section_align_start = skeleton.footer.section_align_start, - column = 0; - - if (textarea.selectionDirection === 'forward') { - var column = textarea.selectionEnd; - } else { - var column = textarea.selectionStart; - } - - var lines = textarea.value.substr(0, column).split('\n'); - - section_align_start.line.value.rendered.textContent = lines.length; - section_align_start.column.value.rendered.textContent = lines[lines.length - 1].length + 1; - } - } - } - }, - footer: { - component: 'footer', - - section_align_start: { - component: 'section', - variant: 'align-start', - - line: { - component: 'span', - - label: { - component: 'span', - text: 'line' - }, - value: { - component: 'span', - text: '0' - } - }, - column: { - component: 'span', - - label: { - component: 'span', - text: 'column' - }, - value: { - component: 'span', - text: '0' - } - } - }, - section_align_end: { - component: 'section', - variant: 'align-end', - - characters: { - component: 'span', - - label: { - component: 'span', - text: 'characters' - }, - value: { - component: 'span', - text: '0' - } - }, - bytes: { - component: 'span', - - label: { - component: 'span', - text: 'bytes' - }, - value: { - component: 'span', - text: '0' - } - } - } - } -}; - - -/*-------------------------------------------------------------- -# INITIALIZATION ---------------------------------------------------------------*/ - -satus.storage.import(function (items) { - var language = items.language || window.navigator.language; - - if (language.indexOf('en') === 0) { - language = 'en'; - } - - satus.fetch('_locales/' + language + '/messages.json', function (object) { - for (var key in object) { - satus.locale.strings[key] = object[key].message; - } - - satus.render(skeleton); - }); -}); \ No newline at end of file diff --git a/styles.css b/styles.css deleted file mode 100644 index 4ee6028..0000000 --- a/styles.css +++ /dev/null @@ -1,66 +0,0 @@ -/*-------------------------------------------------------------- ->>> TEXT EDITOR ----------------------------------------------------------------- -# Base -# Main -# Footer ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# BASE ---------------------------------------------------------------*/ - -.satus-base { - --satus-menubar-background: #1a1f23; - --satus-menubar-text: #6e7377; - --satus-main-background: #2f3841; -} - - -/*-------------------------------------------------------------- -# MAIN ---------------------------------------------------------------*/ - -.satus-main { - flex: 1; -} - -.satus-textarea { - font: inherit; - box-sizing: border-box; - width: 100%; - height: 100%; - padding: 4px 0; - resize: none; - color: #d8dee9; - border: none; - outline: none; - background: transparent; -} - - -/*-------------------------------------------------------------- -# FOOTER ---------------------------------------------------------------*/ - -.satus-footer { - font-size: 14px; - display: flex; - box-sizing: border-box; - height: 32px; - padding: 0 8px; - color: #6e7377; - background: #1a1f23; - justify-content: space-between; - align-items: center; -} - -.satus-footer .satus-section> :not(:last-child)::after { - margin: 0 4px 0 0; - content: ','; -} - -.satus-footer .satus-section>*> :not(:last-child)::after { - margin: 0 4px 0 0; - content: ':'; -} \ No newline at end of file diff --git a/options.html b/ui/options.html similarity index 80% rename from options.html rename to ui/options.html index f3bacfe..cb5be04 100644 --- a/options.html +++ b/ui/options.html @@ -6,19 +6,17 @@ Text Editor - + diff --git a/popup.html b/ui/popup.html similarity index 81% rename from popup.html rename to ui/popup.html index 190c7ea..f2bd077 100644 --- a/popup.html +++ b/ui/popup.html @@ -6,13 +6,11 @@ Text Editor diff --git a/satus/satus.css b/ui/satus/satus.css similarity index 85% rename from satus/satus.css rename to ui/satus/satus.css index b24a83d..088ec0c 100644 --- a/satus/satus.css +++ b/ui/satus/satus.css @@ -1,17 +1,4 @@ -/*-------------------------------------------------------------- ->>> ELEMENTS: ----------------------------------------------------------------- -# Hidden ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# HIDDEN ---------------------------------------------------------------*/ - -[hidden] { - display: none; -} /*-------------------------------------------------------------- >>> THEMES: ---------------------------------------------------------------- @@ -23,16 +10,20 @@ --------------------------------------------------------------*/ body { + --satus-contrast: 0, 0, 0; --satus-primary: #f6b465; - --satus-switch-background: rgba(0,0,0,.08); + --satus-switch-background: rgba(var(--satus-contrast),.08); --satus-header-background: #fff; + --satus-header-border: rgba(var(--satus-contrast),.1); --satus-header-text: #848471; --satus-layers-background: #f6f6f4; --satus-layers-text: #848471; --satus-section-card-background: #fff; + --satus-section-card-border: rgba(var(--satus-contrast),.1); --satus-modal-background: #f6f6f4; + --satus-modal-border: rgba(var(--satus-contrast), .1); --satus-modal-text: #848471; - --satus-hover: rgba(0, 0, 0, .04); + --satus-hover: rgba(var(--satus-contrast), .04); --satus-text-field--background: #e8e8e3; --satus-text-field--border: #d6d6cd; --satus-text-field--text: #848471; @@ -40,14 +31,14 @@ body { --satus-switch-track--active: var(--satus-primary); --satus-switch-thumb: #fff; --satus-tabs: #fff; - --satus-tooltip: rgba(0,0,0,.4); - --satus-sortable-ghost: rgba(0, 0, 0, .80); - --satus-sortable-background: #f9cf9f; - --satus-sortable-text: #fff; - --satus-divider: #e0e0e0; + --satus-tooltip: rgba(var(--satus-contrast),.4); + --satus-sortable-ghost: rgba(var(--satus-contrast), .80); + --satus-sortable-background: rgba(var(--satus-contrast), .08); + --satus-sortable-text: currentColor; + --satus-divider: rgba(var(--satus-contrast),.1); --satus-tabs-background: #e8e8e3; --satus-tabs-foreground: #fff; - --satus-context-menu--border: #ccc; + --satus-tabs-border: rgba(var(--satus-contrast), .1); --satus-checkbox--background: rgb(90, 90, 73, .08); --satus-checkbox--border: rgb(90, 90, 73, .16); --satus-checkbox--mark: #fff; @@ -56,757 +47,1003 @@ body { --satus-alert-error-color: #ad5f5f; } -body[theme=dark] { - --satus-primary: #90a5e0; - --satus-switch-background: rgba(0,0,0,.08); - --satus-header-background: #232b43; - --satus-header-text: #bcc4dc; - --satus-layers-background: #0e111b; - --satus-layers-text: #bcc4dc; - --satus-section-card-background: #1d2335; - --satus-modal-background: #252e46; - --satus-modal-text: #bcc4dc; - --satus-hover: rgba(255, 255, 255, .08); - --satus-text-field--background: #20273c; - --satus-text-field--border: #2e3957; - --satus-text-field--text: #c4c4d4; - --satus-switch-track: #101219; +body[data-theme=dark] { + --satus-contrast: 255, 255, 255; + --satus-primary: #8f8f8f; + --satus-switch-background: rgba(var(--satus-contrast),.08); + --satus-header-background: #1f1f1f; + --satus-header-border: rgba(var(--satus-contrast),.08); + --satus-header-text: #ccc; + --satus-layers-background: #000; + --satus-layers-text: #ccc; + --satus-section-card-background: #1e1e1e; + --satus-section-card-border: rgba(var(--satus-contrast),.08); + --satus-modal-background: #212121; + --satus-modal-border: rgba(var(--satus-contrast),.08); + --satus-modal-text: #ccc; + --satus-hover: rgba(var(--satus-contrast), .05); + --satus-text-field--background: #333333; + --satus-text-field--border: #525252; + --satus-text-field--text: #ccc; + --satus-switch-track: #111; --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #d7dcea; - --satus-tooltip: rgba(255,255,255,.4); - --satus-sortable-ghost: rgba(255, 255, 255, .8); - --satus-sortable-background: var(--satus-primary); + --satus-switch-thumb: #ddd; + --satus-tooltip: rgba(var(--satus-contrast),.4); + --satus-sortable-ghost: rgba(var(--satus-contrast), .8); + --satus-sortable-background: rgba(var(--satus-contrast), .1); --satus-sortable-text: #fff; - --satus-divider: #3e4865; - --satus-tabs-background: #1f2433; - --satus-tabs-foreground: #344165; - --satus-context-menu--border: #2e3957; - --satus-checkbox--background: rgb(233, 234, 237, .08); - --satus-checkbox--border: rgb(233, 234, 237, .16); + --satus-divider: rgba(var(--satus-contrast),.08); + --satus-tabs-background: #111; + --satus-tabs-foreground: #2e2e2e; + --satus-tabs-border: #2f2f2f; + --satus-checkbox--background: rgb(var(--satus-contrast), .08); + --satus-checkbox--border: #2f2f2f; --satus-checkbox--mark: #fff; --satus-alert-error-background: #501616; --satus-alert-error-border: #6f1f1f; --satus-alert-error-color: #cf7777; } -body[theme=black] { +body[data-theme=black] { + --satus-contrast: 255, 255, 255; --satus-primary: #8f8f8f; - --satus-switch-background: rgba(255,255,255,.08); - --satus-header-background: #1f1f1f; + --satus-switch-background: rgba(var(--satus-contrast),.08); + --satus-header-background: #000; + --satus-header-border: rgba(var(--satus-contrast),.16); --satus-header-text: #ccc; --satus-layers-background: #000; --satus-layers-text: #ccc; - --satus-section-card-background: #1a1a1a; - --satus-modal-background: #212121; + --satus-section-card-background: #000; + --satus-section-card-border: rgba(var(--satus-contrast),.16); + --satus-modal-background: #000; + --satus-modal-border: rgba(var(--satus-contrast),.16); --satus-modal-text: #ccc; - --satus-hover: rgba(255, 255, 255, .08); + --satus-hover: rgba(var(--satus-contrast), .05); --satus-text-field--background: #333333; --satus-text-field--border: #525252; --satus-text-field--text: #ccc; - --satus-switch-track: #111; + --satus-switch-track: rgba(var(--satus-contrast),.16); --satus-switch-track--active: var(--satus-primary); --satus-switch-thumb: #ddd; - --satus-tooltip: rgba(255,255,255,.4); - --satus-sortable-ghost: rgba(255, 255, 255, .8); - --satus-sortable-background: var(--satus-primary); + --satus-tooltip: rgba(var(--satus-contrast),.4); + --satus-sortable-ghost: rgba(var(--satus-contrast), .8); + --satus-sortable-background: rgba(var(--satus-contrast), .1); --satus-sortable-text: #fff; - --satus-divider: #444; + --satus-divider: rgba(var(--satus-contrast),.08); --satus-tabs-background: #111; --satus-tabs-foreground: #2e2e2e; - --satus-context-menu--border: #525252; - --satus-checkbox--background: rgb(235, 235, 235, .08); - --satus-checkbox--border: rgb(235, 235, 235, .16); + --satus-tabs-border: #2f2f2f; + --satus-checkbox--background: rgb(var(--satus-contrast), .08); + --satus-checkbox--border: #2f2f2f; --satus-checkbox--mark: #fff; --satus-alert-error-background: #501616; --satus-alert-error-border: #6f1f1f; --satus-alert-error-color: #cf7777; } /*-------------------------------------------------------------- ->>> COLOR PICKER: +>>> ELEMENTS: ---------------------------------------------------------------- -# Button -# Modal +# Reset +# Attributes + # Hidden --------------------------------------------------------------*/ - /*-------------------------------------------------------------- -# BUTTON +# RESET --------------------------------------------------------------*/ -.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; +:where([class^=satus]:not(iframe, canvas, img, svg, video, svg *, symbol *)) { + display: revert; + all: unset; } -.satus-color-picker__value { - width: 22px; - height: 22px; - border: 2px solid rgba(0, 0, 0, .16); - border-radius: 50%; - background: #fff; +:where([class^=satus]:not(iframe, canvas, img, svg, video, svg *, symbol *)) { + box-sizing: border-box; } /*-------------------------------------------------------------- -# MODAL +# ATTRIBUTES --------------------------------------------------------------*/ -.satus-modal--color-picker { - position: relative; -} +/*-------------------------------------------------------------- +# HIDDEN +--------------------------------------------------------------*/ -.satus-modal--color-picker .satus-modal__surface { - padding-top: 0; -} +[class^=satus][hidden] { + display: none; +} +/*-------------------------------------------------------------- +>>> PLUVIAM +--------------------------------------------------------------*/ -.satus-color-picker__palette { - position: relative; - overflow: hidden; - width: 100%; - height: 256px; - background-color: #f00; +.satus-pluviam { + position: absolute; + transform: scale(0); + animation-name: pluviam; + animation-duration: 1000ms; + opacity: var(--satus-pluviam-opacity, .08); + border-radius: 50%; + background: var(--satus-pluviam-background, #000); + animation-fill-mode: forwards; } -.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); -} +@keyframes pluviam { + 0% { + transform: scale(0); + opacity: var(--satus-pluviam-opacity, .08); + } + 70% { + transform: scale(.8); + opacity: var(--satus-pluviam-opacity, .08); + } + 100% { + transform: scale(1); + opacity: 0; + } +} +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ -.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-sortable__chosen { + color: var(--satus-sortable-text) !important; + background-color: var(--satus-sortable-background) !important; } -.satus-modal--color-picker .satus-modal__surface .satus-section--color { - margin: 8px 16px 0; - align-items: center; +.satus-sortable__ghost { + position: fixed !important; + z-index: 999 !important; + top: 0 !important; + left: 0 !important; + pointer-events: none !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); + will-change: transform !important; + opacity: .8 !important; +} +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ + +.satus-modal--contextmenu .satus-modal__scrim { + background: none; + backdrop-filter: none; + animation: none; + visibility: visible; + opacity: 1; + transform: none; } -.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-modal--contextmenu .satus-modal__surface { + position: absolute; + margin: 0; + box-sizing: border-box; + min-width: 200px; + max-width: 200px; + padding: 4px 0; + border-radius: 4px; + box-shadow: none; + animation: none; + visibility: visible; + opacity: 1; + transform: none; } -.satus-slider.satus-color-picker__hue { - padding: 0; - flex: 1; +.satus-modal--contextmenu .satus-modal__surface > * { + } -.satus-color-picker__hue .satus-slider__track { - height: 16px; - 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-modal--contextmenu .satus-modal__surface>* { + display: flex; + height: 32px; + padding: 0 16px; + align-items: center; } -.satus-color-picker__hue .satus-slider__handle { - width: 16px; - height: 16px; - background: #fff; - box-shadow: 0 0 4px rgb(0, 0, 0, .64); +.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-color-picker__hue::before, -.satus-color-picker__hue .satus-slider__track-fill, -.satus-color-picker__hue .satus-slider__handle:focus::after { - display: none; +.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } /*-------------------------------------------------------------- -# MAIN +>>> BASE --------------------------------------------------------------*/ -.satus-main { - color: var(--satus-main-text); - background: var(--satus-main-background); - overflow-y: auto; +.satus-base { + display: flex; + flex-direction: column; + width: 100%; + height: 100% +} +/**/ + +.satus-aside { + color: var(--satus-aside-text); + background: var(--satus-aside-background); box-sizing: border-box; } /*-------------------------------------------------------------- ->>> TABS +>>> RADIO +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +>>> CHECKBOX --------------------------------------------------------------*/ -.satus-tabs { +.satus-checkbox { + position: relative; + font: inherit; display: flex; - height: 26px !important; + color: inherit; + border: none; + background: transparent; + appearance: none; + align-items: center; + justify-content: flex-start; } -.satus-tabs__content { - position: relative; +.satus-checkbox:hover { + cursor: pointer; + background-color: var(--satus-hover); +} + +.satus-checkbox:focus { + outline: none; +} + +.satus-checkbox__content { + display: block; + white-space: nowrap; + text-overflow: ellipsis; overflow: hidden; - width: 100%; - height: 100%; - border: 2px solid var(--satus-tabs-background); - border-radius: 4px; - background: var(--satus-tabs-background); } -.satus-tabs__selection { - position: absolute; - z-index: 0; - top: 0; - left: 0; - height: 100%; - transition: left .25s; - border-radius: 4px; - background: var(--satus-tabs-foreground); +.satus-checkbox::before { + display: flex; + min-width: 16px; + width: 16px; + height: 16px; + margin: 0 12px 0 0; + content: ''; + border: 1px solid var(--satus-checkbox--border); + border-radius: 6px; + background: var(--satus-checkbox--background); + align-items: center; + justify-content: center; } -.satus-tabs__button { - font: inherit; - position: relative; - z-index: 1; - overflow: hidden; - height: 100%; - padding: 0 4px; - white-space: nowrap; - text-overflow: ellipsis; - color: inherit; - border: none; - background: transparent; - flex: 1; +.satus-checkbox[data-value=true]::before { + background: var(--satus-primary); } -.satus-tabs__button:hover { - cursor: pointer; +.satus-checkbox[data-value=true]::after { + position: absolute; + top: 20px; + left: 20px; + width: 8px; + height: 4px; + content: ''; + transform: rotate(-45deg); + border: 2px solid var(--satus-checkbox--mark); + border-top: none; + border-right: none; } /*-------------------------------------------------------------- ->>> MENUBAR +>>> SELECT --------------------------------------------------------------*/ -.satus-menubar, -.satus-menubar ul { - margin: 0; - padding: 0; - list-style: none; - background: var(--satus-menubar-background); - color: var(--satus-menubar-text); +.satus-select { + position: relative; + display: flex; + box-sizing: border-box; + align-items: center; + justify-content: space-between; } -.satus-menubar li > .satus-button { - height: 32px; - font-size: 14px; +.satus-select__content { + display: flex; + align-items: center; } -.satus-menubar > li > ul { - display: none; +.satus-select__content > svg { + width: 20px; + + height: 18px; + margin: 0 14px 0 0; + opacity: .75; +} + +.satus-select__value { + margin-left: 16px; + text-align: right; + opacity: .75; +} + +.satus-select select { + font: inherit; position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + padding: inherit; + cursor: pointer; + opacity: 0; + border: none; + outline: none; + background: none; + appearance: none; } -.satus-menubar > li > ul:hover, -.satus-menubar > li > *:focus + ul { - display: block; +.satus-select:hover { + cursor: pointer; + background-color: var(--satus-hover); } /*-------------------------------------------------------------- ->>> RADIO ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- -# BUTTON +>>> SHORTCUT: +---------------------------------------------------------------- +# --------------------------------------------------------------*/ -.satus-button { - font: inherit; - position: relative; +.satus-shortcut { + justify-content: space-between; +} + +.satus-shortcut__value { + font-size: 11px; display: flex; - overflow: hidden; - height: 48px; - margin: 0; - padding: 8px; - text-align: left; - color: var(--satus-button-text, inherit); - border: none; - background: var(--satus-button-background, transparent); - appearance: none; + text-transform: uppercase; align-items: center; } -.satus-button:hover { - cursor: pointer; - background-color: var(--satus-hover); +.satus-shortcut__actions { + display: flex; + justify-content: flex-end; } -.satus-button[hidden] { - display: none; +.satus-shortcut__actions .satus-button { + height: 32px; + margin: 8px 4px 0; + border-radius: 8px; + background: rgba(0, 0, 0, .15); } -.satus-button>svg { - min-width: 20px; +.satus-shortcut__actions .satus-button:hover { + background: rgba(0, 0, 0, .25); } -.satus-button>.satus-span--label { - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -/*-------------------------------------------------------------- ->>> LIST: ---------------------------------------------------------------*/ - -.satus-list { - list-style: none; - margin: 0; +.satus-shortcut__primary { + display: flex; + box-sizing: border-box; + width: 100%; + height: 68px; + padding: 16px; + background: rgba(0, 0, 0, .16); + align-items: center; } -.satus-list__item { - display: flex; +.satus-shortcut__key { + display: flex; + box-sizing: border-box; + min-width: 32px; + height: 32px; + padding: 4px 8px; + 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: space-between; - min-height: 48px; + justify-content: center; } -.satus-list__item>*:last-child { - text-align: right; -} -/*-------------------------------------------------------------- ->>> SECTION: ----------------------------------------------------------------- -# Align -# Card ---------------------------------------------------------------*/ +.satus-shortcut__value>.satus-shortcut__key { + font-size: 14px; + min-width: 24px; + height: 24px; +} -.satus-section { - display: flex; - box-sizing: border-box; - flex-wrap: wrap; +.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; +} -/*-------------------------------------------------------------- -# ALIGN ---------------------------------------------------------------*/ +.satus-shortcut__plus::after { + position: absolute; + top: 5px; + left: 0; + width: 12px; + height: 2px; + content: ''; + background-color: #aaa; +} -.satus-section--align-start { - align-items: center; - justify-content: flex-start; +.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-section--align-end { - align-items: center; - justify-content: flex-end; +.satus-shortcut__value>.satus-shortcut__mouse { + width: 22px; + height: 28px; } -.satus-section--space-between { - align-items: center; - justify-content: space-between; +.satus-shortcut__mouse>div { + position: absolute; + top: 0; + left: calc(50% - 1px); + width: 2px; + height: 11px; + border-radius: 2px; + background: #ccc; } -.satus-section--column { - flex-direction: column; +.satus-shortcut__mouse::before { + position: absolute; + top: -16%; + right: 14%; + width: 2px; + height: 60%; + content: ''; + background: #f96754; } +.satus-shortcut__mouse.false::before { + top: -6%; +} -/*-------------------------------------------------------------- -# CARD ---------------------------------------------------------------*/ +.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-section--card { - flex-direction: column; - box-sizing: border-box; - width: 100%; - max-width: 900px; - margin: 8px auto; - padding: 8px 0; - color: var(--satus-section-card-text); - border: 1px solid rgba(0, 0, 0, .1); - border-radius: 8px; - background: var(--satus-section-card-background); - justify-content: stretch; +.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-section--card>*:not(.satus-button) { - box-sizing: border-box; - min-height: 48px; - padding: 0 16px; - text-align: left; +.satus-shortcut__mouse.click::before { + position: absolute; + top: 0; + left: -1px; + width: 10px; + height: 10px; + content: ''; + border-radius: 50%; + background: #f96754; } -.satus-section--card>.satus-switch, -.satus-section--card>.satus-select, -.satus-section--card>.satus-radio { - display: flex; - justify-content: space-between; - align-items: center; +.satus-shortcut__mouse.context::before { + position: absolute; + top: 0; + left: 15px; + width: 10px; + height: 10px; + content: ''; + border-radius: 50%; + background: #f96754; } -.satus-section--card>.satus-button:hover, -.satus-section--card>.satus-switch:hover, -.satus-section--card>.satus-select:hover, -.satus-section--card>.satus-slider:hover, -.satus-section--card>.satus-radio:hover { - background-color: var(--satus-hover); +.satus-section_shortcut { + width: 100%; + margin: 8px 0 0; + justify-content: flex-end; } -.satus-section--card>.satus-button { - width: 100%; - padding: 0 16px; +.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; +} +/*-------------------------------------------------------------- +>>> 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-section--card>.satus-button>svg { - width: 20px; - margin: 2px 16px 0 0; - color: var(--satus-primary); +.satus-switch:hover { + cursor: pointer; } -.satus-section--card>.satus-span { - display: flex; - align-items: center; -} +.satus-switch__content { + display: flex; + align-items: center; +} + +.satus-switch__content>svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + opacity: .75; +} + + /*-------------------------------------------------------------- -# SCROLLBAR +# TRACK --------------------------------------------------------------*/ -::-webkit-scrollbar { - width: 4px; +.satus-switch>i { + width: 32px; + height: 18px; + transition: background-color 150ms; + border-radius: 18px; + background-color: var(--satus-switch-track); + flex: 0 0 32px; } -::-webkit-scrollbar:hover { - width: 8px; +.satus-section--card .satus-switch>i { + margin-left: 16px; +} + +.satus-switch[data-value='true']>i { + background-color: var(--satus-switch-track--active); +} + + +/*-------------------------------------------------------------- +# 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; } -::-webkit-scrollbar-thumb { - background: rgba(0, 0, 0, .3); +.satus-switch[data-value='true']>i::before { + transform: translateX(14px); } /*-------------------------------------------------------------- ->>> MODAL +>>> LAYERS --------------------------------------------------------------*/ -.satus-modal { - position: absolute; - z-index: 100; - top: 0; - left: 0; - display: flex; - width: 100%; - height: 100vh; - justify-content: center; - align-items: center; +.satus-layers { + position: relative; + overflow: hidden; + color: var(--satus-layers-text); + background: var(--satus-layers-background); + flex: 1; } -.satus-modal__scrim { +.satus-layer { position: absolute; top: 0; left: 0; - width: 100%; - height: 100%; - animation: modalFadeIn 150ms linear forwards; - opacity: 0; - background: rgba(0, 0, 0, .16); - backdrop-filter: blur(8px); -} - -.satus-modal__surface { display: flex; overflow-y: auto; flex-direction: column; - width: 95%; - min-width: 240px; - max-width: 560px; - max-height: 80%; - margin: 0 16px; - padding: 12px 16px; - transform: scale(.8); - animation: modalZoomIn 150ms linear forwards; - animation-delay: 20ms; - opacity: 0; - color: var(--satus-modal-text); - border-radius: 6px; - background-color: var(--satus-modal-background); - box-shadow: inset 0 -1px 1px 1px rgb(0, 0, 0, .1), 0 2px 6px rgb(0, 0, 0, .15); -} + box-sizing: border-box; + width: 100%; + height: 100%; + padding: 0 12px; + align-content: center; +} +/*-------------------------------------------------------------- +# INPUT +--------------------------------------------------------------*/ -.satus-modal__surface .satus-section--actions { - display: flex; +.satus-input[type=text], +.satus-input[type=password] { + font: inherit; + box-sizing: border-box; width: 100%; - margin: 8px 0 0; - padding: 0; - justify-content: flex-end; - align-items: center; + margin: 0; + padding: 6px 8px; + color: var(--satus-text-field--text, inherit); + border: none; + outline: none; + background: none; + appearance: none; + font-size: 16px; + margin: 8px 0; + border: 1px solid var(--satus-text-field--border); + border-radius: 4px; + background-color: var(--satus-text-field--background); +} +/*-------------------------------------------------------------- +>>> MENUBAR +--------------------------------------------------------------*/ + +.satus-menubar { + display: flex; } -.satus-modal__surface .satus-section--actions .satus-button { - font-weight: 500; - height: 32px; - margin-left: 8px; - padding: 0 8px; - letter-spacing: .5px; - color: var(--satus-primary); - border-radius: 4px; +.satus-menubar, +.satus-menubar ul { + margin: 0; + padding: 0; + list-style: none; + color: var(--satus-menubar-text); + background: var(--satus-menubar-background); } -.satus-modal--closing .satus-modal__scrim { - animation: modalFadeOut 70ms linear forwards; +.satus-menubar li { + position: relative; } -.satus-modal--closing .satus-modal__surface { - animation: modalZoomOut 70ms linear forwards; +.satus-menubar li:focus, +.satus-menubar li:hover { + background: var(--satus-menubar-hover); } -.satus-modal--vertical .satus-modal__surface { +.satus-menubar>li ul { position: absolute; - top: 8px; - right: 8px; - left: auto; - min-width: 200px; - max-width: 200px; - margin: 0; - padding: 8px 0; - transform-origin: right top; + min-width: 126px; } -.satus-modal--vertical .satus-modal__surface>.satus-button, -.satus-modal--vertical .satus-modal__surface>.satus-switch, -.satus-modal--vertical .satus-modal__surface>.satus-select { - display: flex; - height: 36px; - padding: 0 16px; - align-items: center; +.satus-menubar>li>ul ul { + top: 0; + left: 100%; } -.satus-modal--vertical .satus-modal__surface>.satus-tabs { - padding: 0 12px; +.satus-menubar li>ul { + position: absolute; + display: none; } -.satus-modal--vertical .satus-modal__surface>.satus-span { - font-size: 13px; - font-weight: 500; - margin: 6px 0; - padding: 0 12px; +.satus-menubar li>*:not(ul):focus+ul, +.satus-menubar li>*:not(ul):hover+ul, +.satus-menubar li>ul:hover { + display: block; } -.satus-modal--vertical .satus-modal__surface>.satus-button:hover, -.satus-modal--vertical .satus-modal__surface>.satus-switch:hover, -.satus-modal--vertical .satus-modal__surface>.satus-select:hover { - background-color: var(--satus-hover); -} +.satus-menubar li> :not(ul) { + font-size: 14px; + display: flex; + width: 100%; + height: 32px; + align-items: center; +} +/*-------------------------------------------------------------- +# MAIN +--------------------------------------------------------------*/ -.satus-modal--vertical .satus-button svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; - flex: 0 0 20px; -} +.satus-main { + color: var(--satus-main-text); + background: var(--satus-main-background); + overflow-y: auto; + box-sizing: border-box; +} +/*-------------------------------------------------------------- +# SCROLLBAR +--------------------------------------------------------------*/ -.satus-modal--vertical .satus-button .satus-span { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; +::-webkit-scrollbar { + width: 4px; } +::-webkit-scrollbar:hover { + width: 8px; +} +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, .3); +} /*-------------------------------------------------------------- -# ANIMATIONS +>>> TEXTAREA --------------------------------------------------------------*/ -@keyframes modalFadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } +.satus-textarea { + position: relative; + display: flex; + overflow: hidden; + color: var(--satus-textarea-color, inherit); + background: var(--satus-textarea-background); } -@keyframes modalFadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } +.satus-textarea textarea { + font-size: inherit; + line-height: 1.2; + overflow: auto; + width: 100%; + height: 100%; + padding: 0; + resize: none; + white-space: pre; + word-break: break-all; + color: inherit; + border: none; + outline: none; + background: transparent; + overflow-wrap: normal; } -@keyframes modalZoomIn { - from { - transform: scale(.8); - opacity: 0; - } - to { - transform: scale(1); - opacity: 1; - } +.satus-textarea__line-number { + padding: 0 16px 0 8px; + opacity: .5; } -@keyframes modalZoomOut { - from { - transform: scale(1); - opacity: 1; - } - to { - transform: scale(.8); - opacity: 0; - } +.satus-textarea__line-number>span { + font-size: inherit; + line-height: 1.2; + display: block; + width: 100%; + text-align: right; } /*-------------------------------------------------------------- ->>> CHECKBOX +>>> DIVIDER --------------------------------------------------------------*/ -.satus-checkbox { +.satus-divider { + height: 1px; + margin: 16px 0 12px; + background: var(--satus-divider); +} +/*-------------------------------------------------------------- +>>> TEXT FIELD +--------------------------------------------------------------*/ + +.satus-text-field { position: relative; - font: inherit; + padding: 0 16px; + background-color: var(--satus-text-field--background); + border-radius: 8px; + color: var(--satus-text-field--text); + overflow: hidden; display: flex; - color: inherit; - border: none; - background: transparent; - appearance: none; +} + +.satus-text-field__pre { + display: flex; + position: relative; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; align-items: center; - justify-content: flex-start; + flex: 1; } -.satus-checkbox:hover { - cursor: pointer; - background-color: var(--satus-hover); +.satus-text-field__input { + font: inherit; + position: absolute; + top: 0; + left: 0; + width: 100%; + min-width: 0; + max-width: none; + height: 100%; + min-height: 0; + max-height: none; + margin: 0; + padding: 0; + opacity: 0; + border: none; + appearance: none; + z-index: 9; } -.satus-checkbox:focus { - outline: none; +.satus-text-field__hidden-text { + position: absolute; + pointer-events: none; + opacity: 0; } -.satus-checkbox__content { - display: block; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; +.satus-text-field__text { + position: absolute; + top: 0; + left: 0; + display: flex; + height: 100%; + margin: 0; + align-items: center; } -.satus-checkbox::before { - display: flex; - min-width: 16px; - width: 16px; - height: 16px; - margin: 0 12px 0 0; - content: ''; - border: 1px solid var(--satus-checkbox--border); - border-radius: 6px; - background: var(--satus-checkbox--background); - align-items: center; - justify-content: center; +.satus-text-field__cursor { + position: absolute; + top: 6px; + left: 0; + display: none; + width: 2px; + height: 25px; + animation: blink 1s step-end 8; + background: #fa0; } -.satus-checkbox[data-value=true]::before { - background: var(--satus-primary); +.satus-text-field__selection { + position: absolute; + top: 5px; + left: 0; + display: none; + width: 0; + height: 25px; + border: 1px solid rgba(255, 255, 255, .2); + border-radius: 3px; + background: rgba(255, 255, 255, .1); } -.satus-checkbox[data-value=true]::after { - position: absolute; - top: 20px; - left: 20px; - width: 8px; - height: 4px; - content: ''; - transform: rotate(-45deg); - border: 2px solid var(--satus-checkbox--mark); - border-top: none; - border-right: none; -} -/*-------------------------------------------------------------- ->>> SWITCH ----------------------------------------------------------------- -# Container -# Track -# Thumb ---------------------------------------------------------------*/ +.satus-text-field__input:focus + * + * + * + .satus-text-field__cursor, +.satus-text-field__selection:not([disabled]) { + display: block; +} + +@keyframes blink { + from, + to { + opacity: 1; + } + 50% { + opacity: 0; + } +} /*-------------------------------------------------------------- -# CONTAINER +# SYNTAX HIGHLIGHTING --------------------------------------------------------------*/ -.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-text-field__text>.group { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); } -.satus-switch:hover { - cursor: pointer; +.satus-text-field__text>.character-class { + color: #ffc247; + background-color: rgb(255, 170, 0, .16); } -.satus-switch__content { - display: flex; - align-items: center; +.satus-text-field__text>.quantifier { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); } -.satus-switch__content>svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; +.satus-text-field__text>.anchor { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); } +.satus-text-field__text>.metasequence { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); +} +.satus-text-field__text>.text { + color: #c4c4d4; + background-color: rgb(196, 196, 212, .16); +} /*-------------------------------------------------------------- -# TRACK +>>> TABS --------------------------------------------------------------*/ -.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-tabs { + display: flex; + height: 26px !important; } -.satus-section--card .satus-switch>i { - margin-left: 16px; +.satus-tabs__content { + position: relative; + overflow: hidden; + width: 100%; + height: 100%; + border: 2px solid var(--satus-tabs-background); + border-radius: 4px; + background: var(--satus-tabs-background); + display: flex; } -.satus-switch[data-value='true']>i { - background-color: var(--satus-switch-track--active); +.satus-tabs__selection { + position: absolute; + z-index: 0; + top: 0; + left: 0; + height: 100%; + transition: left .25s; + border-radius: 4px; + background: var(--satus-tabs-foreground); + box-sizing: border-box; + border: 1px solid var(--satus-tabs-border); } +.satus-tabs__button { + font: inherit; + position: relative; + z-index: 1; + overflow: hidden; + height: 100%; + padding: 0 4px; + white-space: nowrap; + text-overflow: ellipsis; + color: inherit; + border: none; + background: transparent; + flex: 1; + text-align: center; +} +.satus-tabs__button:hover { + cursor: pointer; +} /*-------------------------------------------------------------- -# THUMB +>>> ALERT --------------------------------------------------------------*/ -.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-alert { + display: flex; + box-sizing: border-box; + min-height: 48px; + margin: 8px 0 0; + padding: 8px 16px; + border-radius: 8px; + align-items: center; } -.satus-switch[data-value='true']>i::before { - transform: translateX(14px); +.satus-alert--error { + color: var(--satus-alert-error-color); + border: 1px solid var(--satus-alert-error-border); + background: var(--satus-alert-error-background); } /*-------------------------------------------------------------- >>> SLIDER @@ -821,74 +1058,75 @@ body[theme=black] { .satus-slider__container { position: relative; - height: 32px; + display: block; width: 100%; + height: 32px; } .satus-slider__track { position: absolute; top: 50%; left: 0; - height: 2px; width: 100%; + height: 2px; transform: translateY(-50%); } .satus-slider__track::before { position: absolute; - left: 0; top: 0; + left: 0; width: 100%; height: 100%; - background: var(--satus-primary); - opacity: .24; content: ''; + opacity: .24; + background: var(--satus-primary); } .satus-slider__handle:focus::after { - content: attr(data-value); position: absolute; - left: 50%; top: -2px; - background: var(--satus-primary); - color: #fff; + left: 50%; display: block; - transform: translate(-50%, -100%); padding: 1px 4px; + content: attr(data-value); + transform: translate(-50%, -100%); + color: #fff; border-radius: 4px; + background: var(--satus-primary); } .satus-slider__track-fill { position: absolute; - left: 0; top: 0; + left: 0; height: 100%; background: var(--satus-primary); } .satus-slider__handle { position: absolute; + top: 50%; + left: 0; width: 10px; height: 10px; - background: var(--satus-primary); - border-radius: 50%; transform: translate(-50%, -50%); - top: 50%; - left: 0; + border-radius: 50%; + background: var(--satus-primary); } .satus-slider__handle::before { - content: ''; - background: var(--satus-primary); position: absolute; - left: 50%; top: 50%; + left: 50%; width: 1px; height: 1px; + content: ''; + transition: .2s; + transform: translate(-50%, -50%) scale(1); opacity: 0; border-radius: 50%; - transform: translate(-50%, -50%) scale(1); - transition: .2s; + background: var(--satus-primary); } .satus-slider:focus .satus-slider__handle::before { @@ -896,339 +1134,239 @@ body[theme=black] { opacity: .24; } /*-------------------------------------------------------------- ->>> SHORTCUT: +>>> COLOR PICKER: ---------------------------------------------------------------- -# +# Button +# Modal --------------------------------------------------------------*/ -.satus-shortcut { - justify-content: space-between; -} - -.satus-shortcut__value { - font-size: 11px; - display: flex; - text-transform: uppercase; - align-items: center; -} - -.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); -} +/*-------------------------------------------------------------- +# BUTTON +--------------------------------------------------------------*/ -.satus-shortcut__primary { +.satus-color-picker { + font-size: inherit; + position: relative; display: flex; box-sizing: border-box; - width: 100%; - height: 68px; - padding: 16px; - background: rgba(0, 0, 0, .16); + 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-shortcut__key { - display: flex; - box-sizing: border-box; - min-width: 32px; - height: 32px; - padding: 4px 8px; - border-radius: 4px; +.satus-color-picker__value { + width: 22px; + height: 22px; + border: 2px solid rgba(0, 0, 0, .16); + border-radius: 50%; 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; -} +/*-------------------------------------------------------------- +# MODAL +--------------------------------------------------------------*/ -.satus-shortcut__plus::before { - position: absolute; - top: 0; - left: 5px; - width: 2px; - height: 12px; - content: ''; - background-color: #aaa; +.satus-modal--color-picker { + position: relative; } -.satus-shortcut__plus::after { - position: absolute; - top: 5px; - left: 0; - width: 12px; - height: 2px; - content: ''; - background-color: #aaa; +.satus-modal--color-picker .satus-modal__surface { + padding-top: 0; } -.satus-shortcut__mouse { +.satus-color-picker__palette { 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; + overflow: hidden; + width: 100%; + height: 256px; + background-color: #f00; } -.satus-shortcut__mouse>div { +.satus-color-picker__palette:before { 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%; + left: 0; + width: 100%; + height: 100%; content: ''; - background: #f96754; -} - -.satus-shortcut__mouse.false::before { - top: -6%; + background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent); } -.satus-shortcut__mouse.false::after { +.satus-color-picker__cursor { 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; + 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-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-modal--color-picker .satus-modal__surface .satus-section--color { + margin: 8px 16px 0; + align-items: center; } -.satus-shortcut__mouse.click::before { - position: absolute; - top: 0; - left: -1px; - width: 10px; - height: 10px; - content: ''; +.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: #f96754; + background: #f00; } -.satus-shortcut__mouse.context::before { - position: absolute; - top: 0; - left: 15px; - width: 10px; - height: 10px; - content: ''; - border-radius: 50%; - background: #f96754; +.satus-slider.satus-color-picker__hue { + padding: 0; + flex: 1; } -.satus-section_shortcut { - width: 100%; - margin: 8px 0 0; - justify-content: flex-end; +.satus-color-picker__hue .satus-slider__track { + height: 16px; + 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-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; +.satus-color-picker__hue .satus-slider__handle { + width: 16px; + height: 16px; + background: #fff; + box-shadow: 0 0 4px rgb(0, 0, 0, .64); +} + +.satus-color-picker__hue::before, +.satus-color-picker__hue .satus-slider__track-fill, +.satus-color-picker__hue .satus-slider__handle:focus::after { + display: none; } /*-------------------------------------------------------------- ->>> BASE +>>> SECTION: +---------------------------------------------------------------- +# Align +# Card --------------------------------------------------------------*/ -.satus-base{ - display: flex; - flex-direction: column; - width: 100%; - height: 100%; -} +.satus-section { + display: flex; + box-sizing: border-box; + flex-wrap: wrap; +} + + /*-------------------------------------------------------------- ->>> TEXT FIELD +# ALIGN --------------------------------------------------------------*/ -.satus-text-field { - position: relative; - padding: 0 16px; - background-color: var(--satus-text-field--background); - border-radius: 8px; - color: var(--satus-text-field--text); - overflow: hidden; - display: flex; +.satus-section--align-start { + align-items: center; + justify-content: flex-start; } -.satus-text-field__pre { - display: flex; - position: relative; - height: 100%; - margin: 0; - padding: 0; - overflow: hidden; - align-items: center; - flex: 1; +.satus-section--align-end { + align-items: center; + justify-content: flex-end; } -.satus-text-field__input { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - min-width: 0; - max-width: none; - height: 100%; - min-height: 0; - max-height: none; - margin: 0; - padding: 0; - opacity: 0; - border: none; - appearance: none; - z-index: 9; +.satus-section--space-between { + align-items: center; + justify-content: space-between; } -.satus-text-field__hidden-text { - position: absolute; - pointer-events: none; - opacity: 0; +.satus-section--column { + flex-direction: column; } -.satus-text-field__text { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - margin: 0; - align-items: center; -} -.satus-text-field__cursor { - position: absolute; - top: 6px; - left: 0; - display: none; - width: 2px; - height: 25px; - animation: blink 1s step-end 8; - background: #fa0; -} +/*-------------------------------------------------------------- +# CARD +--------------------------------------------------------------*/ -.satus-text-field__selection { - position: absolute; - top: 5px; - left: 0; - display: none; - width: 0; - height: 25px; - border: 1px solid rgba(255, 255, 255, .2); - border-radius: 3px; - background: rgba(255, 255, 255, .1); +.satus-section--card { + flex-direction: column; + box-sizing: border-box; + width: 100%; + max-width: 900px; + margin: 8px auto; + padding: 8px 0; + color: var(--satus-section-card-text); + border: 1px solid var(--satus-section-card-border); + border-radius: 8px; + background: var(--satus-section-card-background); + justify-content: stretch; } -.satus-text-field__input:focus + * + * + * + .satus-text-field__cursor, -.satus-text-field__selection:not([disabled]) { - display: block; +.satus-section--label { + width: 100%; + max-width: 900px; + margin: 8px auto; } -@keyframes blink { - from, - to { - opacity: 1; - } - 50% { - opacity: 0; - } +.satus-section--card>*:not(.satus-button) { + box-sizing: border-box; + min-height: 48px; + padding: 0 16px; + text-align: left; } +.satus-section--card>.satus-switch, +.satus-section--card>.satus-select, +.satus-section--card>.satus-radio { + display: flex; + justify-content: space-between; + align-items: center; +} -/*-------------------------------------------------------------- -# SYNTAX HIGHLIGHTING ---------------------------------------------------------------*/ - -.satus-text-field__text>.group { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); +.satus-section--card>.satus-button:hover, +.satus-section--card>.satus-switch:hover, +.satus-section--card>.satus-select:hover, +.satus-section--card>.satus-slider:hover, +.satus-section--card>.satus-radio:hover { + background-color: var(--satus-hover); } -.satus-text-field__text>.character-class { - color: #ffc247; - background-color: rgb(255, 170, 0, .16); +.satus-section--card>.satus-button { + width: 100%; + padding: 0 16px; } -.satus-text-field__text>.quantifier { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); +.satus-section--card>.satus-button>svg { + width: 20px; + margin: 2px 16px 0 0; + color: var(--satus-primary); } -.satus-text-field__text>.anchor { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); +.satus-section--card>.satus-span { + display: flex; + align-items: center; +} +/*-------------------------------------------------------------- +>>> LIST: +--------------------------------------------------------------*/ + +.satus-list { + list-style: none; + margin: 0; } -.satus-text-field__text>.metasequence { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); +.satus-list__item { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 48px; } -.satus-text-field__text>.text { - color: #c4c4d4; - background-color: rgb(196, 196, 212, .16); +.satus-list__item>*:last-child { + text-align: right; } /*-------------------------------------------------------------- >>> HEADER @@ -1242,6 +1380,7 @@ body[theme=black] { padding: 0 12px; color: var(--satus-header-text); background: var(--satus-header-background); + border-bottom: 1px solid var(--satus-header-border); box-shadow: 0 0 3px rgb(0, 0, 0, .1); align-items: center; justify-content: space-between; @@ -1256,255 +1395,232 @@ body[theme=black] { border-radius: 50%; } -.satus-header .satus-section--align-start > * { +.satus-header .satus-section--align-start>* { margin-right: 8px; } .satus-header .satus-span--title { font-size: 15px; + font-weight: 500; overflow: hidden; white-space: nowrap; letter-spacing: .0125em; text-overflow: ellipsis; flex: 1; -} - -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -.satus-alert { - display: flex; - box-sizing: border-box; - min-height: 48px; - margin: 8px 0 0; - padding: 8px 16px; - border-radius: 8px; - align-items: center; -} - -.satus-alert--error { - color: var(--satus-alert-error-color); - border: 1px solid var(--satus-alert-error-border); - background: var(--satus-alert-error-background); } /*-------------------------------------------------------------- ->>> LAYERS +# BUTTON --------------------------------------------------------------*/ -.satus-layers { +.satus-button { + font: inherit; position: relative; - overflow: hidden; - color: var(--satus-layers-text); - background: var(--satus-layers-background); - flex: 1; -} - -.satus-layer { - position: absolute; - top: 0; - left: 0; display: flex; - overflow-y: auto; - box-sizing: border-box; - width: 100%; - height: 100%; - padding: 0 12px; - flex-wrap: wrap; - align-content: flex-start; -} -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ - -.satus-divider { - height: 1px; - margin: 16px 0 12px; - background: var(--satus-divider); -} -/*-------------------------------------------------------------- -# INPUT ---------------------------------------------------------------*/ - -.satus-input[type=text], -.satus-input[type=password] { - font: inherit; - box-sizing: border-box; - width: 100%; + overflow: hidden; + height: 48px; margin: 0; - padding: 0 8px; - color: var(--satus-text-field--text, inherit); + padding: 8px; + text-align: left; + color: var(--satus-button-text, inherit); border: none; - outline: none; - background: none; + background: var(--satus-button-background, transparent); appearance: none; - font-size: 16px; - margin: 8px 0; - border: 1px solid var(--satus-text-field--border); - border-radius: 4px; - background-color: var(--satus-text-field--background); -} -/**/ + align-items: center; +} + +.satus-button:hover { + cursor: pointer; + background-color: var(--satus-hover); +} -.satus-aside { - color: var(--satus-aside-text); - background: var(--satus-aside-background); - box-sizing: border-box; +.satus-button[hidden] { + display: none; +} + +.satus-button>svg { + min-width: 20px; +} + +.satus-button>.satus-span--label { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } /*-------------------------------------------------------------- ->>> SELECT +>>> MODAL --------------------------------------------------------------*/ -.satus-select { - position: relative; - display: flex; - box-sizing: border-box; - align-items: center; - justify-content: space-between; +.satus-modal { + position: absolute; + z-index: 100; + top: 0; + left: 0; + display: flex; + width: 100%; + height: 100vh; + justify-content: center; + align-items: center; } -.satus-select__content { - display: flex; - align-items: center; +.satus-modal__scrim { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + animation: modalFadeIn 150ms linear forwards; + opacity: 0; + background: rgba(0, 0, 0, .16); + backdrop-filter: blur(8px); } -.satus-select__content > svg { - width: 20px; - - height: 18px; - margin: 0 14px 0 0; - opacity: .75; +.satus-modal__surface { + display: flex; + overflow-y: auto; + flex-direction: column; + width: 95%; + min-width: 240px; + max-width: 560px; + max-height: 80%; + margin: 0 16px; + padding: 12px 16px; + transform: scale(.8); + animation: modalZoomIn 150ms linear forwards; + animation-delay: 20ms; + opacity: 0; + color: var(--satus-modal-text); + border-radius: 6px; + background-color: var(--satus-modal-background); + border: 1px solid var(--satus-modal-border); + box-shadow: 0 2px 6px rgb(0, 0, 0, .15); + box-sizing: border-box; } -.satus-select__value { - margin-left: 16px; - text-align: right; - opacity: .75; +.satus-modal__surface .satus-section--actions { + display: flex; + width: 100%; + margin: 8px 0 0; + padding: 0; + justify-content: flex-end; + align-items: center; } -.satus-select select { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin: 0; - padding: 0; - padding: inherit; - cursor: pointer; - opacity: 0; - color: inherit; - border: none; - outline: none; - background: none; - appearance: none; +.satus-modal__surface .satus-section--actions .satus-button { + font-weight: 500; + height: 32px; + margin-left: 8px; + padding: 0 8px; + letter-spacing: .5px; + color: var(--satus-primary); + border-radius: 4px; } -.satus-select:hover { - cursor: pointer; - background-color: var(--satus-hover); -} -/*-------------------------------------------------------------- ->>> CONTEXT MENU ---------------------------------------------------------------*/ +.satus-modal__surface .satus-section--actions .satus-button:hover { + background: rgba(var(--satus-contrast), .075); +} -.satus-modal--contextmenu .satus-modal__scrim { - background: none; - backdrop-filter: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; +.satus-modal--closing .satus-modal__scrim { + animation: modalFadeOut 70ms linear forwards; } -.satus-modal--contextmenu .satus-modal__surface { +.satus-modal--closing .satus-modal__surface { + animation: modalZoomOut 70ms linear forwards; +} + +.satus-modal--vertical .satus-modal__surface { position: absolute; - margin: 0; - box-sizing: border-box; + top: 8px; + right: 8px; + left: auto; min-width: 200px; max-width: 200px; - padding: 4px 0; - border-radius: 4px; - border: 1px solid var(--satus-context-menu--border); - box-shadow: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; -} - -.satus-modal--contextmenu .satus-modal__surface > * { - + margin: 0; + padding: 8px 0; + transform-origin: right top; } -.satus-modal--contextmenu .satus-modal__surface>* { +.satus-modal--vertical .satus-modal__surface>.satus-button, +.satus-modal--vertical .satus-modal__surface>.satus-switch, +.satus-modal--vertical .satus-modal__surface>.satus-select { display: flex; - height: 32px; + height: 36px; padding: 0 16px; align-items: center; } -.satus-modal--contextmenu .satus-modal__surface .satus-button svg { +.satus-modal--vertical .satus-modal__surface>.satus-tabs { + padding: 0 12px; +} + +.satus-modal--vertical .satus-modal__surface>.satus-span { + font-size: 13px; + font-weight: 500; + margin: 6px 0; + padding: 0 12px; +} + +.satus-modal--vertical .satus-modal__surface>.satus-button:hover, +.satus-modal--vertical .satus-modal__surface>.satus-switch:hover, +.satus-modal--vertical .satus-modal__surface>.satus-select:hover { + background-color: var(--satus-hover); +} + +.satus-modal--vertical .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 { +.satus-modal--vertical .satus-button .satus-span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -} +} + + /*-------------------------------------------------------------- ->>> PLUVIAM +# ANIMATIONS --------------------------------------------------------------*/ -.satus-pluviam { - position: absolute; - transform: scale(0); - animation-name: pluviam; - animation-duration: 1000ms; - opacity: var(--satus-pluviam-opacity, .08); - border-radius: 50%; - background: var(--satus-pluviam-background, #000); - animation-fill-mode: forwards; +@keyframes modalFadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } } -@keyframes pluviam { - 0% { - transform: scale(0); - opacity: var(--satus-pluviam-opacity, .08); - } - 70% { - transform: scale(.8); - opacity: var(--satus-pluviam-opacity, .08); - } - 100% { - transform: scale(1); - opacity: 0; - } -} -/*-------------------------------------------------------------- ->>> SORTABLE ---------------------------------------------------------------*/ +@keyframes modalFadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} -.satus-sortable__chosen { - color: var(--satus-sortable-text) !important; - background-color: var(--satus-sortable-background) !important; +@keyframes modalZoomIn { + from { + transform: scale(.8); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } } -.satus-sortable__ghost { - position: fixed !important; - z-index: 999 !important; - top: 0 !important; - left: 0 !important; - pointer-events: none !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); - will-change: transform !important; - opacity: .8 !important; +@keyframes modalZoomOut { + from { + transform: scale(1); + opacity: 1; + } + to { + transform: scale(.8); + opacity: 0; + } } \ No newline at end of file diff --git a/satus/satus.js b/ui/satus/satus.js similarity index 85% rename from satus/satus.js rename to ui/satus/satus.js index 3b7f95d..6b4d7c1 100644 --- a/satus/satus.js +++ b/ui/satus/satus.js @@ -196,6 +196,8 @@ satus.fetch = function (url, success, error) { } else { error(); } + }).catch(function () { + error(success); }); }; @@ -254,7 +256,7 @@ satus.storage.get = function (name) { # SET --------------------------------------------------------------*/ -satus.storage.set = function (name, value) { +satus.storage.set = function (name, value, callback) { var items = {}, target = satus.storage.data; @@ -290,10 +292,10 @@ satus.storage.set = function (name, value) { } if (satus.storage.attributes[name]) { - document.body.setAttribute(name, value); + document.body.setAttribute('data-' + name, value); } - chrome.storage.local.set(items); + chrome.storage.local.set(items, callback); }; @@ -312,11 +314,17 @@ satus.storage.remove = function (name) { # IMPORT --------------------------------------------------------------*/ -satus.storage.import = function (callback) { - chrome.storage.local.get(function (items) { +satus.storage.import = function (keys, callback) { + if (typeof keys === 'function') { + callback = keys; + + keys = undefined; + } + + chrome.storage.local.get(keys, function (items) { for (var key in items) { if (satus.storage.attributes[key]) { - document.body.setAttribute(key, items[key]); + document.body.setAttribute('data-' + key, items[key]); } satus.storage.data[key] = items[key]; @@ -357,8 +365,8 @@ satus.locale.get = function (string) { # IMPORT --------------------------------------------------------------*/ -satus.locale.import = function (string, path, callback) { - var language = string || window.navigator.language; +satus.locale.import = function (code, path, callback) { + var language = code || window.navigator.language; if (language.indexOf('en') === 0) { language = 'en'; @@ -368,20 +376,16 @@ satus.locale.import = function (string, path, callback) { path = '_locales/'; } - satus.ajax(path + language + '/messages.json', function (response) { - try { - response = JSON.parse(response); - - for (var key in response) { - satus.locale.strings[key] = response[key].message; - } - } catch (error) { - console.error(error); + satus.fetch(chrome.runtime.getURL(path + language + '/messages.json'), function (response) { + for (var key in response) { + satus.locale.strings[key] = response[key].message; } callback(); }, function (success) { - satus.ajax(path + 'en/messages.json', success); + satus.fetch(chrome.runtime.getURL(path + 'en/messages.json'), success, function () { + success(); + }); }); }; @@ -787,897 +791,1047 @@ satus.render = function (skeleton, container, skip, property) { return component; }; /*-------------------------------------------------------------- ->>> COLOR PICKER +>>> COLOR: +---------------------------------------------------------------- +# RGB to HSL +# HUE to RGB +# HSL to RGB --------------------------------------------------------------*/ -satus.components.colorPicker = function (skeleton) { - var component = document.createElement('button'), - component_label = document.createElement('span'), - component_value = document.createElement('span'); - - component.inner = component_label; - component.valueElement = component_value; - - component.className = 'satus-button'; - component_value.className = 'satus-color-picker__value'; - - component.appendChild(component_label); - component.appendChild(component_value); +satus.color = {}; - 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; +/*-------------------------------------------------------------- +# RGB TO HSL +--------------------------------------------------------------*/ - var v = l + s; +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; - s = 2 * s / (l + s); + if (min === max) { + h = 0; + s = 0; + } else { + var delta = max - min; - satus.render({ - component: 'modal', - variant: 'color-picker', - value: hsl, - parent: this, + s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); - 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]; + 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; + } - function mousemove(event) { - var hsl = palette.skeleton.parent.value, - x = event.clientX - rect.left, - y = event.clientY - rect.top, - s; + h /= 6; + } - x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); - y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); + h *= 360; + s *= 100; + l *= 100; - var v = 100 - y, - l = (2 - x / 100) * v / 2; + if (array.length === 3) { + return [h, s, l]; + } else { + return [h, s, l, array[3]]; + } +}; - hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); - hsl[2] = l; - cursor.style.left = x + '%'; - cursor.style.top = y + '%'; +/*-------------------------------------------------------------- +# HUE TO RGB +--------------------------------------------------------------*/ - palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; +satus.color.hueToRgb = function (array) { + var t1 = array[0], + t2 = array[1], + hue = array[2]; - event.preventDefault(); - } + if (hue < 0) { + hue += 6; + } - function mouseup() { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } + if (hue >= 6) { + hue -= 6; + } - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - } - }, + 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; + } +}; - 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.parent.parent, - hsl = modal.value; +/*-------------------------------------------------------------- +# HSL TO RGB +--------------------------------------------------------------*/ - hsl[0] = this.values[0]; +satus.color.hslToRgb = function (array) { + var h = array[0] / 360, + s = array[1] / 100, + l = array[2] / 100, + r, g, b; - 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', + if (s == 0) { + r = g = b = l; + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; + 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); + } - component.rgb = component.skeleton.value; + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +}; +/*-------------------------------------------------------------- +>>> PLUVIAM +--------------------------------------------------------------*/ - component.storageValue = component.rgb; - component.storageChange(); +satus.events.add('render', function (component, skeleton) { + if (skeleton.pluviam === true) { + function createPluviam(event) { + var pluviam = document.createElement('span'), + rect = this.getBoundingClientRect(), + x = event.clientX - rect.left, + y = event.clientY - rect.top, + diameter = Math.sqrt(Math.pow(rect.width * 2, 2) + Math.pow(rect.height * 2, 2)); - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + pluviam.className = 'satus-pluviam'; - modal.rendered.close(); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - this.skeleton.parent.parent.rendered.close(); - } - } - }, - ok: { - component: 'button', - text: 'OK', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; + pluviam.style.left = x - diameter / 2 + 'px'; + pluviam.style.top = y - diameter / 2 + 'px'; + pluviam.style.width = diameter + 'px'; + pluviam.style.height = diameter + 'px'; - component.rgb = satus.color.hslToRgb(modal.value); + this.appendChild(pluviam); - component.storageValue = component.rgb; - component.storageChange(); + setTimeout(function () { + pluviam.remove(); + }, 1000); + } - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + component.addEventListener('mousedown', createPluviam); + component.addEventListener('mouseover', createPluviam); + } +}); +/*-------------------------------------------------------------- +>>> EXTENSION STORAGE +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +>>> INDEXEDDB: +---------------------------------------------------------------- +# Global variable +# Methods + # Open + # Get + # Get by key + # Set + # Clear + # Delete + # Search +--------------------------------------------------------------*/ - modal.rendered.close(); - } - } - } - } - }); - }); +/*-------------------------------------------------------------- +# GLOBAL VARIABLE +--------------------------------------------------------------*/ - component.addEventListener('render', function () { - component.rgb = this.storageValue || [0, 100, 50]; +satus.indexeddb = { + request: null +}; - component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - }); - return component; -}; /*-------------------------------------------------------------- ->>> TABS +# METHODS --------------------------------------------------------------*/ -satus.components.tabs = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - selection = document.createElement('div'); +/*-------------------------------------------------------------- +# OPEN +---------------------------------------------------------------- +satus.indexeddb.open('rootCellar', { + fruits: { + indexes: [ + 'id', + 'name', + 'amount', + ... + ], + keyOptions: { + keyPath: 'id', + autoIncrement: true + } + }, + ... +}, function () { ... }); +--------------------------------------------------------------*/ - content.className = 'satus-tabs__content'; - selection.className = 'satus-tabs__selection'; - selection.style.width = 100 / skeleton.items.length + '%'; +satus.indexeddb.open = function (name, objects, callback) { + var request = indexedDB.open(name); - content.appendChild(selection); + request.onerror = function (event) { + callback(); + }; - component.selection = selection; + request.onblocked = function(event) { + satus.indexeddb.open(callback); + }; - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var item = skeleton.items[i], - button = document.createElement('button'); + request.onsuccess = function (event) { + satus.indexeddb.request = this.result; - button.className = 'satus-tabs__button'; - button.value = item; - button.style.width = 100 / l + '%'; + callback(); + }; - satus.text(button, item); + request.onupgradeneeded = function (event) { + satus.indexeddb.request = this.result; - button.addEventListener('click', function () { - var component = this.parentNode.parentNode; + for (var key in objects) { + var object = objects[key]; - component.selection.style.left = 100 / (this.parentNode.children.length - 1) * (satus.indexOf(this) - 1) + '%'; + if (!this.result.objectStoreNames.contains(key)) { + var object_store = this.result.createObjectStore(key, object.keyOptions); - component.storageValue = this.value; - component.storageChange(); - }); + for (var i = 0, l = object.indexes.length; i < l; i++) { + var name = object.indexes[i]; - if (skeleton.value === item) { - selection.style.left = i * 50 + '%'; + object_store.createIndex(name, name); + } + } } - content.appendChild(button); - } - - component.appendChild(content); - - component.addEventListener('render', function () { - var index = satus.indexOf(this.storageValue, this.skeleton.items); + this.result.onversionchange = function (event) { + satus.indexeddb.close(); - if (index === -1) { - index = 0; - } + satus.indexeddb.open(callback); + }; + }; +}; - this.selection.style.left = 100 / this.skeleton.items.length * index + '%'; - }); - return component; -}; /*-------------------------------------------------------------- ->>> MENUBAR +# GET +---------------------------------------------------------------- +satus.indexeddb.get({ + fruits: { + direction: 'next', + index: 'name', + offset: 0, + limit: 100 + }, + ... +}, function (result) { ... }); --------------------------------------------------------------*/ -satus.components.menubar = function (skeleton) { - var component = document.createElement('ul'); +satus.indexeddb.get = function (items, callback) { + var queue = [], + results = {}; - if (skeleton.items) { - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var item = skeleton.items[i], - li = document.createElement('li'); + for (var key in items) { + var item = items[key]; + + queue.push({ + name: key, + direction: item.direction, + index: item.index, + offset: item.offset + }); + } - if (Array.isArray(item) === true) { - var ul = document.createElement('ul'); + function handle() { + var item = queue[0], + transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), + object_store = transaction.objectStore(item.name), + object_result = [], + offset = item.offset || 0, + limit = item.limit || 100; - satus.render(item[0], li); + if (item.index) { + object_store = object_store.index(item.index); + } - for (var j = 1, k = item.length; j < k; j++) { - var li2 = document.createElement('li'); + results[item.name] = object_result; - satus.render(item[j], li2); + object_store.openCursor(null, item.direction).onsuccess = function(event) { + var cursor = event.target.result; - ul.appendChild(li2); - } + if (cursor) { + if (item.offset > 0) { + cursor.advance(item.offset); - li.appendChild(ul); + item.offset = 0; + } else if (object_result.length < limit) { + object_result.push(cursor.value); + + cursor.continue(); + } } else { - satus.render(item, li); - } + object_store.count().onsuccess = function(event) { + object_result.fullLength = event.target.result; - component.appendChild(li); - } + queue.shift(); + + if (queue.length === 0) { + callback(results); + } else { + handle(); + } + }; + } + }; } - return component; -}; + handle(); +}; + + /*-------------------------------------------------------------- ->>> RADIO +# GET BY KEY +---------------------------------------------------------------- +satus.indexeddb.getByKey({ + fruits: [1], + ... +}, function (result) { ... }); --------------------------------------------------------------*/ -satus.components.radio = function (skeleton) { - var component = document.createElement('label'), - content = document.createElement('span'), - radio = document.createElement('input'); +satus.indexeddb.getByKey = function (items, callback) { + var queue = [], + results = {}; - component.inner = content; + for (var name in items) { + queue.push({ + name: name, + keys: items[name] + }); + } - radio.type = 'radio'; + function handle() { + var item = queue[0], + transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), + object_store = transaction.objectStore(item.name), + object_result = []; - if (skeleton.group) { - component.storage = skeleton.group; - radio.name = skeleton.group; - } + results[item.name] = object_result; - if (skeleton.value) { - radio.value = skeleton.value; - } + for (var i = 0, l = item.keys.length; i < l; i++) { + var key = item.keys[i]; - component.addEventListener('render', function () { - this.storageValue = satus.storage.get(this.storage); + object_store.get(key).onsuccess = function(event) { + var result = event.target.result; - if (satus.isset(this.storageValue)) { - radio.checked = this.storageValue === skeleton.value; - } else if (skeleton.checked) { - radio.checked = true; + if (result) { + object_result.push(result); + } + + object_store.count().onsuccess = function(event) { + object_result.fullLength = event.target.result; + + queue.shift(); + + if (queue.length === 0) { + callback(results); + } else { + handle(); + } + }; + }; } - }); + } - radio.addEventListener('change', function () { - component.storageValue = this.value; - component.storageChange(); - }); + handle(); +}; - component.appendChild(content); - component.appendChild(radio); - return component; -}; /*-------------------------------------------------------------- ->>> LIST +# SET +---------------------------------------------------------------- +satus.indexeddb.set({ + fruits: [ + { name: 'apple', amount: 500 }, + ... + ], + ... +}, function () { ... }); --------------------------------------------------------------*/ -satus.components.list = function (skeleton) { - var ul = document.createElement('ul'); +satus.indexeddb.set = function (items, callback) { + var threads = 0; - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var li = document.createElement('li'), - item = skeleton.items[i]; + for (var name in items) { + var item = items[name], + transaction = this.request.transaction(name, 'readwrite'), + object_store = transaction.objectStore(name); - li.className = 'satus-list__item'; + for (var i = 0, l = item.length; i < l; i++) { + var request = object_store.put(item[i]); - for (var j = 0, k = item.length; j < k; j++) { - var child = item[j]; + threads++; - if (typeof child === 'string') { - var span = document.createElement('span'); + request.onsuccess = function () { + threads--; - span.textContent = satus.locale.get(child); + if (callback && threads === 0) { + callback(); + } + }; - li.appendChild(span); - } else { - satus.render(child, li); - } - } + request.onerror = function () { + threads--; - ul.appendChild(li); + if (callback && threads === 0) { + callback(); + } + }; + } } +}; + - return ul; -}; /*-------------------------------------------------------------- ->>> MODAL +# CLEAR +---------------------------------------------------------------- +satus.indexeddb.clear(['fruits'], function (result) { ... }); --------------------------------------------------------------*/ -satus.components.modal = function (skeleton) { - var component = document.createElement('div'), - scrim = document.createElement('div'), - surface = document.createElement('div'); - - component.inner = surface; +satus.indexeddb.clear = function (items) { + if (typeof items === 'string') { + items = [items]; + } - scrim.className = 'satus-modal__scrim'; - surface.className = 'satus-modal__surface'; + for (var i = 0, l = items.length; i < l; i++) { + var name = items[i], + transaction = satus.indexeddb.request.transaction(name, 'readwrite'), + object_store = transaction.objectStore(name); - component.close = function () { - var component = this, - component_surface = this.children[1]; + object_store.clear(); + } +}; - this.classList.add('satus-modal--closing'); - setTimeout(function () { - component.remove(); +/*-------------------------------------------------------------- +# DELETE +---------------------------------------------------------------- +satus.indexeddb.delete({ + fruits: { + name: [ + 'apple' + ] + } +}); +--------------------------------------------------------------*/ - component.dispatchEvent(new CustomEvent('close')); - }, satus.getAnimationDuration(component_surface)); - }; +satus.indexeddb.delete = function (stores, callback) { + var queue = []; - scrim.addEventListener('click', function () { - this.parentNode.close(); - }); + for (var name in stores) { + var store = stores[name]; - component.appendChild(scrim); - component.appendChild(surface); + for (var index in store) { + queue.push({ + object_store_name: name, + index_name: index, + keys: store[index] + }); + } + } - return component; -}; -/*-------------------------------------------------------------- ->>> CHECKBOX ---------------------------------------------------------------*/ + function handle() { + var item = queue[0], + transaction = satus.indexeddb.request.transaction(item.object_store_name, 'readwrite'), + object_store = transaction.objectStore(item.object_store_name), + object_result = []; -satus.components.checkbox = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'); + if (item.index_name) { + object_store = object_store.index(item.index_name); + } - component.inner = content; + object_store.openCursor(null, item.direction).onsuccess = function(event) { + var cursor = event.target.result; - content.className = 'satus-checkbox__content'; + if (cursor) { + cursor.delete(); + } - component.appendChild(content); + queue.shift(); - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; - } + if (queue.length === 0) { + callback(); + } else { + handle(); + } + }; + } - this.storageChange(); - }); + handle(); +}; - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); - return component; -}; /*-------------------------------------------------------------- ->>> SWITCH +# SEARCH +---------------------------------------------------------------- +satus.indexeddb.search({ + fruits: { + query: 'apple', // or function () { ... } + direction: 'next', + index: 'name', + offset: 0, + limit: 0 + }, + ... +}, function () { ... }); --------------------------------------------------------------*/ -satus.components.switch = function (skeleton) { - var component = document.createElement('button'), - component_content = document.createElement('span'), - component_thumb = document.createElement('i'); +satus.indexeddb.search = function (items, callback) { + var queue = [], + results = {}; - component.inner = component_content; + for (var key in items) { + var item = items[key]; - component_content.className = 'satus-switch__content'; + queue.push({ + name: key, + direction: item.direction, + index: item.index, + offset: item.offset + }); + } - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; + function handle() { + var item = queue[0], + transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), + object_store = transaction.objectStore(item.name), + object_result = [], + offset = item.offset || 0, + limit = item.limit || 100; + + if (item.index) { + object_store = object_store.index(item.index); } - this.storageChange(); - }); + results[item.name] = object_result; - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); + object_store.openCursor(null, item.direction).onsuccess = function(event) { + var cursor = event.target.result; - component.appendChild(component_content); - component.appendChild(component_thumb); + if (cursor) { + if (item.offset > 0) { + cursor.advance(item.offset); - return component; -}; -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ + item.offset = 0; + } else if (limit && object_result.length < limit) { + object_result.push(cursor.value); -satus.components.slider = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - container = document.createElement('div'), - track = document.createElement('div'), - track_fill = document.createElement('div'); + cursor.continue(); + } + } else { + object_store.count().onsuccess = function(event) { + object_result.fullLength = event.target.result; - container.className = 'satus-slider__container'; - track.className = 'satus-slider__track'; - track_fill.className = 'satus-slider__track-fill'; + queue.shift(); - component.min = skeleton.min || 0; - component.max = skeleton.max || 1; - component.step = (skeleton.step || 1); - component.percent = 100 / ((component.max - component.min) / component.step); - component.precision = String(component.step).replace(/[0-9]./, '').length; + if (queue.length === 0) { + callback(results); + } else { + handle(); + } + }; + } + }; + } - component.container = container; - component.track = track_fill; - component.handles = []; - component.inner = content; + handle(); +}; +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ - component.toPercent = function (number) { - return number / this.step * this.percent + '%'; - }; +satus.events.add('render', function (component, skeleton) { + if (skeleton.sortable === true) { + component.addEventListener('mousedown', function (event) { + if (event.button !== 0) { + return false; + } - component.createHandle = function (index) { - var handle = document.createElement('div'); + 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; - handle.className = 'satus-slider__handle'; - handle.handleIndex = index; - handle.tabIndex = 0; + ghost.classList.add('satus-sortable__ghost'); - this.handles.push(handle); + function mousemove(event) { + if (appended === false && (Math.abs(event.clientX - x) > 4 || Math.abs(event.clientY - y) > 4)) { + appended = true; - this.container.appendChild(handle); - }; + component.classList.add('satus-sortable__chosen'); - component.update = function () { - if (this.values.length > 1) { - var min = Math.min.apply(null, this.values) - this.min, - max = Math.max.apply(null, this.values) - this.min; + component.parentNode.appendChild(ghost); + } - this.track.style.left = this.toPercent(min); - this.track.style.width = this.toPercent(max - min); + ghost.style.transform = 'translate(' + (event.clientX - offset_x) + 'px, ' + (event.clientY - offset_y) + 'px)'; + } - for (var i = 0, l = this.handles.length; i < l; i++) { - var handle = this.handles[i], - value = this.values[i]; + function mouseup(event) { + component.classList.remove('satus-sortable__chosen'); + ghost.remove(); - handle.style.left = this.toPercent(value - this.min); - handle.dataset.value = value; - } - } else { - var value = this.values[0]; + window.removeEventListener('mousemove', mousemove, true); + window.removeEventListener('mouseup', mouseup, true); - this.track.style.width = this.toPercent(value - this.min); - this.handles[0].style.left = this.toPercent(value - this.min); - this.handles[0].dataset.value = value; - } - }; + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; - component.appendChild(content); - track.appendChild(track_fill); - container.appendChild(track); - component.appendChild(container); + if (child !== component) { + child.removeEventListener('mouseover', siblingMouseOver); + } + } - component.addEventListener('keydown', function (event) { - var code = event.keyCode; + component.dispatchEvent(new CustomEvent('sort')); - console.log(code); - }); + event.stopPropagation(); - component.addEventListener('render', function () { - var value = this.storageValue; + return false; + } - if (satus.isArray(value)) { - this.values = value; - } else if (satus.isNumber(value)) { - this.values = [value]; - } else { - this.values = this.skeleton.values || [satus.isset(this.skeleton.value) ? this.skeleton.value : 1]; - } + window.addEventListener('mousemove', mousemove, { + passive: true, + capture: true + }); - for (var i = 0, l = this.values.length; i < l; i++) { - this.createHandle(i); - } + window.addEventListener('mouseup', mouseup, { + passive: true, + capture: true + }); - this.update(); - }); + function siblingMouseOver(event) { + var target = event.target, + parent = target.parentNode, + y = event.layerY / (target.offsetHeight / 100); - container.addEventListener('mousedown', function (event) { - if (event.button === 0) { - var component = this.parentNode, - rect = this.getBoundingClientRect(), - cursor_x = event.clientX - rect.left, - percent = cursor_x / rect.width * 100, - steps = percent / component.percent * component.step + component.min, - closest_value = component.values.indexOf(component.values.reduce(function(previous, current, index) { - return Math.abs(current - steps) < Math.abs(previous - steps) ? current : previous; - })), - handle_index = component.handles[closest_value].handleIndex; + if (y < 50 && target.previousSibling !== component || y >= 50 && target.nextSibling === component) { + parent.insertBefore(component, target); + } else { + parent.insertBefore(component, target.nextSibling); + } + } - setTimeout(function () { - component.handles[closest_value].focus(); - }); + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; - function update(event) { - var cursor_x = Math.min(Math.max(event.clientX - rect.left, 0), rect.width), - percent = cursor_x / rect.width * 100, - value = percent / component.percent * component.step + component.min; + if (child !== component) { + child.addEventListener('mouseover', siblingMouseOver); + } + } - value = (Math.round(value / component.step) * component.step); + event.stopPropagation(); + event.preventDefault(); - value = Number(value.toFixed(component.precision)); + return false; + }); + } +}); +/*-------------------------------------------------------------- +>>> USER +--------------------------------------------------------------*/ - if (component.values[handle_index] !== value) { - component.values[handle_index] = value; +satus.user = function () { + /*-------------------------------------------------------------- + 1.0 VARIABLES + --------------------------------------------------------------*/ - component.storageValue = component.values.length === 1 ? component.values[0] : component.values; - component.value = component.storageValue; + var user_agent = navigator.userAgent, + random_cookie = 'ta{t`nX6cMXK,Wsc', + video = document.createElement('video'), + video_formats = { + 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"' + }, + audio = document.createElement('audio'), + audio_formats = { + mp3: 'audio/mpeg', + mp4: 'audio/mp4', + aif: 'audio/x-aiff' + }, + cvs = document.createElement('canvas'), + ctx = cvs.getContext('webgl'), + data = { + browser: { + audio: null, + cookies: null, + flash: null, + java: null, + languages: null, + name: null, + platform: null, + version: null, + video: null, + webgl: null + }, + os: { + name: null, + type: null + }, + device: { + connection: { + type: null, + speed: null + }, + cores: null, + gpu: null, + max_touch_points: null, + ram: null, + screen: null, + touch: null + } + }; - component.storageChange(); - } - component.update(); - } + /*-------------------------------------------------------------- + 2.0 SOFTWARE + --------------------------------------------------------------*/ - function mousemove(event) { - update(event); - } + /*-------------------------------------------------------------- + 2.1.0 OS + --------------------------------------------------------------*/ - function mouseup(event) { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - }; + /*-------------------------------------------------------------- + 2.1.1 NAME + --------------------------------------------------------------*/ - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); + if (navigator.appVersion.indexOf('Win') !== -1) { + if (navigator.appVersion.match(/(Windows 10.0|Windows NT 10.0)/)) { + data.os.name = 'Windows 10'; + } else if (navigator.appVersion.match(/(Windows 8.1|Windows NT 6.3)/)) { + data.os.name = 'Windows 8.1'; + } else if (navigator.appVersion.match(/(Windows 8|Windows NT 6.2)/)) { + data.os.name = 'Windows 8'; + } else if (navigator.appVersion.match(/(Windows 7|Windows NT 6.1)/)) { + data.os.name = 'Windows 7'; + } else if (navigator.appVersion.match(/(Windows NT 6.0)/)) { + data.os.name = 'Windows Vista'; + } else if (navigator.appVersion.match(/(Windows NT 5.1|Windows XP)/)) { + data.os.name = 'Windows XP'; + } else { + data.os.name = 'Windows'; + } + } else if (navigator.appVersion.indexOf('(iPhone|iPad|iPod)') !== -1) { + data.os.name = 'iOS'; + } else if (navigator.appVersion.indexOf('Mac') !== -1) { + data.os.name = 'macOS'; + } else if (navigator.appVersion.indexOf('Android') !== -1) { + data.os.name = 'Android'; + } else if (navigator.appVersion.indexOf('OpenBSD') !== -1) { + data.os.name = 'OpenBSD'; + } else if (navigator.appVersion.indexOf('SunOS') !== -1) { + data.os.name = 'SunOS'; + } else if (navigator.appVersion.indexOf('Linux') !== -1) { + data.os.name = 'Linux'; + } else if (navigator.appVersion.indexOf('X11') !== -1) { + data.os.name = 'UNIX'; + } - update(event); + /*-------------------------------------------------------------- + 2.1.2 TYPE + --------------------------------------------------------------*/ - return true; - } - }); + if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { + data.os.type = '64-bit'; + } else { + data.os.type = '32-bit'; + } - return component; -}; -/*-------------------------------------------------------------- ->>> SHORTCUT ---------------------------------------------------------------*/ -satus.components.shortcut = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'), - value = document.createElement('div'); + /*-------------------------------------------------------------- + 2.2.0 BROWSER + --------------------------------------------------------------*/ - component.inner = content; + /*-------------------------------------------------------------- + 2.2.1 NAME + --------------------------------------------------------------*/ - component.className = 'satus-button'; - value.className = 'satus-shortcut__value'; + if (user_agent.indexOf('Opera') !== -1) { + data.browser.name = 'Opera'; + } else if (user_agent.indexOf('Vivaldi') !== -1) { + data.browser.name = 'Vivaldi'; + } else if (user_agent.indexOf('Edge') !== -1) { + data.browser.name = 'Edge'; + } else if (user_agent.indexOf('Chrome') !== -1) { + data.browser.name = 'Chrome'; + } else if (user_agent.indexOf('Safari') !== -1) { + data.browser.name = 'Safari'; + } else if (user_agent.indexOf('Firefox') !== -1) { + data.browser.name = 'Firefox'; + } else if (user_agent.indexOf('MSIE') !== -1) { + data.browser.name = 'IE'; + } - component.render = function (parent) { - var self = this, - parent = parent || self.primary, - children = parent.children; - satus.empty(parent); + /*-------------------------------------------------------------- + 2.2.2 VERSION + --------------------------------------------------------------*/ - function createElement(name) { - var element = document.createElement('div'); + var browser_version = user_agent.match(new RegExp(data.browser.name + '/([0-9.]+)')); - element.className = 'satus-shortcut__' + name; + if (browser_version[1]) { + data.browser.version = browser_version[1]; + } - parent.appendChild(element); - return element; - } + /*-------------------------------------------------------------- + 2.2.3 PLATFORM + --------------------------------------------------------------*/ - if (this.data.alt) { - createElement('key').textContent = 'Alt'; - } + data.browser.platform = navigator.platform || null; - if (this.data.ctrl) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - createElement('key').textContent = 'Ctrl'; - } + /*-------------------------------------------------------------- + 2.2.4 LANGUAGES + --------------------------------------------------------------*/ - if (this.data.shift) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } + data.browser.languages = navigator.languages || null; - createElement('key').textContent = 'Shift'; + + /*-------------------------------------------------------------- + 2.2.5 COOKIES + --------------------------------------------------------------*/ + + if (document.cookie) { + document.cookie = random_cookie; + + if (document.cookie.indexOf(random_cookie) !== -1) { + data.browser.cookies = true; } + } - 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('key') !== -1) { - createElement('plus'); - } + /*-------------------------------------------------------------- + 2.2.6 FLASH + --------------------------------------------------------------*/ - if (index !== -1) { - createElement('key').textContent = ['↑', '→', '↓', '←'][index]; - } else if (key === ' ') { - createElement('key').textContent = '␣'; - } else { - createElement('key').textContent = key.toUpperCase(); - } + try { + if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { + data.browser.flash = true; + } + } catch (e) { + if (navigator.mimeTypes['application/x-shockwave-flash']) { + data.browser.flash = true; } + } - if (this.data.wheel) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - var mouse = createElement('mouse'), - div = document.createElement('div'); + /*-------------------------------------------------------------- + 2.2.7 JAVA + --------------------------------------------------------------*/ - mouse.appendChild(div); + if (typeof navigator.javaEnabled === 'function' && navigator.javaEnabled()) { + data.browser.java = true; + } - mouse.className += ' ' + (this.data.wheel > 0); - } - if (this.data.click) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } + /*-------------------------------------------------------------- + 2.2.8 VIDEO FORMATS + --------------------------------------------------------------*/ - var mouse = createElement('mouse'), - div = document.createElement('div'); + if (typeof video.canPlayType === 'function') { + data.browser.video = {}; - mouse.appendChild(div); + for (var i in video_formats) { + var can_play_type = video.canPlayType(video_formats[i]); - mouse.className += ' click'; + if (can_play_type === '') { + data.browser.video[i] = false; + } else { + data.browser.video[i] = can_play_type; + } } + } - if (this.data.context) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - var mouse = createElement('mouse'), - div = document.createElement('div'); + /*-------------------------------------------------------------- + 2.2.9 AUDIO FORMATS + --------------------------------------------------------------*/ - mouse.appendChild(div); + if (typeof audio.canPlayType === 'function') { + data.browser.audio = {}; - mouse.className += ' context'; + for (var i in audio_formats) { + var can_play_type = audio.canPlayType(audio_formats[i]); + + if (can_play_type == '') { + data.browser.audio[i] = false; + } else { + data.browser.audio[i] = can_play_type; + } } - }; + } - component.valueElement = value; - component.appendChild(content); - component.appendChild(value); + /*-------------------------------------------------------------- + 2.2.10 WEBGL + --------------------------------------------------------------*/ - component.keydown = function (event) { - event.preventDefault(); - event.stopPropagation(); + if (ctx && ctx instanceof WebGLRenderingContext) { + data.browser.webgl = true; + } - 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 - }; - } + /*-------------------------------------------------------------- + 3.0 HARDWARE + --------------------------------------------------------------*/ - component.data.wheel = 0; + /*-------------------------------------------------------------- + 3.1 SCREEN + --------------------------------------------------------------*/ - component.render(); + if (screen) { + data.device.screen = screen.width + 'x' + screen.height; + } - return false; - }; - component.mousewheel = function (event) { - event.stopPropagation(); + /*-------------------------------------------------------------- + 3.2 RAM + --------------------------------------------------------------*/ - 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(); + if ('deviceMemory' in navigator) { + data.device.ram = navigator.deviceMemory + ' GB'; + } - return false; - }; - component.addEventListener('render', function () { - this.data = this.storageValue || { - alt: false, - ctrl: false, - shift: false, - keys: {}, - wheel: 0 - }; + /*-------------------------------------------------------------- + 3.3 GPU + --------------------------------------------------------------*/ - this.render(this.valueElement); - }); + if ( + ctx && + ctx instanceof WebGLRenderingContext && + 'getParameter' in ctx && + 'getExtension' in ctx + ) { + var info = ctx.getExtension('WEBGL_debug_renderer_info'); - component.addEventListener('click', function () { - satus.render({ - component: 'modal', - on: { - close: function () { - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - }, + if (info) { + data.device.gpu = ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); + } + } - primary: { - component: 'div', - class: 'satus-shortcut__primary', - on: { - render: function () { - component.primary = this; - if (component.skeleton.mouseButtons === true) { - this.addEventListener('click', function () { - component.data.context = false; - component.data.click = true; + /*-------------------------------------------------------------- + 3.4 CORES + --------------------------------------------------------------*/ - component.render(); - }); + if (navigator.hardwareConcurrency) { + data.device.cores = navigator.hardwareConcurrency; + } - this.addEventListener('contextmenu', function (event) { - event.preventDefault(); - event.stopPropagation(); - component.data.context = true; - component.data.click = false; + /*-------------------------------------------------------------- + 3.5 TOUCH + --------------------------------------------------------------*/ - component.render(); + if ( + window.hasOwnProperty('ontouchstart') || + window.DocumentTouch && document instanceof window.DocumentTouch || + navigator.maxTouchPoints > 0 || + window.navigator.msMaxTouchPoints > 0 + ) { + data.device.touch = true; + data.device.max_touch_points = navigator.maxTouchPoints; + } - return false; - }); - } - component.render(); - } - } - }, - actions: { - component: 'section', - variant: 'actions', + /*-------------------------------------------------------------- + 3.6 CONNECTION + --------------------------------------------------------------*/ - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - component.data = component.skeleton.value; + if (typeof navigator.connection === 'object') { + data.device.connection.type = navigator.connection.effectiveType || null; - component.render(component.valueElement); + if (navigator.connection.downlink) { + data.device.connection.speed = navigator.connection.downlink + ' Mbps'; + } + } - satus.storage.set(skeleton.storage, false); - this.parentNode.parentNode.parentNode.close(); + /*-------------------------------------------------------------- + 4.0 CLEARING + --------------------------------------------------------------*/ - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - component.data = satus.storage.get(component.storage) || component.skeleton.value; + video.remove(); + audio.remove(); + cvs.remove(); - component.render(component.valueElement); - this.parentNode.parentNode.parentNode.close(); + return data; +}; +/*-------------------------------------------------------------- +>>> UUID +--------------------------------------------------------------*/ - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - }, - save: { - component: 'button', - text: 'save', - on: { - click: function () { - component.storageValue = component.data; +satus.uuid = function () { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (match) { + return (match ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> match / 4).toString(16) + }); +}; +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ - component.storageChange(); +satus.events.add('render', function (component, skeleton) { + if (skeleton.contextMenu) { + component.addEventListener('contextmenu', function (event) { + var x = event.clientX, + y = event.clientY, + modal = satus.render({ + component: 'modal', + variant: 'contextmenu', + parent: this.skeleton + }); - component.render(component.valueElement); + if (window.innerWidth - x < 200) { + x = window.innerWidth - 200; + } - this.parentNode.parentNode.parentNode.close(); + modal.inner.style.left = x + 'px'; + modal.inner.style.top = y + 'px'; - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - } - } - }); + satus.render(this.skeleton.contextMenu, modal.inner); - window.addEventListener('keydown', this.keydown); - window.addEventListener('mousewheel', this.mousewheel); - }); + event.preventDefault(); + event.stopPropagation(); - return component; -}; + return false; + }); + } +}); /*-------------------------------------------------------------- >>> BASE --------------------------------------------------------------*/ @@ -1690,985 +1844,1318 @@ satus.components.base = function (skeleton) { return component; }; /*-------------------------------------------------------------- ->>> TEXT FIELD +>>> RADIO --------------------------------------------------------------*/ -satus.components.textField = function (skeleton) { - var component = document.createElement('div'), - pre = document.createElement('pre'), - input = document.createElement('textarea'), - hidden_text = document.createElement('span'), - text = document.createElement('span'), - selection = document.createElement('div'), - cursor = document.createElement('div'); +satus.components.radio = function (skeleton) { + var component = document.createElement('label'), + content = document.createElement('span'), + radio = document.createElement('input'); - input.className = 'satus-text-field__input'; - pre.className = 'satus-text-field__pre'; - hidden_text.className = 'satus-text-field__hidden-text'; - text.className = 'satus-text-field__text'; - selection.className = 'satus-text-field__selection'; - cursor.className = 'satus-text-field__cursor'; + component.inner = content; - component.inputElement = input; - component.textElement = text; - component.languages = { - regex: function (component) { - 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 = component.inputElement.value.match(regex_token); + radio.type = 'radio'; - function create(type, string) { - var span = document.createElement('span'); + if (skeleton.group) { + component.storage = skeleton.group; + radio.name = skeleton.group; + } - span.className = type; - span.textContent = string; + if (skeleton.value) { + radio.value = skeleton.value; + } - component.textElement.appendChild(span); - } + component.addEventListener('render', function () { + this.storageValue = satus.storage.get(this.storage); - for (var i = 0, l = matches.length; i < l; i++) { - var match = matches[i]; + if (satus.isset(this.storageValue)) { + radio.checked = this.storageValue === skeleton.value; + } else if (skeleton.checked) { + radio.checked = true; + } + }); - 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); - } - } - } - }; - component._syntax = skeleton.syntax; - - Object.defineProperty(component, 'value', { - get: function () { - return this.inputElement.value; - }, - set: function (value) { - var input = this.inputElement; - - input.value = value; - - input.updateValue(); - input.updateCursor(); - } - }); - - Object.defineProperty(component, 'syntax', { - get: function () { - return this._syntax; - }, - set: function (value) { - var input = this.inputElement; - - this._syntax = value; - - input.updateValue(); - input.updateCursor(); - } + radio.addEventListener('change', function () { + component.storageValue = this.value; + component.storageChange(); }); - input.rows = skeleton.rows || 1; - input.autocapitalize = 'none'; - input.autocomplete = 'off'; - input.autocorrect = 'off'; - input.spellcheck = false; - input.autofocus = true; - input.textElement = text; - input.hiddenTextElement = hidden_text; - input.selectionElement = selection; - input.cursorElement = cursor; + component.appendChild(content); + component.appendChild(radio); - input.updateValue = function () { - var component = this.parentNode.parentNode; + return component; +}; +/*-------------------------------------------------------------- +>>> CHECKBOX +--------------------------------------------------------------*/ - for (var i = this.textElement.childNodes.length - 1; i > -1; i--) { - this.textElement.childNodes[i].remove(); - } +satus.components.checkbox = function (skeleton) { + var component = document.createElement('button'), + content = document.createElement('span'); - if (this.value.length > 0) { - if (component.languages[component._syntax]) { - component.languages[component._syntax](component); - } else { - this.textElement.textContent = this.value; - } - } - }; + component.inner = content; - input.updateCursor = function () { - var cursor = this.cursorElement, - selection = this.selectionElement, - hidden_text = this.hiddenTextElement, - start = this.selectionStart, - end = this.selectionEnd; + content.className = 'satus-checkbox__content'; - cursor.style.animation = 'none'; + component.appendChild(content); - if (start === end) { - selection.setAttribute('disabled', ''); + component.addEventListener('click', function () { + if (this.dataset.value === 'true') { + this.storageValue = false; + this.dataset.value = 'false'; } else { - selection.removeAttribute('disabled'); + this.storageValue = true; + this.dataset.value = 'true'; + } - hidden_text.textContent = this.value.substring(0, start); + this.storageChange(); + }); - selection.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; + component.addEventListener('render', function () { + this.dataset.value = this.storageValue; + }); - hidden_text.textContent = this.value.substring(start, end); + return component; +}; +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ - selection.style.width = hidden_text.offsetWidth + 'px'; - } +satus.components.select = function (skeleton) { + var component = document.createElement('div'), + component_content = document.createElement('span'), + component_value = document.createElement('span'), + select = document.createElement('select'); - if (this.selectionDirection === 'forward') { - hidden_text.textContent = this.value.substring(0, end); - } else { - hidden_text.textContent = this.value.substring(0, start); - } + component_content.className = 'satus-select__content'; + component_value.className = 'satus-select__value'; - cursor.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; + for (var i = 0, l = skeleton.options.length; i < l; i++) { + var option = document.createElement('option'); - cursor.style.animation = ''; + option.value = skeleton.options[i].value; - hidden_text.textContent = ''; - }; + satus.text(option, skeleton.options[i].text); - input.addEventListener('keydown', function () { - var self = this; + select.appendChild(option); + } - setTimeout(function () { - var component = self.parentNode.parentNode; + component.selectElement = select; + select.valueElement = component_value; - component.storageValue = self.value; - component.storageChange(); + select.addEventListener('change', function () { + satus.empty(this.valueElement); - self.updateValue(); - self.updateCursor(); - }); - }); + satus.text(this.valueElement, this.options[this.selectedIndex].text); - input.addEventListener('scroll', function (event) { - this.textElement.style.left = -this.scrollLeft + 'px'; - }); + this.parentNode.storageValue = this.value; - document.addEventListener('selectionchange', function () { - input.updateCursor(); + this.parentNode.storageChange(); }); - selection.setAttribute('disabled', ''); - - pre.appendChild(input); - pre.appendChild(hidden_text); - pre.appendChild(text); - pre.appendChild(selection); - pre.appendChild(cursor); - component.appendChild(pre); + component.appendChild(component_content); + component.appendChild(component_value); + component.appendChild(select); component.addEventListener('render', function () { - input.value = this.storageValue; + select.value = this.storageValue || this.skeleton.options[0].value; - this.inputElement.updateValue(); - this.inputElement.updateCursor(); + satus.text(select.valueElement, select.options[select.selectedIndex].text); }); - return component; -}; -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -satus.components.alert = function (skeleton) { - var component = document.createElement('div'); + component.inner = component_content; return component; }; /*-------------------------------------------------------------- ->>> LAYERS +>>> SHORTCUT --------------------------------------------------------------*/ -satus.components.layers = function (skeleton) { - var component = document.createElement('div'); - - component.path = [skeleton]; +satus.components.shortcut = function (skeleton) { + var component = document.createElement('button'), + content = document.createElement('span'), + value = document.createElement('div'); - component.back = function () { - if (this.path.length > 1) { - this.path.pop(); + component.inner = content; - this.open(); - } - }; + component.className = 'satus-button'; + value.className = 'satus-shortcut__value'; - component.open = function (skeleton) { - var layer = document.createElement('div'); + component.render = function (parent) { + var self = this, + parent = parent || self.primary, + children = parent.children; - if (skeleton) { - this.path.push(skeleton); - } else { - skeleton = this.path[this.path.length - 1]; - } + satus.empty(parent); - layer.className = 'satus-layer'; + function createElement(name) { + var element = document.createElement('div'); - layer.skeleton = skeleton; - layer.base = this.base; + element.className = 'satus-shortcut__' + name; - satus.render(skeleton, layer, skeleton.component === 'layers'); + parent.appendChild(element); - satus.empty(this); + return element; + } - this.appendChild(layer); + if (this.data.alt) { + createElement('key').textContent = 'Alt'; + } - this.dispatchEvent(new Event('open')); - }; + if (this.data.ctrl) { + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - component.update = function () { - var layer = this.querySelector('.satus-layer'); + createElement('key').textContent = 'Ctrl'; + } - satus.empty(layer); + if (this.data.shift) { + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - satus.render(layer.skeleton, layer); - }; + createElement('key').textContent = 'Shift'; + } - component.render_children = false; + for (var code in this.data.keys) { + var key = this.data.keys[code].key, + arrows = ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft'], + index = arrows.indexOf(key); - component.addEventListener('render', function () { - this.open(); - }); + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - return component; -}; -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ + if (index !== -1) { + createElement('key').textContent = ['↑', '→', '↓', '←'][index]; + } else if (key === ' ') { + createElement('key').textContent = '␣'; + } else if (key) { + createElement('key').textContent = key.toUpperCase(); + } + } -satus.components.divider = function () { - var component = document.createElement('div'); + if (this.data.wheel) { + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - return component; -}; -/*-------------------------------------------------------------- ->>> INPUT ---------------------------------------------------------------*/ + var mouse = createElement('mouse'), + div = document.createElement('div'); -satus.components.input = function (skeleton) { - var component = document.createElement('input'); + mouse.appendChild(div); - if (skeleton.attr) { - var key = skeleton.attr.name || skeleton.storage, - value; + mouse.className += ' ' + (this.data.wheel > 0); + } - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } + if (this.data.click) { + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - if (skeleton.attr.type === 'radio') { - component.checked = value === skeleton.attr.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } + var mouse = createElement('mouse'), + div = document.createElement('div'); - component.addEventListener('change', function () { - var key = this.skeleton.attr.name || this.skeleton.storage; + mouse.appendChild(div); - satus.storage.set(key, this.value); - }); - } else { - var key = skeleton.name || skeleton.storage, - value; + mouse.className += ' click'; + } - component.type = skeleton.type; + if (this.data.context) { + if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { + createElement('plus'); + } - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } + var mouse = createElement('mouse'), + div = document.createElement('div'); - if (skeleton.type === 'radio') { - component.checked = value === skeleton.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } + mouse.appendChild(div); - component.addEventListener('change', function () { - var key = this.skeleton.name || this.skeleton.storage; + mouse.className += ' context'; + } + }; - satus.storage.set(key, this.value); - }); - } + component.valueElement = value; - return component; -}; -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ + component.appendChild(content); + component.appendChild(value); -satus.components.select = function (skeleton) { - var component = document.createElement('div'), - component_content = document.createElement('span'), - component_value = document.createElement('span'), - select = document.createElement('select'); + component.keydown = function (event) { + event.preventDefault(); + event.stopPropagation(); - component_content.className = 'satus-select__content'; - component_value.className = 'satus-select__value'; + component.data = { + alt: event.altKey, + ctrl: event.ctrlKey, + shift: event.shiftKey, + keys: {} + }; - for (var i = 0, l = skeleton.options.length; i < l; i++) { - var option = document.createElement('option'); + if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) { + component.data.keys[event.keyCode] = { + code: event.code, + key: event.key + }; + } - option.value = skeleton.options[i].value; + component.data.wheel = 0; - satus.text(option, skeleton.options[i].text); + component.render(); - select.appendChild(option); - } + return false; + }; - component.selectElement = select; - select.valueElement = component_value; + component.mousewheel = function (event) { + event.stopPropagation(); - select.addEventListener('change', function () { - satus.empty(this.valueElement); + 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: {} + }; + } - satus.text(this.valueElement, this.options[this.selectedIndex].text); + component.data.wheel = event.deltaY < 0 ? -1 : 1; - this.parentNode.storageValue = this.value; + component.render(); - this.parentNode.storageChange(); - }); + return false; + }; - component.appendChild(component_content); - component.appendChild(component_value); - component.appendChild(select); + component.addEventListener('render', function () { + this.data = this.storageValue || { + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0 + }; - component.addEventListener('render', function () { - select.value = this.storageValue || this.skeleton.options[0].value; + this.render(this.valueElement); + }); - satus.text(select.valueElement, select.options[select.selectedIndex].text); - }); + component.addEventListener('click', function () { + satus.render({ + component: 'modal', + on: { + close: function () { + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + }, - component.inner = component_content; + primary: { + component: 'div', + class: 'satus-shortcut__primary', + on: { + render: function () { + component.primary = this; - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR: ----------------------------------------------------------------- -# RGB to HSL -# HUE to RGB -# HSL to RGB ---------------------------------------------------------------*/ + if (component.skeleton.mouseButtons === true) { + this.addEventListener('click', function () { + component.data.context = false; + component.data.click = true; -satus.color = {}; + component.render(); + }); + this.addEventListener('contextmenu', function (event) { + event.preventDefault(); + event.stopPropagation(); -/*-------------------------------------------------------------- -# RGB TO HSL ---------------------------------------------------------------*/ + component.data.context = true; + component.data.click = false; -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; + component.render(); - if (min === max) { - h = 0; - s = 0; - } else { - var delta = max - min; + return false; + }); + } - s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); + component.render(); + } + } + }, + actions: { + component: 'section', + variant: 'actions', - 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; - } + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + component.data = component.skeleton.value || {}; - h /= 6; - } + component.render(component.valueElement); - h *= 360; - s *= 100; - l *= 100; + satus.storage.set(skeleton.storage, false); - if (array.length === 3) { - return [h, s, l]; + 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.storageValue = component.data; + + component.storageChange(); + + component.render(component.valueElement); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + } + } + }); + + window.addEventListener('keydown', this.keydown); + window.addEventListener('wheel', this.mousewheel); + }); + + return component; +}; +/*-------------------------------------------------------------- +>>> SWITCH +--------------------------------------------------------------*/ + +satus.components.switch = function (skeleton) { + var component = document.createElement('button'), + component_content = document.createElement('span'), + component_thumb = document.createElement('i'); + + component.inner = component_content; + + component_content.className = 'satus-switch__content'; + + component.addEventListener('click', function () { + if (this.dataset.value === 'true') { + this.storageValue = false; + this.dataset.value = 'false'; + } else { + this.storageValue = true; + this.dataset.value = 'true'; + } + + this.storageChange(); + }); + + component.addEventListener('render', function () { + this.dataset.value = this.storageValue; + }); + + component.appendChild(component_content); + component.appendChild(component_thumb); + + return component; +}; +/*-------------------------------------------------------------- +>>> LAYERS +--------------------------------------------------------------*/ + +satus.components.layers = function (skeleton) { + var component = document.createElement('div'); + + component.path = [skeleton]; + + component.back = function () { + if (this.path.length > 1) { + this.path.pop(); + + this.open(); + } + }; + + component.open = function (skeleton) { + var layer = document.createElement('div'); + + if (skeleton) { + this.path.push(skeleton); + } else { + skeleton = this.path[this.path.length - 1]; + } + + layer.className = 'satus-layer'; + + layer.skeleton = skeleton; + layer.base = this.base; + + satus.render(skeleton, layer, skeleton.component === 'layers'); + + satus.empty(this); + + this.appendChild(layer); + + this.dispatchEvent(new Event('open')); + }; + + component.update = function () { + var layer = this.querySelector('.satus-layer'); + + satus.empty(layer); + + satus.render(layer.skeleton, layer); + }; + + component.render_children = false; + + component.addEventListener('render', function () { + this.open(); + }); + + return component; +}; +/*-------------------------------------------------------------- +>>> INPUT +--------------------------------------------------------------*/ + +satus.components.input = function (skeleton) { + var component = document.createElement('input'); + + if (skeleton.attr) { + var key = skeleton.attr.name || skeleton.storage, + value; + + if (satus.isset(satus.storage.get(key))) { + value = satus.storage.get(key); + } else { + value = skeleton.value; + } + + if (skeleton.attr.type === 'radio') { + component.checked = value === skeleton.attr.value || skeleton.value; + } else if (satus.isset(value)) { + component.value = value; + } + + component.addEventListener('change', function () { + var key = this.skeleton.attr.name || this.skeleton.storage; + + satus.storage.set(key, this.value); + }); } else { - return [h, s, l, array[3]]; + var key = skeleton.name || skeleton.storage, + value; + + component.type = skeleton.type; + + if (satus.isset(satus.storage.get(key))) { + value = satus.storage.get(key); + } else { + value = skeleton.value; + } + + if (skeleton.type === 'radio') { + component.checked = value === skeleton.value || skeleton.value; + } else if (satus.isset(value)) { + component.value = value; + } + + component.addEventListener('change', function () { + var key = this.skeleton.name || this.skeleton.storage; + + satus.storage.set(key, this.value); + }); } -}; + return component; +}; +/*-------------------------------------------------------------- +>>> MENUBAR +--------------------------------------------------------------*/ + +satus.components.menubar = function (skeleton) { + function createList(items) { + var ul = document.createElement('ul'); + + for (var key in items) { + var item = items[key], + li = document.createElement('li'); + + satus.render(item, li); + + if (item.items) { + li.appendChild(createList(item.items)); + } + + ul.appendChild(li); + } + + return ul; + } + + return createList(skeleton.items); +}; +/*-------------------------------------------------------------- +>>> TEXTAREA +--------------------------------------------------------------*/ + +satus.components.textarea = function (skeleton) { + var component = document.createElement('div'), + line_number = document.createElement('div'), + textarea = document.createElement('textarea'); + + line_number.className = 'satus-textarea__line-number'; + + component.line_number = line_number; + component.textarea = textarea; + + Object.defineProperty(component, 'value', { + get() { + return this.textarea.value; + }, + set(value) { + this.textarea.value = value; + + this.line_number.update(); + } + }); + + line_number.update = function () { + var count = this.parentNode.textarea.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); + } + } + }; + + textarea.addEventListener('input', function () { + this.parentNode.line_number.update(); + }); + + textarea.addEventListener('selectionchange', function () { + this.parentNode.line_number.update(); + }); + + textarea.addEventListener('scroll', function () { + this.parentNode.line_number.style.transform = 'translateY(-' + this.scrollTop + 'px)'; + + this.parentNode.line_number.update(); + }); + + component.appendChild(line_number); + component.appendChild(textarea); + + line_number.update(1); + + return component; +}; +/*-------------------------------------------------------------- +>>> DIVIDER +--------------------------------------------------------------*/ + +satus.components.divider = function () { + var component = document.createElement('div'); + + return component; +}; +/*-------------------------------------------------------------- +>>> TEXT FIELD +--------------------------------------------------------------*/ + +satus.components.textField = function (skeleton) { + var component = document.createElement('div'), + pre = document.createElement('pre'), + input = document.createElement('textarea'), + hidden_text = document.createElement('span'), + text = document.createElement('span'), + selection = document.createElement('div'), + cursor = document.createElement('div'); + + input.className = 'satus-text-field__input'; + pre.className = 'satus-text-field__pre'; + hidden_text.className = 'satus-text-field__hidden-text'; + text.className = 'satus-text-field__text'; + selection.className = 'satus-text-field__selection'; + cursor.className = 'satus-text-field__cursor'; + + component.inputElement = input; + component.textElement = text; + component.languages = { + regex: function (component) { + 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 = component.inputElement.value.match(regex_token); + + function create(type, string) { + var span = document.createElement('span'); + + span.className = type; + span.textContent = string; + + component.textElement.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); + } + } + } + }; + component._syntax = skeleton.syntax; + + Object.defineProperty(component, 'value', { + get: function () { + return this.inputElement.value; + }, + set: function (value) { + var input = this.inputElement; + + input.value = value; + + input.updateValue(); + input.updateCursor(); + } + }); + + Object.defineProperty(component, 'syntax', { + get: function () { + return this._syntax; + }, + set: function (value) { + var input = this.inputElement; + + this._syntax = value; + + input.updateValue(); + input.updateCursor(); + } + }); + + input.rows = skeleton.rows || 1; + input.autocapitalize = 'none'; + input.autocomplete = 'off'; + input.autocorrect = 'off'; + input.spellcheck = false; + input.autofocus = true; + input.textElement = text; + input.hiddenTextElement = hidden_text; + input.selectionElement = selection; + input.cursorElement = cursor; + + input.updateValue = function () { + var component = this.parentNode.parentNode; + + for (var i = this.textElement.childNodes.length - 1; i > -1; i--) { + this.textElement.childNodes[i].remove(); + } + + if (this.value.length > 0) { + if (component.languages[component._syntax]) { + component.languages[component._syntax](component); + } else { + this.textElement.textContent = this.value; + } + } + }; + + input.updateCursor = function () { + var cursor = this.cursorElement, + selection = this.selectionElement, + hidden_text = this.hiddenTextElement, + start = this.selectionStart, + end = this.selectionEnd; + + cursor.style.animation = 'none'; + + if (start === end) { + selection.setAttribute('disabled', ''); + } else { + selection.removeAttribute('disabled'); + + hidden_text.textContent = this.value.substring(0, start); + + selection.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; + + hidden_text.textContent = this.value.substring(start, end); + + selection.style.width = hidden_text.offsetWidth + 'px'; + } + + if (this.selectionDirection === 'forward') { + hidden_text.textContent = this.value.substring(0, end); + } else { + hidden_text.textContent = this.value.substring(0, start); + } + + cursor.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; + + cursor.style.animation = ''; + + hidden_text.textContent = ''; + }; + + input.addEventListener('keydown', function () { + var self = this; + + setTimeout(function () { + var component = self.parentNode.parentNode; + + component.storageValue = self.value; + component.storageChange(); + + self.updateValue(); + self.updateCursor(); + }); + }); + + input.addEventListener('scroll', function (event) { + this.textElement.style.left = -this.scrollLeft + 'px'; + }); + + document.addEventListener('selectionchange', function () { + input.updateCursor(); + }); + + selection.setAttribute('disabled', ''); + + pre.appendChild(input); + pre.appendChild(hidden_text); + pre.appendChild(text); + pre.appendChild(selection); + pre.appendChild(cursor); + component.appendChild(pre); + + component.addEventListener('render', function () { + input.value = this.storageValue; + + this.inputElement.updateValue(); + this.inputElement.updateCursor(); + }); + + return component; +}; +/*-------------------------------------------------------------- +>>> TABS +--------------------------------------------------------------*/ + +satus.components.tabs = function (skeleton) { + var component = document.createElement('div'), + content = document.createElement('div'), + selection = document.createElement('div'); + + content.className = 'satus-tabs__content'; + selection.className = 'satus-tabs__selection'; + selection.style.width = 100 / skeleton.items.length + '%'; + + content.appendChild(selection); + + component.selection = selection; + + for (var i = 0, l = skeleton.items.length; i < l; i++) { + var item = skeleton.items[i], + button = document.createElement('button'); + + button.className = 'satus-tabs__button'; + button.value = item; + button.style.width = 100 / l + '%'; + + satus.text(button, item); + + button.addEventListener('click', function () { + var component = this.parentNode.parentNode; + + component.selection.style.left = 100 / (this.parentNode.children.length - 1) * (satus.indexOf(this) - 1) + '%'; -/*-------------------------------------------------------------- -# HUE TO RGB ---------------------------------------------------------------*/ + component.storageValue = this.value; + component.storageChange(); + }); -satus.color.hueToRgb = function (array) { - var t1 = array[0], - t2 = array[1], - hue = array[2]; + if (skeleton.value === item) { + selection.style.left = i * 50 + '%'; + } - if (hue < 0) { - hue += 6; + content.appendChild(button); } + + component.appendChild(content); - if (hue >= 6) { - hue -= 6; - } + component.addEventListener('render', function () { + var index = satus.indexOf(this.storageValue, this.skeleton.items); - 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; - } -}; + if (index === -1) { + index = 0; + } + this.selection.style.left = 100 / this.skeleton.items.length * index + '%'; + }); + return component; +}; /*-------------------------------------------------------------- -# HSL TO RGB +>>> ALERT --------------------------------------------------------------*/ -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 hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - - 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); - } +satus.components.alert = function (skeleton) { + var component = document.createElement('div'); - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; + return component; }; /*-------------------------------------------------------------- ->>> USER +>>> SLIDER --------------------------------------------------------------*/ -satus.user = function () { - /*-------------------------------------------------------------- - 1.0 VARIABLES - --------------------------------------------------------------*/ - - var user_agent = navigator.userAgent, - random_cookie = 'ta{t`nX6cMXK,Wsc', - video = document.createElement('video'), - video_formats = { - 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"' - }, - audio = document.createElement('audio'), - audio_formats = { - mp3: 'audio/mpeg', - mp4: 'audio/mp4', - aif: 'audio/x-aiff' - }, - cvs = document.createElement('canvas'), - ctx = cvs.getContext('webgl'), - data = { - browser: { - audio: null, - cookies: null, - flash: null, - java: null, - languages: null, - name: null, - platform: null, - version: null, - video: null, - webgl: null - }, - os: { - name: null, - type: null - }, - device: { - connection: { - type: null, - speed: null - }, - cores: null, - gpu: null, - max_touch_points: null, - ram: null, - screen: null, - touch: null - } - }; +satus.components.slider = function (skeleton) { + var component = document.createElement('div'), + content = document.createElement('div'), + container = document.createElement('div'), + track = document.createElement('div'), + track_fill = document.createElement('div'); + container.className = 'satus-slider__container'; + track.className = 'satus-slider__track'; + track_fill.className = 'satus-slider__track-fill'; - /*-------------------------------------------------------------- - 2.0 SOFTWARE - --------------------------------------------------------------*/ + component.min = skeleton.min || 0; + component.max = skeleton.max || 1; + component.step = (skeleton.step || 1); + component.percent = 100 / ((component.max - component.min) / component.step); + component.precision = String(component.step).replace(/[0-9]./, '').length; - /*-------------------------------------------------------------- - 2.1.0 OS - --------------------------------------------------------------*/ + component.container = container; + component.track = track_fill; + component.handles = []; + component.inner = content; - /*-------------------------------------------------------------- - 2.1.1 NAME - --------------------------------------------------------------*/ + component.toPercent = function (number) { + return number / this.step * this.percent + '%'; + }; - if (navigator.appVersion.indexOf('Win') !== -1) { - if (navigator.appVersion.match(/(Windows 10.0|Windows NT 10.0)/)) { - data.os.name = 'Windows 10'; - } else if (navigator.appVersion.match(/(Windows 8.1|Windows NT 6.3)/)) { - data.os.name = 'Windows 8.1'; - } else if (navigator.appVersion.match(/(Windows 8|Windows NT 6.2)/)) { - data.os.name = 'Windows 8'; - } else if (navigator.appVersion.match(/(Windows 7|Windows NT 6.1)/)) { - data.os.name = 'Windows 7'; - } else if (navigator.appVersion.match(/(Windows NT 6.0)/)) { - data.os.name = 'Windows Vista'; - } else if (navigator.appVersion.match(/(Windows NT 5.1|Windows XP)/)) { - data.os.name = 'Windows XP'; - } else { - data.os.name = 'Windows'; - } - } else if (navigator.appVersion.indexOf('(iPhone|iPad|iPod)') !== -1) { - data.os.name = 'iOS'; - } else if (navigator.appVersion.indexOf('Mac') !== -1) { - data.os.name = 'macOS'; - } else if (navigator.appVersion.indexOf('Android') !== -1) { - data.os.name = 'Android'; - } else if (navigator.appVersion.indexOf('OpenBSD') !== -1) { - data.os.name = 'OpenBSD'; - } else if (navigator.appVersion.indexOf('SunOS') !== -1) { - data.os.name = 'SunOS'; - } else if (navigator.appVersion.indexOf('Linux') !== -1) { - data.os.name = 'Linux'; - } else if (navigator.appVersion.indexOf('X11') !== -1) { - data.os.name = 'UNIX'; - } + component.createHandle = function (index) { + var handle = document.createElement('div'); - /*-------------------------------------------------------------- - 2.1.2 TYPE - --------------------------------------------------------------*/ + handle.className = 'satus-slider__handle'; + handle.handleIndex = index; + handle.tabIndex = 0; - if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { - data.os.type = '64-bit'; - } else { - data.os.type = '32-bit'; - } + this.handles.push(handle); + this.container.appendChild(handle); + }; - /*-------------------------------------------------------------- - 2.2.0 BROWSER - --------------------------------------------------------------*/ + component.update = function () { + if (this.values.length > 1) { + var min = Math.min.apply(null, this.values) - this.min, + max = Math.max.apply(null, this.values) - this.min; - /*-------------------------------------------------------------- - 2.2.1 NAME - --------------------------------------------------------------*/ + this.track.style.left = this.toPercent(min); + this.track.style.width = this.toPercent(max - min); - if (user_agent.indexOf('Opera') !== -1) { - data.browser.name = 'Opera'; - } else if (user_agent.indexOf('Vivaldi') !== -1) { - data.browser.name = 'Vivaldi'; - } else if (user_agent.indexOf('Edge') !== -1) { - data.browser.name = 'Edge'; - } else if (user_agent.indexOf('Chrome') !== -1) { - data.browser.name = 'Chrome'; - } else if (user_agent.indexOf('Safari') !== -1) { - data.browser.name = 'Safari'; - } else if (user_agent.indexOf('Firefox') !== -1) { - data.browser.name = 'Firefox'; - } else if (user_agent.indexOf('MSIE') !== -1) { - data.browser.name = 'IE'; - } + for (var i = 0, l = this.handles.length; i < l; i++) { + var handle = this.handles[i], + value = this.values[i]; + handle.style.left = this.toPercent(value - this.min); + handle.dataset.value = value; + } + } else { + var value = this.values[0]; - /*-------------------------------------------------------------- - 2.2.2 VERSION - --------------------------------------------------------------*/ + this.track.style.width = this.toPercent(value - this.min); + this.handles[0].style.left = this.toPercent(value - this.min); + this.handles[0].dataset.value = value; + } + }; - var browser_version = user_agent.match(new RegExp(data.browser.name + '/([0-9.]+)')); + component.appendChild(content); + track.appendChild(track_fill); + container.appendChild(track); + component.appendChild(container); - if (browser_version[1]) { - data.browser.version = browser_version[1]; - } + component.addEventListener('keydown', function (event) { + var code = event.keyCode; + console.log(code); + }); - /*-------------------------------------------------------------- - 2.2.3 PLATFORM - --------------------------------------------------------------*/ + component.addEventListener('render', function () { + var value = this.storageValue; - data.browser.platform = navigator.platform || null; + if (satus.isArray(value)) { + this.values = value; + } else if (satus.isNumber(value)) { + this.values = [value]; + } else { + this.values = this.skeleton.values || [satus.isset(this.skeleton.value) ? this.skeleton.value : 1]; + } + for (var i = 0, l = this.values.length; i < l; i++) { + this.createHandle(i); + } - /*-------------------------------------------------------------- - 2.2.4 LANGUAGES - --------------------------------------------------------------*/ + this.update(); + }); - data.browser.languages = navigator.languages || null; + container.addEventListener('mousedown', function (event) { + if (event.button === 0) { + var component = this.parentNode, + rect = this.getBoundingClientRect(), + cursor_x = event.clientX - rect.left, + percent = cursor_x / rect.width * 100, + steps = percent / component.percent * component.step + component.min, + closest_value = component.values.indexOf(component.values.reduce(function(previous, current, index) { + return Math.abs(current - steps) < Math.abs(previous - steps) ? current : previous; + })), + handle_index = component.handles[closest_value].handleIndex; + setTimeout(function () { + component.handles[closest_value].focus(); + }); - /*-------------------------------------------------------------- - 2.2.5 COOKIES - --------------------------------------------------------------*/ + function update(event) { + var cursor_x = Math.min(Math.max(event.clientX - rect.left, 0), rect.width), + percent = cursor_x / rect.width * 100, + value = percent / component.percent * component.step + component.min; - if (document.cookie) { - document.cookie = random_cookie; + value = (Math.round(value / component.step) * component.step); - if (document.cookie.indexOf(random_cookie) !== -1) { - data.browser.cookies = true; - } - } + value = Number(value.toFixed(component.precision)); + if (component.values[handle_index] !== value) { + component.values[handle_index] = value; - /*-------------------------------------------------------------- - 2.2.6 FLASH - --------------------------------------------------------------*/ + component.storageValue = component.values.length === 1 ? component.values[0] : component.values; + component.value = component.storageValue; - try { - if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { - data.browser.flash = true; - } - } catch (e) { - if (navigator.mimeTypes['application/x-shockwave-flash']) { - data.browser.flash = true; - } - } + component.storageChange(); + } + component.update(); + } - /*-------------------------------------------------------------- - 2.2.7 JAVA - --------------------------------------------------------------*/ + function mousemove(event) { + update(event); + } - if (typeof navigator.javaEnabled === 'function' && navigator.javaEnabled()) { - data.browser.java = true; - } + function mouseup(event) { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + }; + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); - /*-------------------------------------------------------------- - 2.2.8 VIDEO FORMATS - --------------------------------------------------------------*/ + update(event); - if (typeof video.canPlayType === 'function') { - data.browser.video = {}; + return true; + } + }); - for (var i in video_formats) { - var can_play_type = video.canPlayType(video_formats[i]); + return component; +}; +/*-------------------------------------------------------------- +>>> COLOR PICKER +--------------------------------------------------------------*/ - if (can_play_type === '') { - data.browser.video[i] = false; - } else { - data.browser.video[i] = can_play_type; - } - } - } +satus.components.colorPicker = function (skeleton) { + var component = document.createElement('button'), + component_label = document.createElement('span'), + component_value = document.createElement('span'); + component.inner = component_label; + component.valueElement = component_value; - /*-------------------------------------------------------------- - 2.2.9 AUDIO FORMATS - --------------------------------------------------------------*/ + component.className = 'satus-button'; + component_value.className = 'satus-color-picker__value'; - if (typeof audio.canPlayType === 'function') { - data.browser.audio = {}; + component.appendChild(component_label); + component.appendChild(component_value); - for (var i in audio_formats) { - var can_play_type = audio.canPlayType(audio_formats[i]); + component.addEventListener('click', function () { + var rgb = this.rgb, + hsl = satus.color.rgbToHsl(rgb), + s = hsl[1] / 100, + l = hsl[2] / 100; - if (can_play_type == '') { - data.browser.audio[i] = false; - } else { - data.browser.audio[i] = can_play_type; - } - } - } + s *= l < .5 ? l : 1 - l; + var v = l + s; - /*-------------------------------------------------------------- - 2.2.10 WEBGL - --------------------------------------------------------------*/ + s = 2 * s / (l + s); - if (ctx && ctx instanceof WebGLRenderingContext) { - data.browser.webgl = true; - } + satus.render({ + component: 'modal', + variant: 'color-picker', + value: hsl, + parent: 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]; - /*-------------------------------------------------------------- - 3.0 HARDWARE - --------------------------------------------------------------*/ + function mousemove(event) { + var hsl = palette.skeleton.parent.value, + x = event.clientX - rect.left, + y = event.clientY - rect.top, + s; - /*-------------------------------------------------------------- - 3.1 SCREEN - --------------------------------------------------------------*/ + x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); + y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); - if (screen) { - data.device.screen = screen.width + 'x' + screen.height; - } + var v = 100 - y, + l = (2 - x / 100) * v / 2; + hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); + hsl[2] = l; - /*-------------------------------------------------------------- - 3.2 RAM - --------------------------------------------------------------*/ + cursor.style.left = x + '%'; + cursor.style.top = y + '%'; - if ('deviceMemory' in navigator) { - data.device.ram = navigator.deviceMemory + ' GB'; - } + palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + event.preventDefault(); + } - /*-------------------------------------------------------------- - 3.3 GPU - --------------------------------------------------------------*/ + function mouseup() { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } - if ( - ctx && - ctx instanceof WebGLRenderingContext && - 'getParameter' in ctx && - 'getExtension' in ctx - ) { - var info = ctx.getExtension('WEBGL_debug_renderer_info'); + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + }, - if (info) { - data.device.gpu = ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); - } - } + 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.parent.parent, + hsl = modal.value; - /*-------------------------------------------------------------- - 3.4 CORES - --------------------------------------------------------------*/ + hsl[0] = this.values[0]; - if (navigator.hardwareConcurrency) { - data.device.cores = navigator.hardwareConcurrency; - } + 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.parent.parent, + component = modal.parent; - /*-------------------------------------------------------------- - 3.5 TOUCH - --------------------------------------------------------------*/ + component.rgb = component.skeleton.value; - if ( - window.hasOwnProperty('ontouchstart') || - window.DocumentTouch && document instanceof window.DocumentTouch || - navigator.maxTouchPoints > 0 || - window.navigator.msMaxTouchPoints > 0 - ) { - data.device.touch = true; - data.device.max_touch_points = navigator.maxTouchPoints; - } + component.storageValue = component.rgb; + component.storageChange(); + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - /*-------------------------------------------------------------- - 3.6 CONNECTION - --------------------------------------------------------------*/ + modal.rendered.close(); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.skeleton.parent.parent.rendered.close(); + } + } + }, + ok: { + component: 'button', + text: 'OK', + on: { + click: function () { + var modal = this.skeleton.parent.parent, + component = modal.parent; - if (typeof navigator.connection === 'object') { - data.device.connection.type = navigator.connection.effectiveType || null; + component.rgb = satus.color.hslToRgb(modal.value); - if (navigator.connection.downlink) { - data.device.connection.speed = navigator.connection.downlink + ' Mbps'; - } - } + component.storageValue = component.rgb; + component.storageChange(); + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - /*-------------------------------------------------------------- - 4.0 CLEARING - --------------------------------------------------------------*/ + modal.rendered.close(); + } + } + } + } + }); + }); - video.remove(); - audio.remove(); - cvs.remove(); + component.addEventListener('render', function () { + component.rgb = this.storageValue || [0, 100, 50]; + component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + }); - return data; + return component; }; /*-------------------------------------------------------------- ->>> CONTEXT MENU +>>> LIST --------------------------------------------------------------*/ -satus.events.add('render', function (component, skeleton) { - if (skeleton.contextMenu) { - component.addEventListener('contextmenu', function (event) { - var x = event.clientX, - y = event.clientY, - modal = satus.render({ - component: 'modal', - variant: 'contextmenu', - parent: skeleton - }); - - if (window.innerWidth - x < 200) { - x = window.innerWidth - 200; - } - - modal.inner.style.left = x + 'px'; - modal.inner.style.top = y + 'px'; - - satus.render(skeleton.contextMenu, modal.inner); - - event.preventDefault(); - event.stopPropagation(); +satus.components.list = function (skeleton) { + var ul = document.createElement('ul'); - return false; - }); - } -}); -/*-------------------------------------------------------------- ->>> EXTENSION STORAGE ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> PLUVIAM ---------------------------------------------------------------*/ + for (var i = 0, l = skeleton.items.length; i < l; i++) { + var li = document.createElement('li'), + item = skeleton.items[i]; -satus.events.add('render', function (component, skeleton) { - if (skeleton.pluviam === true) { - function createPluviam(event) { - var pluviam = document.createElement('span'), - rect = this.getBoundingClientRect(), - x = event.clientX - rect.left, - y = event.clientY - rect.top, - diameter = Math.sqrt(Math.pow(rect.width * 2, 2) + Math.pow(rect.height * 2, 2)); + li.className = 'satus-list__item'; - pluviam.className = 'satus-pluviam'; + for (var j = 0, k = item.length; j < k; j++) { + var child = item[j]; - pluviam.style.left = x - diameter / 2 + 'px'; - pluviam.style.top = y - diameter / 2 + 'px'; - pluviam.style.width = diameter + 'px'; - pluviam.style.height = diameter + 'px'; + if (typeof child === 'string') { + var span = document.createElement('span'); - this.appendChild(pluviam); + span.textContent = satus.locale.get(child); - setTimeout(function () { - pluviam.remove(); - }, 1000); + li.appendChild(span); + } else { + satus.render(child, li); + } } - component.addEventListener('mousedown', createPluviam); - component.addEventListener('mouseover', createPluviam); + ul.appendChild(li); } -}); + + return ul; +}; /*-------------------------------------------------------------- ->>> SORTABLE +>>> MODAL --------------------------------------------------------------*/ -satus.events.add('render', function (component, skeleton) { - if (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.parentNode.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(); +satus.components.modal = function (skeleton) { + var component = document.createElement('div'), + scrim = document.createElement('div'), + surface = document.createElement('div'); - return false; - } + component.inner = surface; - window.addEventListener('mousemove', mousemove, { - passive: true, - capture: true - }); + scrim.className = 'satus-modal__scrim'; + surface.className = 'satus-modal__surface'; - window.addEventListener('mouseup', mouseup, { - passive: true, - capture: true - }); + component.close = function () { + var component = this, + component_surface = this.children[1]; - function siblingMouseOver(event) { - var target = event.target, - parent = target.parentNode, - y = event.layerY / (target.offsetHeight / 100); + this.classList.add('satus-modal--closing'); - if (y < 50 && target.previousSibling !== component || y >= 50 && target.nextSibling === component) { - parent.insertBefore(component, target); - } else { - parent.insertBefore(component, target.nextSibling); - } - } + setTimeout(function () { + component.remove(); - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; + component.dispatchEvent(new CustomEvent('close')); + }, satus.getAnimationDuration(component_surface)); + }; - if (child !== component) { - child.addEventListener('mouseover', siblingMouseOver); - } - } + scrim.addEventListener('click', function () { + this.parentNode.close(); + }); - event.stopPropagation(); - event.preventDefault(); + component.appendChild(scrim); + component.appendChild(surface); - return false; - }); - } -}); \ No newline at end of file + return component; +}; \ No newline at end of file diff --git a/ui/script.js b/ui/script.js new file mode 100644 index 0000000..e5a27c4 --- /dev/null +++ b/ui/script.js @@ -0,0 +1,842 @@ +/*-------------------------------------------------------------- +>>> TEXT EDITOR: +---------------------------------------------------------------- +# Global variables +# Functions +# Skeleton +# Initialization +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GLOBAL VARIABLES +--------------------------------------------------------------*/ + +var functions = {}; + + + + + + + + + + + + + + + + +/*-------------------------------------------------------------- +# FUNCTIONS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# NEW FILE +--------------------------------------------------------------*/ + +functions.newFile = function () { + var textarea = skeleton.main.textarea.rendered; + + textarea.indexId = undefined; + textarea.name = undefined; + textarea.value = ''; + + satus.indexeddb.clear('session'); + + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); +}; + + +/*-------------------------------------------------------------- +# OPEN FILE +--------------------------------------------------------------*/ + +functions.openFile = function (id) { + satus.indexeddb.clear('session'); + + satus.indexeddb.getByKey({ + content: [ + id + ], + files: [ + id + ] + }, function (items) { + if (items.files[0]) { + var textarea = skeleton.main.textarea.rendered; + + textarea.indexId = id; + textarea.name = items.files[0].name; + textarea.value = items.content[0].content; + + skeleton.main.sidebar.list.update(); + + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); + + satus.indexeddb.set({ + session: [ + {id} + ] + }); + } + }); +}; + + +/*-------------------------------------------------------------- +# SAVE +--------------------------------------------------------------*/ + +functions.save = function (name, content, id) { + if (satus.isset(id) || name) { + var object = { + time: new Date().getTime(), + name: name + }; + + if (id) { + object.id = id; + } + + satus.indexeddb.clear('session'); + + satus.indexeddb.set({ + files: [ + object + ] + }, function () { + satus.indexeddb.get({ + files: { + direction: 'prev', + limit: 1 + } + }, function (items) { + if (items.files[0]) { + skeleton.main.textarea.indexId = items.files[0].id; + + satus.indexeddb.set({ + content: [ + { + id: items.files[0].id, + content: content + } + ], + session: [ + { + id: items.files[0].id + } + ] + }, function () { + satus.indexeddb.get({ + content: { + direction: 'prev', + limit: 1 + } + }, function (items) { + if (items.content[0]) { + skeleton.main.sidebar.list.update(); + } + }); + }); + } + }); + }); + } else { + satus.render({ + component: 'modal', + + input: { + component: 'input', + properties: { + type: 'text', + value: name || 'untitled' + }, + on: { + render: function () { + this.focus(); + } + } + }, + section_align_end: { + component: 'section', + variant: 'actions', + + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.parentNode.parentNode.parentNode.close(); + } + } + }, + save: { + component: 'button', + text: 'save', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + functions.save(modal.skeleton.input.rendered.value, content, id); + + modal.close(); + } + } + } + } + }); + } +}; + + +/*-------------------------------------------------------------- +# SAVE AS +--------------------------------------------------------------*/ + +functions.saveAs = function () { + var textarea = skeleton.main.textarea.rendered; + + chrome.permissions.request({ + permissions: ['downloads'] + }, function (granted) { + if (granted) { + chrome.downloads.download({ + url: URL.createObjectURL(new Blob([textarea.value], { + type: 'text/plain;charset=utf-8' + })), + filename: textarea.name || 'untitled', + saveAs: true + }); + } + }); +}; + + +/*-------------------------------------------------------------- +# IMPORT +--------------------------------------------------------------*/ + +functions.import = function () { + var input = document.createElement('input'); + + input.type = 'file'; + + input.addEventListener('change', function () { + var file_reader = new FileReader(); + + file_reader.onload = function (event) { + var textarea = skeleton.main.textarea.rendered; + + textarea.name = input.files[0].name; + textarea.value = this.result; + + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); + + functions.save( + textarea.name, + textarea.value + ); + }; + + file_reader.readAsText(this.files[0]); + }); + + input.click(); +}; + + +/*-------------------------------------------------------------- +# DELETE +--------------------------------------------------------------*/ + +functions.delete = function (id) { + satus.render({ + component: 'modal', + + label: { + component: 'span', + text: 'areYouSureYouWantToDeleteTheFile' + }, + section: { + component: 'section', + variant: 'actions', + + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + modal.close(); + } + } + }, + delete: { + component: 'button', + text: 'delete', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + satus.indexeddb.delete({ + content: { + id: [id] + }, + files: { + id: [id] + }, + session: { + id: [id] + } + }, function () { + var textarea = skeleton.main.textarea.rendered; + + textarea.indexId = null; + textarea.name = undefined; + textarea.value = ''; + + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); + + satus.indexeddb.set({ + session: [ + {id} + ] + }, function () { + skeleton.main.sidebar.list.update(); + }); + }); + + modal.close(); + } + } + } + } + }); +}; + + +/*-------------------------------------------------------------- +# CLOSE FILE +--------------------------------------------------------------*/ + +functions.closeFile = function () { + var textarea = skeleton.main.textarea.rendered; + + textarea.indexId = null; + textarea.name = undefined; + textarea.value = ''; + + satus.indexeddb.clear('session'); + + skeleton.main.sidebar.list.update(); + + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); +}; + + + + + + + + + + + + + + + + +/*-------------------------------------------------------------- +# SKELETON +--------------------------------------------------------------*/ + +var skeleton = { + component: 'base', + + menubar: { + component: 'menubar', + items: { + file: { + component: 'button', + text: 'file', + items: { + newFile: { + component: 'button', + text: 'newFile', + on: { + click: functions.newFile + } + }, + openFile: { + component: 'button', + text: 'openFile', + on: { + click: functions.import + } + }, + save: { + component: 'button', + text: 'save', + on: { + click: function () { + var textarea = skeleton.main.textarea.rendered; + + textarea.saved = true; + + functions.save( + textarea.name, + textarea.value + ); + } + } + }, + saveAs: { + component: 'button', + text: 'saveAs', + on: { + click: functions.saveAs + } + }, + deleteFile: { + component: 'button', + text: 'deleteFile', + on: { + click: function () { + functions.delete(skeleton.main.textarea.rendered.indexId); + } + } + }, + closeFile: { + component: 'button', + text: 'closeFile', + on: { + click: function () { + functions.closeFile(); + } + } + }, + quit: { + component: 'button', + text: 'quit', + on: { + click: function () { + window.close(); + } + } + } + } + }, + edit: { + component: 'button', + text: 'edit', + items: { + undo: { + component: 'button', + text: 'undo', + on: { + click: function () { + document.execCommand('undo', false, null); + + } + } + }, + redo: { + component: 'button', + text: 'redo', + on: { + click: function () { + document.execCommand('redo', false, null); + } + } + } + } + }, + help: { + component: 'button', + text: 'help', + items: { + reportABug: { + component: 'button', + text: 'reportABug', + on: { + click: function () { + window.open('https://github.com/victor-savinov/text-editor/issues', '_blank'); + } + } + }, + github: { + component: 'button', + text: 'GitHub', + on: { + click: function () { + window.open('https://github.com/victor-savinov/text-editor', '_blank'); + } + } + } + } + } + } + }, + main: { + component: 'main', + + sidebar: { + component: 'sidebar', + class: 'empty', + + h1: { + component: 'h1', + text: 'files' + }, + list: { + component: 'ul', + on: { + render: function () { + this.skeleton.update(); + } + }, + update: function () { + var list = this.rendered; + + satus.indexeddb.get({ + files: { + index: 'time' + } + }, function (items) { + var textarea = skeleton.main.textarea.rendered; + + satus.empty(list); + + if (items.files.length > 0) { + skeleton.main.sidebar.rendered.classList.remove('empty'); + } else { + skeleton.main.sidebar.rendered.classList.add('empty'); + } + + for (var i = 0, l = items.files.length; i < l; i++) { + var file = items.files[i]; + + satus.render({ + component: 'li', + text: file.name || 'untitled', + class: file.id === textarea.indexId ? 'selected' : '', + properties: { + indexId: file.id + }, + on: { + click: function () { + functions.openFile(this.indexId); + } + }, + contextMenu: { + rename: { + component: 'button', + text: 'rename', + on: { + click: function () { + var modal = this.parentNode.parentNode, + file = modal.skeleton.parent.rendered; + + satus.render({ + component: 'modal', + + input: { + component: 'input', + properties: { + type: 'text', + value: file.textContent + }, + on: { + render: function () { + this.focus(); + } + } + }, + section_align_end: { + component: 'section', + variant: 'actions', + + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.parentNode.parentNode.parentNode.close(); + } + } + }, + save: { + component: 'button', + text: 'save', + on: { + click: function () { + var modal = this.parentNode.parentNode.parentNode; + + satus.indexeddb.set({ + files: [ + { + id: file.indexId, + name: modal.skeleton.input.rendered.value, + time: new Date().getTime() + } + ] + }, function () { + skeleton.main.sidebar.list.update(); + }); + + modal.close(); + } + } + } + } + }); + + modal.close(); + } + } + }, + delete: { + component: 'button', + text: 'delete', + on: { + click: function () { + var modal = this.parentNode.parentNode; + + functions.delete(modal.skeleton.parent.rendered.indexId); + + modal.close(); + } + } + } + } + }, list); + } + }); + } + } + }, + textarea: { + component: 'textarea', + properties: { + saved: false + }, + on: { + input: function () { + this.saved = false; + }, + selectionchange: function () { + skeleton.footer.section_align_start.span.rendered.update(); + skeleton.footer.section_align_end.span.rendered.update(); + } + } + } + }, + footer: { + component: 'footer', + + section_align_start: { + component: 'section', + variant: 'align-start', + + span: { + component: 'span', + text: function () { + return satus.locale.get('line') + ' 1, ' + satus.locale.get('column') + ' 1'; + }, + properties: { + update: function () { + var textarea = skeleton.main.textarea.rendered, + message = skeleton.footer.section_align_start.span.rendered, + selection_start = textarea.textarea.selectionStart, + selection_end = textarea.textarea.selectionEnd; + + if (selection_start === selection_end) { + if (textarea.textarea.selectionDirection === 'forward') { + var column = textarea.textarea.selectionEnd; + } else { + var column = textarea.textarea.selectionStart; + } + + var lines = textarea.value.slice(0, column).split('\n'); + + message.textContent = satus.locale.get('line') + ' ' + lines.length + ', ' + satus.locale.get('column') + ' ' + (lines[lines.length - 1].length + 1); + } else { + var min = Math.min(selection_start, selection_end), + max = Math.max(selection_start, selection_end), + selected_text = textarea.value.slice(min, max); + + message.textContent = selected_text.split('\n').length + ' ' + satus.locale.get('lines') + ', ' + selected_text.length + ' ' + satus.locale.get('characters') + ' ' + satus.locale.get('selected'); + } + } + } + } + }, + section_align_end: { + component: 'section', + variant: 'align-end', + + span: { + component: 'span', + style: { + textTransform: 'capitalize' + }, + text: function () { + return satus.locale.get('characters') + ' 0, ' + satus.locale.get('bytes') + ' 0'; + }, + properties: { + update: function () { + var value = skeleton.main.textarea.rendered.value, + message = skeleton.footer.section_align_end.span.rendered; + + message.textContent = satus.locale.get('characters') + ' ' + value.length + ', ' + satus.locale.get('bytes') + ' ' + new Blob([value]).size; + } + } + } + } + } +}; + + + + + + + + + + + + + + + + +/*-------------------------------------------------------------- +# KEYBOARD +--------------------------------------------------------------*/ + +window.addEventListener('keydown', function (event) { + if (event.code === 'KeyN' && event.ctrlKey === true) { + event.preventDefault(); + event.stopPropagation(); + + functions.newFile(); + + return false; + } else if (event.code === 'KeyO' && event.ctrlKey === true) { + event.preventDefault(); + event.stopPropagation(); + + functions.import(); + + return false; + } else if (event.code === 'KeyS' && event.ctrlKey === true && event.shiftKey === true) { + event.preventDefault(); + event.stopPropagation(); + + functions.saveAs(); + + return false; + } else if (event.code === 'KeyS' && event.ctrlKey === true) { + var textarea = skeleton.main.textarea.rendered; + + event.preventDefault(); + event.stopPropagation(); + + functions.save(textarea.name, textarea.value, textarea.indexId); + + return false; + } else if (event.code === 'KeyQ' && event.ctrlKey === true) { + event.preventDefault(); + event.stopPropagation(); + + window.close(); + + return false; + } +}, true); + + + + + + + + + + + + + + + + +/*-------------------------------------------------------------- +# INITIALIZATION +--------------------------------------------------------------*/ + +satus.indexeddb.open('text-editor', { + files: { + indexes: [ + 'id', + 'time', + 'name' + ], + keyOptions: { + keyPath: 'id', + autoIncrement: true + } + }, + content: { + indexes: [ + 'id', + 'content' + ], + keyOptions: { + keyPath: 'id', + autoIncrement: false + } + }, + session: { + indexes: [ + 'id' + ], + keyOptions: { + keyPath: 'id' + } + }, + options: { + indexes: [ + 'key', + 'value' + ], + keyOptions: { + keyPath: 'key' + } + } +}, function () { + satus.indexeddb.get({ + session: {}, + options: {} + }, function (items) { + console.log('options', items); + + satus.locale.import(items.options.language, '../_locales/', function () { + satus.render(skeleton); + + if (items.session[0]) { + functions.openFile(items.session[0].id); + } + }); + }); +}); \ No newline at end of file diff --git a/ui/styles.css b/ui/styles.css new file mode 100644 index 0000000..371ea64 --- /dev/null +++ b/ui/styles.css @@ -0,0 +1,134 @@ +/*-------------------------------------------------------------- +>>> TEXT EDITOR +---------------------------------------------------------------- +# Body +# Menubar +# Textarea +# Footer +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# BODY +--------------------------------------------------------------*/ + +body { + --satus-contrast: 255, 255, 255; + --satus-menubar-background: #1a1f23; + --satus-menubar-text: #8a8f93; + --satus-menubar-hover: rgba(var(--satus-contrast), .1); + --satus-textarea-background: #2f3841; + --satus-textarea-color: #d8dee9; + --satus-footer-background: #1a1f23; + --satus-footer-text: #8a8f93; + --satus-main-background: #1a1f23; + --satus-main-text: #8a8f93; + --satus-modal-background: #1a1f23; + --satus-modal-text: #d8dee9; + --satus-text-field--background: #23292f; + --satus-text-field--border: #272e35; + --satus-text-field--text: #d8dee9; +} + + +/*-------------------------------------------------------------- +# MENUBAR +--------------------------------------------------------------*/ + +.satus-menubar { + z-index: 1; +} + + +/*-------------------------------------------------------------- +# SIDEBAR +--------------------------------------------------------------*/ + +.satus-sidebar { + width: 16px; + background: #1e2429; + overflow: hidden; + transition: 200ms; +} + +.satus-sidebar.empty { + width: 0; +} + +.page .satus-sidebar:not(.empty) { + width: 256px; +} + +.satus-sidebar:hover { + width: 256px; +} + +.satus-sidebar .satus-h1 { + display: block; + font-size: 15px; + font-weight: 700; + margin: 8px 16px; + text-transform: uppercase; +} + +.satus-sidebar .satus-ul { + display: block; + padding: 0; + list-style: none; +} + +.satus-sidebar li { + display: block; + font-size: 14px; + padding: 4px 16px; +} + +.satus-sidebar li.selected { + background: rgba(255,255,255,.05); +} + +.satus-sidebar li:hover { + background: rgba(var(--satus-contrast), .1); + cursor: pointer; +} + + +/*-------------------------------------------------------------- +# TEXTAREA +--------------------------------------------------------------*/ + +.satus-main { + flex: 1; + display: flex; +} + +.satus-textarea { + padding: 4px 0; + flex: 1; +} + + +/*-------------------------------------------------------------- +# FOOTER +--------------------------------------------------------------*/ + +.satus-footer { + font-size: 14px; + display: flex; + box-sizing: border-box; + height: 32px; + padding: 0 8px; + color: var(--satus-footer-text); + background: var(--satus-footer-background); + justify-content: space-between; + align-items: center; +} + +.satus-footer .satus-section> :not(:last-child)::after { + margin: 0 4px 0 0; + content: ','; +} + +.satus-footer .satus-section>*> :not(:last-child)::after { + margin: 0 4px 0 0; + content: ' '; +} \ No newline at end of file