{"id":28277136,"url":"https://github.com/squidit/ngx-css","last_synced_at":"2026-02-10T15:18:53.857Z","repository":{"id":190679484,"uuid":"683018716","full_name":"squidit/ngx-css","owner":"squidit","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-19T17:08:40.000Z","size":11392,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-19T22:42:07.542Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/squidit.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-08-25T12:02:52.000Z","updated_at":"2026-01-19T17:08:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"d76139f7-4e36-40ff-a9c1-060f033f93a9","html_url":"https://github.com/squidit/ngx-css","commit_stats":null,"previous_names":["squidit/ngx-css"],"tags_count":169,"template":false,"template_full_name":null,"purl":"pkg:github/squidit/ngx-css","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squidit%2Fngx-css","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squidit%2Fngx-css/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squidit%2Fngx-css/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squidit%2Fngx-css/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/squidit","download_url":"https://codeload.github.com/squidit/ngx-css/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squidit%2Fngx-css/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T13:02:32.985Z","status":"ssl_error","status_checked_at":"2026-01-28T13:02:04.945Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2025-05-21T06:14:50.321Z","updated_at":"2026-01-28T15:13:26.535Z","avatar_url":"https://github.com/squidit.png","language":"TypeScript","readme":"# NGX CSS - Library\n\n## About\n\n\u003e NGX CSS Framework An angular abstraction for [Squid CSS](https://github.com/squidit/css)\n\n## Table of contents\n\n- [Example](#example)\n- [Usage](#usage)\n  - [Install](#install)\n  - [Use Form Errors Variables](#use-form-errors-variables)\n  - [SqModalService](#sqmodalservice)\n  - [SqToastService](#sqtoastservice)\n- [Development](#development)\n  - [Write Documentation](#write-documentation)\n  - [Deploy to NPM](#deploy-to-npm)\n- [Documentation](#documentation)\n\n## Exemple\n\nSee an exemple of all components [here](https://css.squidit.com.br/styleguide)\n\n## Usage\n\n### Install\n\n1. Install\n\n```bash\nnpm install @squidit/css @squidit/ngx-css --save\n```\n\n2. Add `css` and `toast js` files to your `angular.json`\n\n```json\n{\n  // ...,\n  \"assets\": [\n    // This object inside assets Array\n    {\n      \"glob\": \"**/*\",\n      \"input\": \"./node_modules/@squidit/css/dist/fonts\",\n      \"output\": \"./assets/fonts\" // Output fonts\n    },\n    \"src/assets\" // Default assets\n  ],\n  \"styles\": [\n    \"src/styles.scss\"\n  ],\n  \"scripts\": [\n    \"node_modules/@squidit/css/src/js/components/toast.js\" // JS includes (legacy)\n  ]\n  // ...\n}\n```\n\n3. Add to your `style.scss` main file\n\n```scss\n$fontsFolderPath: '/assets/fonts'; // Overwrite default font path\n@import '@squidit/css/src/scss/squid.scss'; // Import all Framework Styles\n```\n\n4. Import `SquidCSSModule` in your `*.module.ts`\n\n```ts\nimport { SquidCSSModule } from '@squidit/ngx-css'\n\n@NgModule({\n  // ...\n  imports: [\n    // ...\n    NgxSquidModule\n  ]\n  // ...\n})\n```\n\n#### Use form erros variables\n\nTo use the errors handled in form components, you need to follow the steps below\n\n1. Install [ngx-translate](https://github.com/ngx-translate/core) and follow the initial Setup\n\n2. On you `.json` files from each language follow the same structure (need one for each supported language of your application):\n\n```json\n{\n  // ...\n  \"forms\": {\n    \"search\": \"Search\",\n    \"searchSelectEmpty\": \"There are no options to select\",\n    \"fileSize\": \"File too large\",\n    \"required\": \"Required field\",\n    \"minimumRequired\": \"The minimum number of selected tags must be greater than or equal to {{ minTags }}\",\n    \"email\": \"Invalid email\",\n    \"url\": \"Invalid URL. Attention: URL must start with https://\",\n    \"date\": \"Invalid Date\",\n    \"phone\": \"Invalid phone number\",\n    \"minValueAllowed\": \"Min value allowed is: {{ min }}\",\n    \"maxValueAllowed\": \"Max value allowed is: {{ max }}\",\n    \"rangeDate:\": \"Date outside valid range\"\n  }\n  // ...\n}\n```\n\n---\n\n### SqModalService\n\nService for programmatically opening Modal and Overlay dialogs. Fully testable, Observable-based, with proper memory management.\n\n#### Basic Usage\n\n```typescript\nimport { Component, inject } from '@angular/core';\nimport { SqModalService } from '@squidit/ngx-css';\n\n@Component({...})\nexport class MyComponent {\n  private modalService = inject(SqModalService);\n\n  openSimpleModal() {\n    this.modalService.openModal({\n      header: 'Confirm Action',\n      body: myBodyTemplate, // TemplateRef or Component\n      size: 'md'\n    }).subscribe(result =\u003e {\n      if (result) {\n        console.log('User confirmed!');\n      }\n    });\n  }\n}\n```\n\n#### Modal Configuration\n\n```typescript\ninterface SqModalConfig\u003cT = any\u003e {\n  id?: string;                    // Unique ID (auto-generated if not provided)\n  header?: string | TemplateRef;  // Header content (string = title)\n  body?: TemplateRef | Type\u003cany\u003e; // Body content (template or component)\n  footer?: TemplateRef;           // Footer content (template)\n  data?: T;                       // Data to pass to content\n  size?: 'sm' | 'md' | 'lg' | 'xl'; // Modal size (default: 'md')\n  backdrop?: 'static' | true;     // Backdrop behavior (default: 'static')\n  showCloseButton?: boolean;      // Show X button (default: true)\n  customClass?: string;           // Additional CSS classes\n  cancelText?: string;            // Cancel button text (default: 'Cancelar')\n  confirmText?: string;           // Confirm button text (default: 'Confirmar')\n  dataTest?: string;              // data-test attribute for testing\n}\n```\n\n#### Overlay Configuration\n\n```typescript\ninterface SqOverlayConfig\u003cT = any\u003e extends SqDialogConfig\u003cT\u003e {\n  direction?: 'left' | 'right' | 'top' | 'bottom'; // Slide direction (default: 'right')\n  width?: string;    // Custom width for left/right overlays\n  height?: string;   // Custom height for top/bottom overlays\n  borderless?: boolean;\n}\n```\n\n#### Opening with Templates\n\n```typescript\n@ViewChild('headerTemplate') headerTemplate!: TemplateRef\u003cany\u003e;\n@ViewChild('bodyTemplate') bodyTemplate!: TemplateRef\u003cany\u003e;\n@ViewChild('footerTemplate') footerTemplate!: TemplateRef\u003cany\u003e;\n\nopenModal() {\n  this.modalService.openModal({\n    header: this.headerTemplate,\n    body: this.bodyTemplate,\n    footer: this.footerTemplate,\n    data: { items: this.items }\n  });\n}\n```\n\n```html\n\u003cng-template #bodyTemplate let-modal let-data=\"data\"\u003e\n  \u003cul\u003e\n    @for (item of data.items; track item.id) {\n      \u003cli\u003e{{ item.name }}\u003c/li\u003e\n    }\n  \u003c/ul\u003e\n\u003c/ng-template\u003e\n\n\u003cng-template #footerTemplate let-modal let-data=\"data\"\u003e\n  \u003cbutton (click)=\"modal.close()\"\u003eCancel\u003c/button\u003e\n  \u003cbutton (click)=\"modal.close(data)\"\u003eSave\u003c/button\u003e\n\u003c/ng-template\u003e\n```\n\n#### Opening with Components\n\n```typescript\n// Content component\n@Component({\n  selector: 'app-my-content',\n  template: `\n    \u003ch3\u003e{{ title }}\u003c/h3\u003e\n    \u003cbutton (click)=\"dialogRef?.close({ saved: true })\"\u003eSave\u003c/button\u003e\n  `\n})\nexport class MyContentComponent {\n  @Input() title!: string;       // Receives from data\n  @Input() dialogRef?: SqDialogRef; // Auto-injected\n  \n  // Optional: provide header/footer templates\n  @ViewChild('headerTemplate') headerTemplate?: TemplateRef\u003cany\u003e;\n  @ViewChild('footerTemplate') footerTemplate?: TemplateRef\u003cany\u003e;\n}\n\n// Opening\nthis.modalService.openModal({\n  body: MyContentComponent,\n  data: { title: 'My Modal Title' }\n}).subscribe(result =\u003e {\n  if (result?.saved) {\n    console.log('Data was saved!');\n  }\n});\n```\n\n#### Opening an Overlay\n\n```typescript\nopenSidePanel() {\n  this.modalService.openOverlay({\n    direction: 'right',\n    width: '500px',\n    body: FilterPanelComponent,\n    data: { filters: this.currentFilters }\n  }).subscribe(result =\u003e {\n    if (result) {\n      this.applyFilters(result);\n    }\n  });\n}\n```\n\n#### Confirmation Before Close\n\nUse the `confirmBeforeClose` operator to prompt user before closing without saving:\n\n```typescript\nimport { confirmBeforeClose } from '@squidit/ngx-css';\n\nthis.modalService.openModal({\n  body: MyFormComponent,\n  data: { form: this.form }\n}).pipe(\n  confirmBeforeClose(() =\u003e {\n    // Return Observable\u003cboolean\u003e, Promise\u003cboolean\u003e, or boolean\n    return confirm('You have unsaved changes. Discard?');\n  })\n).subscribe(result =\u003e {\n  // Only reaches here if user confirms or saves\n});\n```\n\n#### Programmatic Control\n\n```typescript\nconst ref = this.modalService.openModal({...});\n\n// Close with result\nref.close({ success: true });\n\n// Close without result (cancel)\nref.close();\n\n// Update data in content component\nref.updateData({ loading: true });\n\n// Close all modals\nthis.modalService.closeAll();\n\n// Check open count\nconsole.log(this.modalService.openCount);\n```\n\n---\n\n### SqToastService\n\nService for displaying toast notifications. Observable-based, fully testable, with proper memory management and data-test attributes.\n\n#### Basic Usage\n\n```typescript\nimport { Component, inject } from '@angular/core';\nimport { SqToastService } from '@squidit/ngx-css';\n\n@Component({...})\nexport class MyComponent {\n  private toastService = inject(SqToastService);\n\n  showSuccess() {\n    this.toastService.success('Operation completed successfully!');\n  }\n\n  showError() {\n    this.toastService.error('Something went wrong.');\n  }\n}\n```\n\n#### Toast Types\n\n```typescript\n// Success (green)\nthis.toastService.success('Item saved!');\n\n// Error (red)\nthis.toastService.error('Failed to save item.');\n\n// Warning (yellow)\nthis.toastService.warning('This action cannot be undone.');\n\n// Info (blue)\nthis.toastService.info('New updates available.');\n\n// Default (gray)\nthis.toastService.default('Notification message.');\n```\n\n#### Toast Configuration\n\n```typescript\ninterface SqToastConfig {\n  type?: 'success' | 'error' | 'warning' | 'info' | 'default';\n  duration?: number;       // ms, 0 = persistent (default: 5000)\n  position?: SqToastPosition; // (default: 'top-right')\n  closeable?: boolean;     // Show close button (default: true)\n  showIcon?: boolean;      // Show type icon (default: false)\n  icon?: string;           // Custom icon class (FontAwesome)\n  dismissOnClick?: boolean; // Click toast to dismiss (default: false)\n  pauseOnHover?: boolean;  // Pause timer on hover (default: true)\n  action?: {               // Action button\n    label: string;\n    callback?: () =\u003e void;\n  };\n  customClass?: string;\n  dataTest?: string;       // data-test attribute\n  data?: any;              // Data for template messages\n}\n```\n\n#### Available Positions\n\n```typescript\ntype SqToastPosition =\n  | 'top-right'      // Default\n  | 'top-left'\n  | 'top-center'\n  | 'top-full'       // Full-width banner at top\n  | 'bottom-right'\n  | 'bottom-left'\n  | 'bottom-center'\n  | 'bottom-full';   // Full-width banner at bottom\n```\n\n#### With Action Button\n\n```typescript\nthis.toastService.success('Item deleted', {\n  duration: 8000,\n  action: {\n    label: 'Undo',\n    callback: () =\u003e this.undoDelete()\n  }\n});\n```\n\n#### Persistent Toast (Manual Dismiss)\n\n```typescript\nconst ref = this.toastService.warning('Processing...', {\n  duration: 0 // Never auto-dismiss\n});\n\n// Later, dismiss programmatically\nref.dismiss();\n```\n\n#### With Observable Lifecycle\n\n```typescript\nthis.toastService.info('Click me!', {\n  duration: 0,\n  dismissOnClick: true\n}).afterDismissed().subscribe(reason =\u003e {\n  // reason: 'timeout' | 'action' | 'manual' | 'swipe'\n  console.log('Toast dismissed by:', reason);\n});\n```\n\n#### Full-Width Banner\n\n```typescript\n// Top banner (like success notification)\nthis.toastService.success('Campaign created successfully!', {\n  position: 'top-full'\n});\n\n// Bottom banner\nthis.toastService.error('Connection lost', {\n  position: 'bottom-full'\n});\n```\n\n#### With Custom Template\n\n```typescript\n@ViewChild('customToast') customToast!: TemplateRef\u003cany\u003e;\n\nshowCustom() {\n  this.toastService.success(this.customToast, {\n    data: { userName: 'John', count: 5 }\n  });\n}\n```\n\n```html\n\u003cng-template #customToast let-ref let-data=\"data\"\u003e\n  \u003cstrong\u003e{{ data.userName }}\u003c/strong\u003e completed {{ data.count }} tasks!\n  \u003cbutton (click)=\"ref.dismiss()\"\u003eOK\u003c/button\u003e\n\u003c/ng-template\u003e\n```\n\n#### Global Operations\n\n```typescript\n// Dismiss all active toasts\nthis.toastService.dismissAll();\n\n// Get count of active toasts\nconsole.log(this.toastService.getActiveCount());\n```\n\n#### Unit Testing\n\n```typescript\nit('should show success toast', () =\u003e {\n  const toastSpy = spyOn(toastService, 'success').and.callThrough();\n  \n  component.save();\n  \n  expect(toastSpy).toHaveBeenCalledWith('Data saved!');\n});\n```\n\n#### E2E Testing (Cypress)\n\n```typescript\n// Find toast by data-test\ncy.get('[data-test=\"sq-toast-container\"]').should('exist');\ncy.get('[data-test=\"sq-toast-1\"]').should('contain', 'Success!');\ncy.get('[data-test=\"sq-toast-1-close\"]').click();\n```\n\n---\n\n## Development\n\n1. Install npm dependences `npm install`\n\n2. Run `npm start` to watch angular library (`src` directory)\n\n3. In another window run `start:application`\n\nThis launches an angular pattern that is contained in the application folder. Just use the components inside it, and every change in the files in the `src` folder will be automatically reflected in the application.\n\n### Write Documentation\n\nWe use [compodoc](https://github.com/compodoc/compodoc) to write docs with [jsDocs](https://jsdoc.app/)\n\nRun `start:docs` and the compodoc will serve the docs. For each change it is necessary to run the command again\n\n### Deploy to NPM\n\n\u003e Just draft a new release here on Github and an actions will starts\n\n**Important to use the same tag as package.json\n\n## Documentation\n\nSee Docs [here](https://ngx-css.squidit.com.br)\n","funding_links":[],"categories":["Development Utilities"],"sub_categories":["Styling"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquidit%2Fngx-css","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsquidit%2Fngx-css","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquidit%2Fngx-css/lists"}