{"id":17018246,"url":"https://github.com/zlatnaspirala/safir","last_synced_at":"2025-04-12T09:32:55.184Z","repository":{"id":60304543,"uuid":"542266942","full_name":"zlatnaspirala/safir","owner":"zlatnaspirala","description":"Lightweight JavaScript framework based on Template Literals vs CustomEvents features. Virtual DOM basic structure.","archived":false,"fork":false,"pushed_at":"2025-02-24T23:15:31.000Z","size":1826,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T10:45:56.952Z","etag":null,"topics":["alternative-frontends","high-performance","javascript","performance","rerender","virtual-dom"],"latest_commit_sha":null,"homepage":"https://maximumroulette.com/apps/safir/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zlatnaspirala.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-27T19:58:40.000Z","updated_at":"2025-02-24T23:15:28.000Z","dependencies_parsed_at":"2024-10-23T21:46:41.772Z","dependency_job_id":null,"html_url":"https://github.com/zlatnaspirala/safir","commit_stats":{"total_commits":39,"total_committers":2,"mean_commits":19.5,"dds":0.05128205128205132,"last_synced_commit":"0bb6301ccfa147ca420259e5f3f180bddaaae93c"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlatnaspirala%2Fsafir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlatnaspirala%2Fsafir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlatnaspirala%2Fsafir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlatnaspirala%2Fsafir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zlatnaspirala","download_url":"https://codeload.github.com/zlatnaspirala/safir/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248546322,"owners_count":21122293,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alternative-frontends","high-performance","javascript","performance","rerender","virtual-dom"],"created_at":"2024-10-14T06:45:08.186Z","updated_at":"2025-04-12T09:32:54.656Z","avatar_url":"https://github.com/zlatnaspirala.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SAFIR [1.1.20]\n\n### Tech: Based on ECMA6 programming paradigms builded on Template Literals, CustomEvents, Custom Tags.\n### Alternative software - High Performace\n\n![](https://github.com/zlatnaspirala/safir/blob/main/hello/assets/icons/192.png)\n\nSafir use `browserify` for building final pack script.\n\n## Objective:\n- Must be simple and usefull. Performace must be 100% with full PWA support.For any platform adapted.\n- Integrate account system using RocketCraftingServer [REST API].\n\n\n### There are two way for creating web components:\n - Safir Component\n - Vanilla component\n\n## NPM users\n There is no profesional documentation about safir so best way is to see examples from:\n - https://github.com/zlatnaspirala/safir\n - https://github.com/RocketCraftingServer/kickstart\n\n\n## Basic Example\n\n#### Main instance script\n\nIn main file use `app.loadComponent` to load your layout/component. After that use you imagination.\n\n```js\nimport { Safir, On } from \"safir\";\nimport MyHeader from \"./layouts/heder\";\nimport Layout from \"./layouts/body\";\n\nlet app  = new Safir();\napp.loadVanillaComp(\"vanilla-components/footer.html\");\n\nOn(\"app.ready\", () =\u003e {\n  let myHeader = app.loadComponent(new MyHeader('my-header'));\n  let myLayout = app.loadComponent(new Layout('my-layout'));\n  console.info(\"App running [ready]...\", Date.now());\n});\n\nconsole.info(\"App running [sync]...\", Date.now());\n```\n\nAfter in program you no need to use always `app.loadComponent` just use `this.mySubCom = new MYCOMP()` and put in render `${MYCOMP.renderById()}`.\n\nIn index.html header add:\n```html\n  \u003clink rel=\"stylesheet\" href=\"./style.css\"\u003e\n```\nIf you wanna use themes.\n\nAdd main dom holder:\n```html\n  \u003cdiv id=\"app\" class=\"theme-light app fill\"\u003e\u003c/div\u003e\n```\n\n## Create component from code\n\nSIMPLE BUTTON COMPONENT:\n```js\nimport {BaseComponent} from \"../../index\";\n\nexport default class SimpleBtn extends BaseComponent {\n\n  id = '';\n  text = '';\n  ready = () =\u003e {};\n\n  constructor(arg, arg2 = '') {\n    super(arg);\n    this.initial(arg, arg2);\n  }\n  onClick = this.clickBind;\n\n  render = () =\u003e `\n    \u003cbutton class=\"fill bg-transparent\" onclick=\"(${this.onClick})('${this.id}')\"\u003e\n      ${this.text}\n    \u003c/button\u003e\n  `;\n}\n\n```\n\nHow works app updates?\n\n[Recommended for end point components]\nWhen you create Safir Component use `class MyNewClass extends BaseComponent`.\nBaseComponent will handle situation. Safir have only function `set`\nfor updating class props. Calling the `set` function will cause a rerender\nand dispach event with `on-\u003cname_of_prop\u003e`.\n\nTo create props just add it normally intro class eg. `counter = 0'.\n\n```js\n  set(arg, newValue, extraData?)\n    - arg -\u003e name of prop eg. counter\n    - newValue -\u003e New value / what ever\n    - extraData -\u003e it is object with only `{ emit: true }`\n                   it is optimal arg.\n    [rerender]\n\n  Usage:\n  mySybCompBtnNoEmit.set('counter', newValue, { emit: false });\n\n  Catch it any where you want:\n  On('on-counter', (data) =\u003e {\n    console.info('[on-counter] Trigger Btn Yes [catched from body] ', data.detail);\n    let t = data.detail;\n    // Because we use multiply same component with also same prop name\n    // you can use `detail.emitter` to determinate by id who made dispach.\n    if (t.emitter === \"yes\") {\n      this.set('statusCounterYes', t.newValue);\n    } else if (t.emitter === \"no\") {\n      this.set('statusCounterNo', t.newValue);\n    }\n    // local tbn (no-emit) never emitted!\n  });\n\n```\n\n```json\nBest way is to use this function only for end component.\n```\n\n#### @Note About direct update [no rerender] Recommented\n\nRerender DOM method is ok for simple[pages] tasks. Safir need to handle massive or deep structure.\nIn that point rerendering is bad praticle.\nI use very simple checking in component for props then looking for DOMs whos have the same id [equal with propName].\n\nThis is most recemmended function for calling `setPropById`.\nTake a look at the demo3. \n\n```js\n  // LEVEL 0 - no storage / simple props\n  // After refresh default value will be used\n  this.myInput2.setPropById('value', r.detail.value);\n\n  // LEVEL 1 - sessionStorage level\n  // After refresh value comes from session storage\n  // but if you close browser tab or open in new one then default value will be used.\n  this.myInput2.setPropById('value', r.detail.value, 1);\n\n  // LEVEL 2 - localStorage level\n  // Even if you close browser tab you will get value from localStorage.\n  // YOU CAN DO RESET WITH CLEAR CACHE - ALSO IT IS A DOMAIN SHARED INFO\n  this.myInput2.setPropById('value', r.detail.value, 2);\n```\n\n## VANILLA COMPONENT\nWEB/HTML/JS/CSS (ecma6)\n\nIt is not focus on vanilla component but it is good to use any js code.\n\n - Perfect for async app flow.\n - Css is local scoped (loaded only when the vanilla component is loaded).\n \n```json\n  - Only role is `put tag \u003cscript\u003e after \u003cstyle\u003e and \u003chtml\u003e`\n```\n\n#### Style\n\nStyle can be used with props [from code].\nSafir use `scss` with themed integrated but don't include dev tools for it. You need to use Visual Code Exstension `Live Sass`.\n\nAdd intro `.vscode\\settings.json`\n```json\n{\n  \"liveSassCompile.settings.formats\": [{\n    \"format\": \"expanded\",\n    \"extensionName\": \".css\",\n    \"savePath\": \"/PREX_ROOT_FOLDER/dist\"\n  }],\n  \"liveSassCompile.settings.excludeList\": [\n    \"PREX_ROOT_FOLDER/test/**\",\n    \"**/node_modules/**\",\n    \".vscode/**\"\n  ]\n}\n```\n\nIf you use in VisualCode root folder of project no need for `PREX_ROOT_FOLDER`. If you put whole project intro prefix folder then add `PREX_ROOT_FOLDER/`. This folder must be intro root of visualCode workspace `.vscode\\` also can be autogenerated from VisualCode.\n\n### Help for ./test [using safir direct from npm service]\n\nIf you are using this git repo and you wanna use `Safir` from npm not from source then you need to change \nscss settings:\n```js\n{\n  \"liveSassCompile.settings.formats\": [{\n    \"format\": \"expanded\",\n    \"extensionName\": \".css\",\n    \"savePath\": \"/safir/dist/css/\"\n  }],\n  \"liveSassCompile.settings.excludeList\": [\n    \"**/node_modules/**\",\n    \".vscode/**\",\n    \"./dist/**\"\n  ]\n}\n```\n\n\n### Role:\n```json\n Any other (except scss) changes in assets/ folder need run `build-assets.sh`\n```\n\n## Hosting/build\n\nFor localhost (http) web server:\n```js\n  npm run host\n```\n\nFor localhost watch:\nRun watch:\n```js\n  npm run demo1\n```\n\nFor production (https) web server:\nRun command:\n```js\n  npm run build.demo1\n```\n\n## Build Library [option]\n\nIf you don't wanna use `npm service` or you dont wanna use `module type` and `compiling js` code\nthen you can build empty lib like javascript ES5 or ES6.\n```\n  \"build.lib\": \"browserify lib.js -p esmify \u003e dist/safir.lib.js\",\n```\n\nImport intro HTML direct:\n```html\n  \u003cscript defer src=\"safir.lib.js\"\u003e\u003c/script\u003e\n```\n\n## Adaptation\n\n - For codesandbox.\n \n Edit and contribute direct online:\n https://codesandbox.io/p/github/zlatnaspirala/safir/main?file=%2Fpackage.json\n\n\n## Links\n\nBasic examples:\n - Demo1.js [How to use? Create and update prop on click]\n   https://codepen.io/zlatnaspirala/pen/mdLzxoy\n - Demo2.js [How to use? Table data remove item from list on click]\n   https://codepen.io/zlatnaspirala/pen/eYrxgKz\n - Demo3.js [How to use? Use input tag with ]\n - demo4.js - TicTacToe game template :\n   https://maximumroulette.com/apps/safir/\n - demo5.js [How to use? Fetch for login (rocketCraftingServer)]\n - demo6.js - Slots mashine counter animator\n\n\n## Where is used\n\n   Kickstart is full standalone web app platform based on\n   Safir vs RocketCraftingServer.\n  - https://github.com/RocketCraftingServer/kickstart\n\n\n## Changes\n\n - from ver[1.2.17] new buildin plugin notify box.\n - from ver[1.1.20] fixed double call of ready() callback function.\n\n\n## Credits\n\n Used for css animation:\n -\u003e https://webcode.tools/generators/css/keyframe-animation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlatnaspirala%2Fsafir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzlatnaspirala%2Fsafir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlatnaspirala%2Fsafir/lists"}