├── CNAME ├── .babelrc ├── images ├── os-gui-favicon.png ├── os-gui-favicon.psd ├── os-gui-logo-wallpaper.psd ├── os-gui-logo-wallpaper-dark.png ├── os-gui-logo-wallpaper-light.png └── 98.js.svg ├── src ├── images │ └── titlebar-buttons.png ├── themes │ └── windows-default.theme ├── layout.css ├── blue.css ├── windows-default.css ├── peggys-pastels.css └── windows-98.css ├── .vscode ├── extensions.json └── settings.json ├── cypress ├── tsconfig.json ├── plugins │ └── index.js ├── support │ ├── e2e.ts │ └── commands.ts ├── fixtures │ ├── window-test-page.html │ └── menu-bar-test-page.html └── e2e │ ├── access-keys.cy.js │ └── menus.cy.js ├── cypress.config.ts ├── demo ├── index.html ├── animation.html ├── test.html ├── animation.js ├── physics-teaser.js └── demo.js ├── .gitattributes ├── .github └── workflows │ └── playwright.yml ├── $MenuBar.js ├── LICENSE ├── postcss.config.js ├── .gitignore ├── tests ├── tabstop-wrapping.spec.ts ├── access-keys.spec.js └── menus.spec.ts ├── playwright.config.ts ├── cspell.json ├── package.json ├── graphic-glitch.js ├── tsconfig.json └── parse-theme.js /CNAME: -------------------------------------------------------------------------------- 1 | os-gui.js.org -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "istanbul" 4 | ] 5 | } -------------------------------------------------------------------------------- /images/os-gui-favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/images/os-gui-favicon.png -------------------------------------------------------------------------------- /images/os-gui-favicon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/images/os-gui-favicon.psd -------------------------------------------------------------------------------- /images/os-gui-logo-wallpaper.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/images/os-gui-logo-wallpaper.psd -------------------------------------------------------------------------------- /src/images/titlebar-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/src/images/titlebar-buttons.png -------------------------------------------------------------------------------- /images/os-gui-logo-wallpaper-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/images/os-gui-logo-wallpaper-dark.png -------------------------------------------------------------------------------- /images/os-gui-logo-wallpaper-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1j01/os-gui/HEAD/images/os-gui-logo-wallpaper-light.png -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "csstools.postcss", 4 | "streetsidesoftware.code-spell-checker", 5 | "ms-playwright.playwright" 6 | ] 7 | } -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es5", 6 | "dom" 7 | ], 8 | "types": [ 9 | "cypress", 10 | "node" 11 | ] 12 | }, 13 | "include": [ 14 | "**/*.ts", 15 | "**/*.js" 16 | ] 17 | } -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | module.exports = (on, config) => { 2 | require('@cypress/code-coverage/task')(on, config); 3 | //used to instrument files included as unit tests 4 | on('file:preprocessor', require('@cypress/code-coverage/use-babelrc')); 5 | return config; 6 | }; 7 | -------------------------------------------------------------------------------- /cypress.config.ts: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('cypress') 2 | 3 | module.exports = defineConfig({ 4 | fixturesFolder: false, 5 | e2e: { 6 | setupNodeEvents(on, config) { 7 | return require('./cypress/plugins/index.js')(on, config) 8 | }, 9 | env: { 10 | codeCoverage: { 11 | exclude: 'cypress/**/*.*' 12 | } 13 | } 14 | }, 15 | }) -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Redirect 7 | 8 | 9 | 10 | 11 | 12 |

Demos are moved to the homepage.

13 | 14 | 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /src/themes/windows-default.theme: -------------------------------------------------------------------------------- 1 | 2 | [Control Panel\Colors] 3 | ActiveTitle=0 0 128 4 | Background=0 128 128 5 | Hilight=0 0 128 6 | HilightText=255 255 255 7 | TitleText=255 255 255 8 | Window=255 255 255 9 | WindowText=0 0 0 10 | Scrollbar=192 192 192 11 | InactiveTitle=128 128 128 12 | Menu=192 192 192 13 | WindowFrame=0 0 0 14 | MenuText=0 0 0 15 | ActiveBorder=192 192 192 16 | InactiveBorder=192 192 192 17 | AppWorkspace=128 128 128 18 | ButtonFace=192 192 192 19 | ButtonShadow=128 128 128 20 | GrayText=128 128 128 21 | ButtonText=0 0 0 22 | InactiveTitleText=192 192 192 23 | ButtonHilight=255 255 255 24 | ButtonDkShadow=0 0 0 25 | ButtonLight=192 192 192 26 | InfoText=0 0 0 27 | InfoWindow=255 255 225 28 | -------------------------------------------------------------------------------- /.github/workflows/playwright.yml: -------------------------------------------------------------------------------- 1 | name: Playwright Tests 2 | on: 3 | push: 4 | branches: [ main, master ] 5 | pull_request: 6 | branches: [ main, master ] 7 | jobs: 8 | test: 9 | timeout-minutes: 60 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: lts/* 16 | - name: Install dependencies 17 | run: npm ci 18 | - name: Install Playwright Browsers 19 | run: npx playwright install --with-deps 20 | - name: Run Playwright tests 21 | run: npx playwright test 22 | - uses: actions/upload-artifact@v4 23 | if: always() 24 | with: 25 | name: playwright-report 26 | path: playwright-report/ 27 | retention-days: 30 28 | -------------------------------------------------------------------------------- /cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/e2e.ts is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | import '@cypress/code-coverage/support'; 17 | 18 | // Import commands.js using ES2015 syntax: 19 | import './commands.ts'; 20 | 21 | // Alternatively you can use CommonJS syntax: 22 | // require('./commands') -------------------------------------------------------------------------------- /$MenuBar.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | console?.warn?.("$MenuBar.js is deprecated. Please use MenuBar.js instead. jQuery is no longer required for menu bars. For upgrading, see https://github.com/1j01/os-gui/blob/master/CHANGELOG.md"); 3 | 4 | // const script = document.createElement('script'); 5 | // script.src = document.currentScript.src.replace("$", ""); 6 | // document.head.appendChild(script); 7 | 8 | var xhr = new XMLHttpRequest(); 9 | // @ts-ignore 10 | xhr.open("GET", document.currentScript.src.replace("$", ""), false); 11 | xhr.send(); 12 | eval(xhr.responseText); 13 | 14 | /** @param {OSGUITopLevelMenus} menus */ 15 | function $MenuBar(menus) { 16 | console?.warn?.("$MenuBar is deprecated. Use `new MenuBar(menus).element` instead."); 17 | return jQuery(new MenuBar(menus).element); 18 | } 19 | 20 | exports.$MenuBar = $MenuBar; 21 | })(window); 22 | -------------------------------------------------------------------------------- /cypress/fixtures/window-test-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OS GUI — $Window component tests 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Isaiah Odhner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {('development'|'production'|string)} PostCSSEnv 3 | */ 4 | 5 | /** 6 | * @typedef {Object} PostCSSFile 7 | * @property {string} dirname 8 | * @property {string} basename 9 | * @property {string} extname 10 | */ 11 | 12 | /** 13 | * @typedef {Object} PostCSSOptions 14 | * @property {unknown} [map] 15 | * @property {unknown} [parser] 16 | * @property {unknown} [syntax] 17 | * @property {unknown} [stringifier] 18 | */ 19 | 20 | /** 21 | * @typedef {Object} PostCSSContext 22 | * @property {PostCSSEnv} env 23 | * @property {PostCSSFile} file 24 | * @property {PostCSSOptions} options 25 | */ 26 | 27 | /** 28 | * @typedef {Object} PostCSSConfig 29 | * @property {unknown} [map] 30 | * @property {unknown} [parser] 31 | * @property {Record} plugins 32 | */ 33 | 34 | /** 35 | * @param {PostCSSContext} ctx 36 | * @returns {PostCSSConfig} PostCSS configuration for a given file 37 | */ 38 | module.exports = (ctx) => ({ 39 | map: ctx.options.map, 40 | parser: ctx.options.parser, 41 | plugins: { 42 | precss: true, 43 | autoprefixer: true, 44 | "postcss-url": { url: "inline" }, 45 | // cssnano: ctx.env === "production" ? {} : false 46 | } 47 | }) 48 | -------------------------------------------------------------------------------- /cypress/support/commands.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // *********************************************** 3 | // This example commands.ts shows you how to 4 | // create various custom commands and overwrite 5 | // existing commands. 6 | // 7 | // For more comprehensive examples of custom 8 | // commands please read more here: 9 | // https://on.cypress.io/custom-commands 10 | // *********************************************** 11 | // 12 | // 13 | // -- This is a parent command -- 14 | // Cypress.Commands.add('login', (email, password) => { ... }) 15 | // 16 | // 17 | // -- This is a child command -- 18 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 19 | // 20 | // 21 | // -- This is a dual command -- 22 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 23 | // 24 | // 25 | // -- This will overwrite an existing command -- 26 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) 27 | // 28 | // declare global { 29 | // namespace Cypress { 30 | // interface Chainable { 31 | // login(email: string, password: string): Chainable 32 | // drag(subject: string, options?: Partial): Chainable 33 | // dismiss(subject: string, options?: Partial): Chainable 34 | // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable 35 | // } 36 | // } 37 | // } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # including build/ for demo for now, much simpler than setting up a deploy to gh-pages with built files included 2 | # TODO: publish to gh-pages branch, hopefully with a new Docusaurus site 3 | # build/ 4 | 5 | # ignore dist/ for future npm package structure 6 | # (Right now I have some files published at root (un-compiled), some in build/, 7 | # but dist/ is a better name since it doesn't imply all files are compiled) 8 | dist/ 9 | 10 | # Docusaurus build directory 11 | */build/ 12 | # Docusaurus temporary files 13 | .docusaurus/ 14 | 15 | # Istanbul test code coverage reports 16 | coverage/ 17 | 18 | # Cypress generates screenshots when tests fail 19 | cypress/screenshots/ 20 | 21 | # Playwright 22 | /test-results/ 23 | /playwright-report/ 24 | /blob-report/ 25 | /playwright/.cache/ 26 | 27 | # Logs 28 | logs 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | 34 | # Runtime data 35 | pids 36 | *.pid 37 | *.seed 38 | *.pid.lock 39 | 40 | # Directory for instrumented libs generated by jscoverage/JSCover 41 | lib-cov 42 | 43 | # Coverage directory used by tools like istanbul 44 | coverage 45 | 46 | # nyc test coverage 47 | .nyc_output 48 | 49 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 50 | .grunt 51 | 52 | # Bower dependency directory (https://bower.io/) 53 | bower_components 54 | 55 | # node-waf configuration 56 | .lock-wscript 57 | 58 | # Compiled binary addons (https://nodejs.org/api/addons.html) 59 | build/Release 60 | 61 | # Dependency directories 62 | node_modules/ 63 | jspm_packages/ 64 | 65 | # Typescript v1 declaration files 66 | typings/ 67 | 68 | # Optional npm cache directory 69 | .npm 70 | 71 | # Optional eslint cache 72 | .eslintcache 73 | 74 | # Optional REPL history 75 | .node_repl_history 76 | 77 | # Output of 'npm pack' 78 | *.tgz 79 | 80 | # Yarn Integrity file 81 | .yarn-integrity 82 | 83 | # dotenv environment variables file 84 | .env 85 | 86 | -------------------------------------------------------------------------------- /tests/tabstop-wrapping.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from '@playwright/test'; 2 | import { pathToFileURL } from 'node:url'; 3 | 4 | test.describe('tabstop wrapping', () => { 5 | // TODO: test `