├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── 1-bug-report.md │ └── 2-feature-request.md ├── PULL_REQUEST_TEMPLATE.md ├── hooks │ ├── commit-msg │ └── pre-commit ├── scripts │ └── setup_hooks.sh └── workflows │ ├── gh-pages.yml │ ├── publish.yml │ ├── quality-check.yml │ └── scripts │ ├── quality.sh │ └── replace_template.sh ├── .gitignore ├── .gitmodules ├── .lintstagedrc ├── .prettierignore ├── .prettierrc.json ├── .releaserc.yaml ├── .stylelintignore ├── .stylelintrc.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── angular.json ├── bun.lock ├── commitlint.config.js ├── cypress.config.ts ├── cypress └── support │ ├── commands.ts │ ├── component-index.html │ └── component.ts ├── eslint.config.js ├── package.json ├── postcss.config.js ├── projects └── ngx-copypaste-lib │ ├── ng-package.json │ ├── package.json │ ├── src │ ├── lib │ │ ├── ngx-copypaste.directive.spec.ts │ │ └── ngx-copypaste.directive.ts │ ├── public-api.ts │ ├── test.ts │ └── test │ │ ├── copy.cy-spec.ts │ │ └── utils │ │ └── cypress-test.component.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ └── tsconfig.spec.json ├── src ├── app │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── cards │ │ ├── cards.component.html │ │ ├── cards.component.scss │ │ ├── cards.component.ts │ │ ├── cards.enum.ts │ │ └── cards.type.ts │ └── shared │ │ └── copied │ │ ├── copied.component.html │ │ ├── copied.component.scss │ │ ├── copied.component.ts │ │ └── copied.path.ts ├── assets │ ├── .gitkeep │ ├── content │ │ ├── card.ts │ │ └── lists.ts │ └── images │ │ ├── content │ │ └── scroll-shadow.svg │ │ ├── open-source │ │ ├── accordion │ │ │ ├── options-active.svg │ │ │ ├── options.svg │ │ │ ├── white-chevron-down.svg │ │ │ ├── yellow-chevron-down.svg │ │ │ └── yellow-chevron-up.svg │ │ ├── cards │ │ │ ├── hand-box.svg │ │ │ └── input-vector.svg │ │ ├── footer │ │ │ └── all-rights-reserved.svg │ │ ├── header │ │ │ ├── burger.svg │ │ │ ├── close.svg │ │ │ ├── logo-white.svg │ │ │ └── logo.svg │ │ └── visit-btn │ │ │ └── button-chevron.svg │ │ └── shared │ │ ├── copied │ │ └── copied.svg │ │ └── github.svg ├── favicon.ico ├── index.html ├── main.ts └── styles.scss ├── tailwind.config.ts ├── tsconfig.app.json ├── tsconfig.eslint.json ├── tsconfig.json └── tsconfig.spec.json /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 2 | 3 | Please help us process issues more efficiently by filing an 4 | issue using one of the following templates: 5 | 6 | https://github.com/angular/angular/issues/new/choose 7 | 8 | Thank you! 9 | 10 | 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41E Bug report" 3 | about: Report a bug in the ngx-copypaste package 4 | --- 5 | 6 | 14 | 15 | # 🐞 bug report 16 | 17 | ### Is this a regression? 18 | 19 | 20 | Yes, the previous version in which this bug was not present was: .... 21 | 22 | ### Description 23 | 24 | A clear and concise description of the problem... 25 | 26 | ## 🔬 Minimal Reproduction 27 | 28 | 31 | https://stackblitz.com/... 32 | 33 | 42 | 43 | ## 🔥 Exception or Error 44 | 45 |

46 | 
47 | 
48 | 
49 | 
50 | 51 | ## 🌍 Your Environment 52 | 53 | **Angular Version:** 54 | 55 |

56 | 
57 | 
58 | 
59 | 
60 | 61 | **Anything else relevant?** 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature request" 3 | about: Suggest a feature for ngx-copypaste package 4 | --- 5 | 6 | 14 | 15 | # 🚀 feature request 16 | 17 | ### Description 18 | 19 | A clear and concise description of the problem or missing capability... 20 | 21 | ### Describe the solution you'd like 22 | 23 | If you have a solution in mind, please describe it. 24 | 25 | ### Describe alternatives you've considered 26 | 27 | Have you considered any alternative solutions or workarounds? 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## PR Checklist 2 | 3 | Please check if your PR fulfills the following requirements: 4 | 5 | - [ ] The commit message follows our guidelines: https://github.com/JsDaddy/ngx-copypaste/blob/develop/CONTRIBUTING.md#commit 6 | - [ ] Tests for the changes have been added (for bug fixes / features) 7 | - [ ] Docs have been added / updated (for bug fixes / features) 8 | 9 | ## PR Type 10 | 11 | What kind of change does this PR introduce? 12 | 13 | 14 | 15 | - [ ] Bugfix 16 | - [ ] Feature 17 | - [ ] Code style update (formatting, local variables) 18 | - [ ] Refactoring (no functional changes, no api changes) 19 | - [ ] Build related changes 20 | - [ ] CI related changes 21 | - [ ] Documentation content changes 22 | - [ ] Other... Please describe: 23 | 24 | ## What is the current behavior? 25 | 26 | 27 | 28 | Issue Number: N/A 29 | 30 | ## What is the new behavior? 31 | 32 | ## Does this PR introduce a breaking change? 33 | 34 | - [ ] Yes 35 | - [ ] No 36 | 37 | 38 | 39 | ## Other information 40 | -------------------------------------------------------------------------------- /.github/hooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | commit_msg=$(cat .git/COMMIT_EDITMSG) 6 | echo "$commit_msg" | bun commitlint 7 | -------------------------------------------------------------------------------- /.github/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | bun lint-staged 6 | 7 | # bun run snyk:test 8 | 9 | output=$(bun run type-coverage) 10 | if echo "$output" | grep -q "lower than "; then 11 | echo "$output" 12 | exit 1 # Terminate the hook script with a non-zero exit code 13 | else 14 | echo "Type coverage is good! 🎉" 15 | fi 16 | 17 | bun run test 18 | 19 | bun run cypress:bash 20 | 21 | bun run build 22 | 23 | bun run build:lib 24 | -------------------------------------------------------------------------------- /.github/scripts/setup_hooks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define the directory containing sample hooks 4 | SAMPLE_HOOKS_DIR=".github/hooks" 5 | 6 | # Define the target directory for Git hooks 7 | GIT_HOOKS_DIR=".git/hooks" 8 | 9 | # Function to copy or replace hooks 10 | copy_or_replace_hooks() { 11 | for hook in "$SAMPLE_HOOKS_DIR"/*; do 12 | hook_name=$(basename "$hook") 13 | target_hook="$GIT_HOOKS_DIR/$hook_name" 14 | if [ -f "$target_hook" ]; then 15 | echo "Replacing existing hook: $hook_name" 16 | else 17 | echo "Copying new hook: $hook_name" 18 | fi 19 | cp "$hook" "$target_hook" 20 | chmod ug+x "$target_hook" # Ensure executable permission is set 21 | done 22 | } 23 | 24 | # Main function 25 | main() { 26 | # Check if .git/hooks directory exists 27 | if [ ! -d "$GIT_HOOKS_DIR" ]; then 28 | echo "Error: .git/hooks directory not found. Are you in a Git repository?" 29 | exit 1 30 | fi 31 | 32 | # Copy or replace hooks 33 | copy_or_replace_hooks 34 | 35 | echo "Git hooks setup complete." 36 | } 37 | 38 | # Run the main function 39 | main 40 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: GitHub pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | submodules: true 17 | 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | 22 | - uses: oven-sh/setup-bun@v2 23 | with: 24 | bun-version: latest 25 | 26 | - name: Install deps 27 | run: | 28 | bun i 29 | 30 | - name: Semantic Release 31 | id: semantic-release 32 | env: 33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 34 | run: | 35 | npx semantic-release 36 | 37 | - name: Build demo app 38 | env: 39 | RELEASE_VERSION: ${{ steps.semantic-release.outputs.new-release-version }} 40 | run: | 41 | echo '********' 42 | echo "RELEASE_VERSION: $RELEASE_VERSION" 43 | echo '********' 44 | bash .github/workflows/scripts/replace_template.sh $RELEASE_VERSION 45 | bun run build 46 | - name: Deploy demo 47 | uses: peaceiris/actions-gh-pages@v4 48 | with: 49 | github_token: ${{ secrets.GITHUB_TOKEN }} 50 | publish_dir: ./dist/ngx-copypaste/browser 51 | outputs: 52 | version: ${{ steps.semantic-release.outputs.new-release-version }} 53 | 54 | slack_notification: 55 | needs: 56 | - build 57 | runs-on: ubuntu-latest 58 | steps: 59 | - name: Post to a Slack channel 60 | id: slack 61 | uses: slackapi/slack-github-action@v1.27.0 62 | with: 63 | channel-id: 'deployments' 64 | payload: | 65 | { 66 | "text": "GitHub Action build result: ${{ job.status == 'success' && ':white_check_mark:' || ':x:' }}", 67 | "blocks": [ 68 | { 69 | "type": "section", 70 | "text": { 71 | "type": "mrkdwn", 72 | "text": "GitHub Action build result: ${{ job.status == 'success' && ':white_check_mark:' || ':x:' }}" 73 | } 74 | }, 75 | { 76 | "type": "section", 77 | "text": { 78 | "type": "mrkdwn", 79 | "text": "Project: `${{ github.event.repository.name }}`" 80 | } 81 | }, 82 | { 83 | "type": "section", 84 | "text": { 85 | "type": "mrkdwn", 86 | "text": "Version: `${{ needs.build.outputs.version || 'TBA' }}`" 87 | } 88 | }, 89 | { 90 | "type": "section", 91 | "text": { 92 | "type": "mrkdwn", 93 | "text": "Commit/PR URL: ${{ github.event.pull_request.html_url || github.event.head_commit.url }}" 94 | } 95 | }, 96 | { 97 | "type": "section", 98 | "text": { 99 | "type": "mrkdwn", 100 | "text": "Website URL: ${{ secrets.WEBSITE_URL || 'TBA' }}" 101 | } 102 | } 103 | ] 104 | } 105 | env: 106 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} 107 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish bun 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | outputs: 12 | version: ${{ steps.get_version.outputs.version }} 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | submodules: true 17 | - uses: oven-sh/setup-bun@v2 18 | with: 19 | bun-version: latest 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: 20 23 | registry-url: 'https://registry.npmjs.org' 24 | - name: Build library 25 | run: | 26 | bun i 27 | bun run build:lib 28 | - name: Publish library 29 | run: bun run publish:lib 30 | env: 31 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 32 | - name: Extract version 33 | id: get_version 34 | run: | 35 | VERSION=$(node -p "require('./dist/ngx-copypaste-lib/package.json').version") 36 | echo "version=$VERSION" >> $GITHUB_OUTPUT 37 | 38 | slack_notification: 39 | needs: 40 | - build 41 | runs-on: ubuntu-latest 42 | steps: 43 | - name: Post to a Slack channel 44 | id: slack 45 | uses: slackapi/slack-github-action@v1.27.0 46 | with: 47 | channel-id: 'deployments' 48 | payload: | 49 | { 50 | "text": "GitHub Action build result: ${{ job.status == 'success' && ':white_check_mark:' || ':x:' }}", 51 | "blocks": [ 52 | { 53 | "type": "section", 54 | "text": { 55 | "type": "mrkdwn", 56 | "text": "GitHub Action build result: ${{ job.status == 'success' && ':white_check_mark:' || ':x:' }}" 57 | } 58 | }, 59 | { 60 | "type": "section", 61 | "text": { 62 | "type": "mrkdwn", 63 | "text": "Project: `${{ github.event.repository.name }}`" 64 | } 65 | }, 66 | { 67 | "type": "section", 68 | "text": { 69 | "type": "mrkdwn", 70 | "text": "Version: `${{ needs.build.outputs.version || 'TBA' }}`" 71 | } 72 | }, 73 | { 74 | "type": "section", 75 | "text": { 76 | "type": "mrkdwn", 77 | "text": "Commit/PR URL: ${{ github.event.pull_request.html_url || github.event.head_commit.url }}" 78 | } 79 | }, 80 | { 81 | "type": "section", 82 | "text": { 83 | "type": "mrkdwn", 84 | "text": "Website URL: ${{ secrets.NPM_PACKAGE_URL }}" 85 | } 86 | } 87 | ] 88 | } 89 | env: 90 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} 91 | -------------------------------------------------------------------------------- /.github/workflows/quality-check.yml: -------------------------------------------------------------------------------- 1 | name: build and quality 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | pull_request: 8 | branches: 9 | - develop 10 | 11 | env: 12 | snyk_token: ${{ secrets.SNYK_TOKEN }} 13 | REF: ${{ github.head_ref || github.ref_name }} 14 | 15 | jobs: 16 | quality-check: 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: write 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | submodules: true 24 | ref: ${{ env.REF }} 25 | - uses: oven-sh/setup-bun@v2 26 | with: 27 | bun-version: latest 28 | - uses: actions/setup-node@v4 29 | with: 30 | node-version: 20 31 | - name: Check quality 32 | run: | 33 | bun i 34 | bash .github/workflows/scripts/quality.sh 35 | -------------------------------------------------------------------------------- /.github/workflows/scripts/quality.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin 2 | 3 | set -e 4 | 5 | bun run lint 6 | 7 | # bun run snyk:auth -- $snyk_token 8 | # bun run snyk:test 9 | 10 | output=$(bun run type-coverage) 11 | if echo "$output" | grep -q "lower than "; then 12 | echo "$output" 13 | exit 1 # Terminate the hook script with a non-zero exit code 14 | else 15 | echo "Type coverage is good! 🎉" 16 | fi 17 | 18 | bun run test 19 | 20 | bun run cypress:bash 21 | 22 | bun run build 23 | 24 | bun run build:lib 25 | -------------------------------------------------------------------------------- /.github/workflows/scripts/replace_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the correct number of arguments are provided 4 | if [ $# -ne 1 ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | # Assign arguments to variables 10 | custom_string="$1" 11 | 12 | # Perform the replacement and save to output file 13 | sed "s/<%version%>/$custom_string/g" "angular.json" > "angular.json.tmp" && mv "angular.json.tmp" "angular.json" 14 | 15 | echo "Template string replaced successfully. 🎉" 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | /cypress/screenshots 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | 44 | .angular 45 | 46 | # Snyk 47 | .dccache 48 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/libraries"] 2 | path = src/libraries 3 | branch = main 4 | url = https://github.com/JsDaddy/libraries.git 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.{ts,js,json}": [ 3 | "eslint --report-unused-disable-directives --max-warnings 0 --fix", 4 | "prettier . --write" 5 | ], 6 | "*.scss": "stylelint --fix" 7 | } 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | ssl -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "semi": true, 6 | "bracketSpacing": true, 7 | "trailingComma": "es5", 8 | "bracketSameLine": true, 9 | "printWidth": 100, 10 | "endOfLine": "lf", 11 | "overrides": [ 12 | { 13 | "files": "*.html", 14 | "options": { 15 | "parser": "html" 16 | } 17 | }, 18 | { 19 | "files": "*.component.html", 20 | "options": { 21 | "parser": "angular" 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.releaserc.yaml: -------------------------------------------------------------------------------- 1 | branches: 2 | - develop 3 | 4 | plugins: 5 | - '@semantic-release/commit-analyzer' 6 | - '@semantic-release/github' 7 | - 'semantic-release-export-data' 8 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | # Compiled output 2 | /dist 3 | /tmp 4 | /out-tsc 5 | /bazel-out 6 | 7 | 8 | # Node 9 | /node_modules 10 | 11 | # IDEs and editors 12 | .idea/ 13 | 14 | # Visual Studio Code 15 | .vscode 16 | .history 17 | 18 | # Miscellaneous 19 | /.angular 20 | /coverage 21 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-recommended-scss"], 3 | "customSyntax": "postcss-scss", 4 | "plugins": ["stylelint-scss", "stylelint-prettier"], 5 | "rules": { 6 | "no-empty-source": null, 7 | "scss/comment-no-empty": null, 8 | "no-descending-specificity": null, 9 | "prettier/prettier": true, 10 | "selector-type-no-unknown": [ 11 | true, 12 | { 13 | "ignoreTypes": ["/^mat-/", "markdown", ":host", ":root"] 14 | } 15 | ], 16 | "scss/at-rule-no-unknown": [ 17 | true, 18 | { 19 | "ignoreAtRules": ["tailwind", "config"] 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 19.0.1(2025-04-29) 2 | 3 | ### Feature 4 | 5 | - update dependencies 6 | 7 | # 19.0.0(2024-11-21) 8 | 9 | ### Feature 10 | 11 | - update ng 19.x 12 | 13 | # 18.0.4(2024-10-25) 14 | 15 | ### Feature 16 | 17 | - add tailwind 18 | - change interface to type, remove prefix "I" 19 | - update dependencies 20 | - add ESLint strict rules 21 | 22 | # 17.3.2(2024-03-29) 23 | 24 | ### Feature 25 | 26 | - change decorators to signals 27 | 28 | 29 | 30 | # 17.0.0(2023-11-28) 31 | 32 | ### Feature 33 | 34 | - update ng 17.x 35 | 36 | 37 | 38 | # 16.0.1(2023-07-07) 39 | 40 | ### Feature 41 | 42 | - add success cb 43 | - update dependencies 44 | 45 | # 16.0.0(2023-07-07) 46 | 47 | ### Feature 48 | 49 | - update ng 16.x 50 | 51 | 52 | 53 | # 15.0.0(2022-25-12) 54 | 55 | ### Feature 56 | 57 | - ng 15 58 | 59 | 60 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Issues 4 | 5 | When submitting an issue, please include a reproducible case that we can actually run. Protractor has a test Angular application available at `http://www.protractortest.org/testapp` which you can use for the reproducible test case. If there's an error, please include the error text. 6 | 7 | Please format code and markup in your issue using [github markdown](https://help.github.com/articles/github-flavored-markdown). 8 | 9 | ## Contributing to Source Code (Pull Requests) 10 | 11 | - If your PR changes any behavior or fixes an issue, it should have an associated test. 12 | - New features should be general and as simple as possible. 13 | - Breaking changes should be avoided if possible. 14 | - All pull requests require review. No PR will be merged without a comment from a team member stating LGTM (Looks good to me). 15 | 16 | ## Protractor specific rules 17 | 18 | - JavaScript style should generally follow the [Google JS style guide](https://google.github.io/styleguide/javascriptguide.xml). 19 | - Document public methods with jsdoc. 20 | - Be consistent with the code around you! 21 | 22 | ## Commit Messages 23 | 24 | Please write meaningful commit messages - they are used to generate the changelog, so the commit message should tell a user everything they need to know about a commit. Protractor follows AngularJS's [commit message format](https://docs.google.com/a/google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.z8a3t6ehl060). 25 | 26 | In summary, this style is 27 | 28 | (): 29 | 30 | 31 | 32 | Where `` is one of [feat, fix, docs, refactor, test, chore, deps] and 33 | `` is a quick descriptor of the location of the change, such as cli, clientSideScripts, element. 34 | 35 | ## Testing your changes 36 | 37 | When you submit a PR, tests will also be run on the Continuous Integration environment 38 | through Travis. If your tests fail on Travis, take a look at the logs. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 JS Daddy 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

NGX COPYPASTE

3 |
4 | 5 |

6 | NGX COPYPASTE is the best directive to copy any content on any element 7 |

8 | 9 | [![CI](https://github.com/JsDaddy/ngx-copypaste/actions/workflows/quality-check.yml/badge.svg?branch=develop)](https://github.com/JsDaddy/ngx-copypaste/actions/workflows/main.yml) 10 | [![npm](https://img.shields.io/npm/v/ngx-copypaste.svg)](https://www.npmjs.com/package/ngx-copypaste) 11 | [![npm downloads](https://img.shields.io/npm/dt/ngx-copypaste.svg)](https://npmjs.org/ngx-copypaste) 12 | 13 | [![npm](https://img.shields.io/npm/dm/ngx-copypaste.svg)](https://www.npmjs.com/package/ngx-copypaste) 14 | 15 | [![GitHub contributors](https://img.shields.io/github/contributors/JSDaddy/ngx-copypaste.svg?style=flat)](https://github.com/JSDaddy/ngx-copypaste) 16 | 17 | [![GitHub stars](https://img.shields.io/github/stars/JSDaddy/ngx-copypaste.svg?label=GitHub%20Stars&style=flat)](https://github.com/JSDaddy/ngx-copypaste) 18 | 19 | You can also try our NGX MASK [check](https://www.npmjs.com/package/ngx-mask) it. 20 | You can also try our NGX LOADER INDICATOR [check](https://www.npmjs.com/package/ngx-loader-indicator) it. 21 | 22 | ### You can try live [demo](https://jsdaddy.github.io/ngx-copypaste/) with examples. 23 | 24 | ## Installing 25 | 26 | ## npm 27 | 28 | ```bash 29 | $ npm install --save ngx-copypaste 30 | ``` 31 | 32 | ## bun 33 | 34 | ```bash 35 | $ bun install --save ngx-copypaste 36 | ``` 37 | 38 | ## Quickstart if ngx-copypaste version >= 15.0.0 39 | 40 | Pay attention this version works for angular >= 14.0.0 41 | 42 | Import **ngx-copypaste** directive to your standalone component 43 | 44 | ```typescript 45 | @Component({ 46 | selector: 'ngx-component', 47 | templateUrl: './app.component.html', 48 | styleUrls: ['./app.component.scss'], 49 | standalone: true, 50 | imports: [ 51 | (...) 52 | NgxCopyPasteDirective, 53 | (...) 54 | ], 55 | }) 56 | export class AppComponent { 57 | (...) 58 | } 59 | ``` 60 | 61 | ## Quickstart if ngx-copypaste version < 15.0.0 62 | 63 | Pay attention this version works for angular < 15.0.0 64 | 65 | Import **ngx-copypaste** module in Angular app. 66 | 67 | ```typescript 68 | import {NgxCopyPasteModule} from 'ngx-copypaste' 69 | 70 | (...) 71 | 72 | @NgModule({ 73 | (...) 74 | imports: [ 75 | NgxCopyPasteModule 76 | ] 77 | (...) 78 | }) 79 | ``` 80 | 81 | #### Usage 82 | 83 | From input 84 | 85 | ```html 86 | 87 | 88 | 89 | ``` 90 | 91 | From any HTML tag 92 | 93 | ```html 94 |

Lorem ipsum

95 | 96 | 97 | ``` 98 | 99 | From complex div 100 | 101 | ```html 102 |
103 |

Lorem ipsum

104 |

105 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rutrum augue at ante 106 | sollicitudin posuere. Pellentesque congue consequat enim quis luctus. 107 |

108 |
109 |

Lorem ipsum

110 |
111 |
112 | 113 | 114 | ``` 115 | 116 | Also you can bind it to any tag 117 | 118 | ```html 119 |

Lorem ipsum

120 | 121 |

Copy

122 | ``` 123 | 124 | Output success cb 125 | 126 | ```html 127 |

Lorem ipsum

128 | 129 |

Copy

130 | 131 | public copy(): void { your code } 132 | ``` 133 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "schematics": { 6 | "@schematics/angular:component": { 7 | "style": "scss", 8 | "standalone": true, 9 | "changeDetection": "OnPush", 10 | "viewEncapsulation": "Emulated" 11 | }, 12 | "@schematics/angular:directive": { 13 | "standalone": true 14 | }, 15 | "@schematics/angular:pipe": { 16 | "standalone": true 17 | }, 18 | "@schematics/angular:application": { 19 | "strict": true 20 | } 21 | }, 22 | "projects": { 23 | "ngx-copypaste": { 24 | "root": "", 25 | "sourceRoot": "src", 26 | "projectType": "application", 27 | "prefix": "app", 28 | "architect": { 29 | "build": { 30 | "builder": "@angular-devkit/build-angular:application", 31 | "options": { 32 | "security": { "autoCsp": true }, 33 | "outputPath": "dist/ngx-copypaste", 34 | "browser": "src/main.ts", 35 | "index": "src/index.html", 36 | "tsConfig": "tsconfig.app.json", 37 | "assets": ["src/favicon.ico", "src/assets"], 38 | "styles": [ 39 | "node_modules/highlight.js/styles/github.css", 40 | "src/styles.scss" 41 | ], 42 | "scripts": [], 43 | "sourceMap": true, 44 | "optimization": false, 45 | "namedChunks": true 46 | }, 47 | "configurations": { 48 | "production": { 49 | "define": { 50 | "VERSION": "'<%version%>'" 51 | }, 52 | "budgets": [ 53 | { 54 | "type": "initial", 55 | "maximumWarning": "2mb", 56 | "maximumError": "2mb" 57 | }, 58 | { 59 | "type": "anyComponentStyle", 60 | "maximumWarning": "15kb", 61 | "maximumError": "15kb" 62 | } 63 | ], 64 | "outputHashing": "all" 65 | }, 66 | "development": { 67 | "optimization": false, 68 | "extractLicenses": false, 69 | "sourceMap": true 70 | } 71 | }, 72 | "defaultConfiguration": "production" 73 | }, 74 | "serve": { 75 | "builder": "@angular-devkit/build-angular:dev-server", 76 | "options": { 77 | "buildTarget": "ngx-copypaste:build" 78 | }, 79 | "configurations": { 80 | "production": { 81 | "buildTarget": "ngx-copypaste:build:production" 82 | } 83 | } 84 | }, 85 | "test": { 86 | "builder": "@angular-devkit/build-angular:web-test-runner", 87 | "options": { 88 | "tsConfig": "tsconfig.spec.json", 89 | "inlineStyleLanguage": "scss", 90 | "assets": [ 91 | "src/favicon.ico", 92 | "src/assets", 93 | "src/robots.txt", 94 | "src/sitemap.xml" 95 | ], 96 | "polyfills": ["zone.js", "zone.js/testing"], 97 | "styles": ["src/styles.scss"], 98 | "scripts": [] 99 | } 100 | }, 101 | "lint": { 102 | "builder": "@angular-eslint/builder:lint", 103 | "options": { 104 | "lintFilePatterns": ["**/*.js", "**/*.json", "**/*.ts", "**/*.html"] 105 | } 106 | } 107 | } 108 | }, 109 | "ngx-copypaste-lib": { 110 | "projectType": "library", 111 | "root": "projects/ngx-copypaste-lib", 112 | "sourceRoot": "projects/ngx-copypaste-lib/src", 113 | "prefix": "lib", 114 | "architect": { 115 | "build": { 116 | "builder": "@angular-devkit/build-angular:ng-packagr", 117 | "options": { 118 | "project": "projects/ngx-copypaste-lib/ng-package.json" 119 | }, 120 | "configurations": { 121 | "production": { 122 | "tsConfig": "projects/ngx-copypaste-lib/tsconfig.lib.prod.json" 123 | }, 124 | "development": { 125 | "tsConfig": "projects/ngx-copypaste-lib/tsconfig.lib.json" 126 | } 127 | }, 128 | "defaultConfiguration": "production" 129 | } 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'scope-empty': [2, 'never'], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress'; 2 | 3 | export default defineConfig({ 4 | projectId: 'qhyo66', 5 | component: { 6 | devServer: { 7 | framework: 'angular', 8 | bundler: 'webpack', 9 | }, 10 | specPattern: 'projects/ngx-copypaste-lib/src/test/**/*.cy-spec.ts', 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /cypress/support/commands.ts: -------------------------------------------------------------------------------- 1 | // for add commands 2 | import { mount } from 'cypress/angular'; 3 | 4 | Cypress.Commands.add('mount', mount); 5 | -------------------------------------------------------------------------------- /cypress/support/component-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ngx-Copypaste 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /cypress/support/component.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/component.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 commands.js using ES2015 syntax: 17 | import './commands'; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | 22 | import { mount } from 'cypress/angular'; 23 | 24 | // Augment the Cypress namespace to include type definitions for 25 | // your custom command. 26 | // Alternatively, can be defined in cypress/support/component.d.ts 27 | // with a at the top of your spec. 28 | declare global { 29 | // eslint-disable-next-line @typescript-eslint/no-namespace 30 | namespace Cypress { 31 | interface Chainable { 32 | mount: typeof mount; 33 | } 34 | } 35 | } 36 | 37 | Cypress.Commands.add('mount', mount); 38 | 39 | // Example use: 40 | // cy.mount(MyComponent) 41 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const globals = require('globals'); 3 | // Allows us to bring in the recommended core rules from eslint itself 4 | const eslint = require('@eslint/js'); 5 | 6 | // Allows us to use the typed utility for our config, and to bring in the recommended rules for TypeScript projects from typescript-eslint 7 | const tseslint = require('typescript-eslint'); 8 | 9 | // Allows us to bring in the recommended rules for Angular projects from angular-eslint 10 | const angular = require('angular-eslint'); 11 | 12 | const json = require('eslint-plugin-json'); 13 | 14 | const ignores = [ 15 | 'dist/', 16 | 'tmp/', 17 | 'out-tsc/', 18 | 'bazel-out/', 19 | 'node_modules/', 20 | '.idea/', 21 | '.vscode/', 22 | '.history/', 23 | '.angular/', 24 | 'coverage/', 25 | 'cypress/', 26 | 'coverage-ts/', 27 | 'package-lock.json', 28 | ]; 29 | 30 | // Export our config array, which is composed together thanks to the typed utility function from typescript-eslint 31 | module.exports = tseslint.config( 32 | { 33 | ignores, 34 | }, 35 | { 36 | // Everything in this config object targets our TypeScript files (Components, Directives, Pipes etc) 37 | files: ['**/*.ts'], 38 | extends: [ 39 | // Apply the recommended core rules 40 | eslint.configs.recommended, 41 | ...tseslint.configs.recommendedTypeChecked, 42 | ...tseslint.configs.strictTypeChecked, 43 | ...tseslint.configs.stylisticTypeChecked, 44 | ...angular.configs.tsRecommended, 45 | ], 46 | // Set the custom processor which will allow us to have our inline Component templates extracted 47 | // and treated as if they are HTML files (and therefore have the .html config below applied to them) 48 | processor: angular.processInlineTemplates, 49 | // Override specific rules for TypeScript files (these will take priority over the extended configs above) 50 | languageOptions: { 51 | parserOptions: { 52 | project: ['./tsconfig.eslint.json'], 53 | }, 54 | }, 55 | rules: { 56 | '@angular-eslint/directive-selector': [ 57 | 'error', 58 | { 59 | type: 'attribute', 60 | prefix: ['ngxCopyPaste', 'jsdaddy'], 61 | style: 'camelCase', 62 | }, 63 | ], 64 | '@angular-eslint/component-selector': [ 65 | 'error', 66 | { 67 | type: 'element', 68 | prefix: 'jsdaddy', 69 | style: 'kebab-case', 70 | }, 71 | ], 72 | '@typescript-eslint/consistent-type-definitions': ['error', 'type'], 73 | '@typescript-eslint/ban-ts-comment': ['error', { minimumDescriptionLength: 10 }], 74 | '@typescript-eslint/no-array-constructor': 'error', 75 | '@typescript-eslint/no-duplicate-enum-values': 'error', 76 | '@typescript-eslint/no-empty-object-type': 'error', 77 | '@typescript-eslint/no-extra-non-null-assertion': 'error', 78 | '@typescript-eslint/no-misused-new': 'error', 79 | '@typescript-eslint/no-namespace': 'error', 80 | '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', 81 | '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', 82 | '@typescript-eslint/no-non-null-assertion': 'error', 83 | '@typescript-eslint/no-this-alias': 'error', 84 | '@typescript-eslint/no-redundant-type-constituents': 'off', 85 | '@typescript-eslint/no-unnecessary-type-constraint': 'error', 86 | '@typescript-eslint/no-unsafe-declaration-merging': 'error', 87 | '@typescript-eslint/no-unused-expressions': 'error', 88 | '@typescript-eslint/no-useless-constructor': 'error', 89 | '@typescript-eslint/no-wrapper-object-types': 'error', 90 | '@typescript-eslint/prefer-as-const': 'error', 91 | '@typescript-eslint/prefer-namespace-keyword': 'error', 92 | '@typescript-eslint/triple-slash-reference': 'error', 93 | 'no-array-constructor': 'off', 94 | 'no-useless-constructor': 'off', 95 | 'no-return-await': 'error', 96 | 'no-useless-catch': 'error', 97 | 'no-unused-labels': 'error', 98 | 'no-unneeded-ternary': 'error', 99 | 'no-undefined': 'error', 100 | 'no-undef-init': 'error', 101 | 'no-regex-spaces': 'error', 102 | 'no-proto': 'error', 103 | 'no-new-wrappers': 'error', 104 | 'no-unused-private-class-members': 'error', 105 | 'no-invalid-regexp': 'error', 106 | curly: ['error', 'all'], 107 | '@typescript-eslint/no-explicit-any': 'off', 108 | '@typescript-eslint/adjacent-overload-signatures': 'error', 109 | 'no-console': ['warn'], 110 | '@typescript-eslint/explicit-member-accessibility': 'error', 111 | '@typescript-eslint/no-inferrable-types': ['error', { ignoreParameters: true }], 112 | 'no-unused-vars': 'off', 113 | 'no-duplicate-imports': 'off', 114 | '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], 115 | '@typescript-eslint/no-require-imports': 'error', 116 | '@typescript-eslint/no-invalid-void-type': 'error', 117 | '@typescript-eslint/indent': 0, 118 | '@typescript-eslint/member-delimiter-style': 0, 119 | '@typescript-eslint/no-var-requires': 0, 120 | '@typescript-eslint/no-use-before-define': 0, 121 | 'prefer-const': 1, 122 | 'prefer-spread': 1, 123 | 'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], 124 | '@typescript-eslint/naming-convention': [ 125 | 'error', 126 | { 127 | selector: 'interface', 128 | format: ['PascalCase'], 129 | custom: { 130 | regex: '^I[A-Z]', 131 | match: true, 132 | }, 133 | }, 134 | ], 135 | 'import/no-unresolved': 'off', 136 | 'import/no-extraneous-dependencies': 'off', 137 | 'import/prefer-default-export': 'off', 138 | 'no-underscore-dangle': 'off', 139 | 'class-methods-use-this': 'off', 140 | 'lines-between-class-members': 'off', 141 | 'no-return-assign': 'off', 142 | 'no-param-reassign': [ 143 | 'error', 144 | { 145 | props: false, 146 | }, 147 | ], 148 | '@typescript-eslint/array-type': 'error', 149 | '@typescript-eslint/consistent-type-assertions': [ 150 | 'error', 151 | { 152 | assertionStyle: 'as', 153 | }, 154 | ], 155 | 'no-plusplus': ['off'], 156 | '@typescript-eslint/unbound-method': 'off', 157 | 'import/no-cycle': 'off', 158 | 'import/extensions': 'off', 159 | '@typescript-eslint/no-unsafe-call': 'off', 160 | '@typescript-eslint/restrict-template-expressions': [ 161 | 'error', 162 | { 163 | allowNullish: true, 164 | allowNumber: true, 165 | }, 166 | ], 167 | }, 168 | }, 169 | { 170 | // Everything in this config object targets our HTML files (external templates, 171 | // and inline templates as long as we have the `processor` set on our TypeScript config above) 172 | files: ['**/*.html'], 173 | extends: [ 174 | // Apply the recommended Angular template rules 175 | ...angular.configs.templateRecommended, 176 | // Apply the Angular template rules which focus on accessibility of our apps 177 | ...angular.configs.templateAccessibility, 178 | ], 179 | rules: { 180 | '@angular-eslint/template/click-events-have-key-events': 'off', 181 | '@angular-eslint/template/interactive-supports-focus': 'off', 182 | }, 183 | }, 184 | { 185 | files: ['**/*.js'], 186 | extends: [eslint.configs.recommended], 187 | languageOptions: { 188 | sourceType: 'commonjs', 189 | globals: { 190 | ...globals.node, 191 | }, 192 | }, 193 | rules: {}, 194 | }, 195 | { 196 | files: ['**/*.json'], 197 | extends: [json.configs.recommended], 198 | rules: {}, 199 | } 200 | ); 201 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-copypaste", 3 | "description": "Awesome ngx copypaste directive", 4 | "version": "19.0.1", 5 | "license": "MIT", 6 | "keywords": [ 7 | "ng2-copypaste", 8 | "ngx-copypaste", 9 | "ng2", 10 | "ng", 11 | "angular-copypaste", 12 | "copypaste", 13 | "angular", 14 | "angular2", 15 | "angular2-clipboard", 16 | "ng2clipboard", 17 | "jsdaddy", 18 | "angular-clipboard", 19 | "clipboard", 20 | "angular2-clipboard", 21 | "ng2clipboard", 22 | "ng2-clipboard", 23 | "ngx-clipboard" 24 | ], 25 | "private": true, 26 | "scripts": { 27 | "ng": "ng", 28 | "start": "ng serve", 29 | "build": "ng build ngx-copypaste --base-href /ngx-copypaste/ --configuration production", 30 | "build:lib": "ng build --configuration production ngx-copypaste-lib && bun run copy-libdocs", 31 | "copy-libdocs": "cp README.md LICENSE dist/ngx-copypaste-lib", 32 | "publish:lib": "cd dist/ngx-copypaste-lib && bun publish", 33 | "test": "ng test", 34 | "test:pre-commit": "ng test --watch=false", 35 | "lint": "ng lint && bun run lint:scss", 36 | "lint:scss": "stylelint \"**/*.scss\"", 37 | "lint:scss:fix": "stylelint \"**/*.scss\" --fix", 38 | "init:git:hooks": ".github/scripts/setup_hooks.sh", 39 | "cypress:open": "cypress open", 40 | "cypress:bash": "npx cypress run --component", 41 | "lint:fix": "ng lint --fix && bun run lint:scss:fix", 42 | "prettier:fix": "npx prettier --write .", 43 | "type-coverage": "type-coverage", 44 | "snyk:auth": "snyk auth", 45 | "snyk:test": "snyk test && snyk code test" 46 | }, 47 | "repository": { 48 | "type": "git", 49 | "url": "https://github.com/JsDaddy/ngx-copypaste.git" 50 | }, 51 | "dependencies": { 52 | "@angular/animations": "19.2.9", 53 | "@angular/common": "19.2.9", 54 | "@angular/compiler": "19.2.9", 55 | "@angular/core": "19.2.9", 56 | "@angular/forms": "19.2.9", 57 | "@angular/platform-browser": "19.2.9", 58 | "@angular/platform-browser-dynamic": "19.2.9", 59 | "@angular/router": "^19.2.9", 60 | "highlight.js": "^11.11.1", 61 | "ngx-highlightjs": "^14.0.0", 62 | "ngxtension": "^5.0.0", 63 | "rxjs": "7.8.2", 64 | "snyk": "^1.1296.2" 65 | }, 66 | "devDependencies": { 67 | "@angular-devkit/build-angular": "19.2.10", 68 | "@angular-eslint/builder": "19.3.0", 69 | "@angular-eslint/eslint-plugin": "19.3.0", 70 | "@angular-eslint/eslint-plugin-template": "19.3.0", 71 | "@angular-eslint/schematics": "19.3.0", 72 | "@angular-eslint/template-parser": "19.3.0", 73 | "@angular/cli": "19.2.10", 74 | "@angular/compiler-cli": "19.2.9", 75 | "@angular/language-service": "19.2.9", 76 | "@commitlint/cli": "19.8.0", 77 | "@commitlint/config-conventional": "19.8.0", 78 | "@types/jasmine": "~5.1.7", 79 | "@types/node": "22.15.3", 80 | "@typescript-eslint/eslint-plugin": "^8.31.1", 81 | "@web/test-runner": "^0.20.1", 82 | "angular-eslint": "^19.3.0", 83 | "cypress": "^14.3.2", 84 | "eslint": "9.26.0", 85 | "eslint-config-prettier": "10.1.2", 86 | "eslint-plugin-import": "2.31.0", 87 | "eslint-plugin-json": "4.0.1", 88 | "eslint-plugin-prettier": "5.4.0", 89 | "jasmine-core": "5.7.1", 90 | "jasmine-spec-reporter": "7.0.0", 91 | "lint-staged": "15.5.1", 92 | "ng-packagr": "19.2.2", 93 | "npm-check-updates": "^18.0.1", 94 | "prettier": "3.5.3", 95 | "puppeteer": "^24.8.0", 96 | "semantic-release": "24.2.3", 97 | "semantic-release-export-data": "^1.1.0", 98 | "stylelint": "16.19.1", 99 | "stylelint-config-prettier": "9.0.5", 100 | "stylelint-config-recommended-scss": "14.1.0", 101 | "stylelint-prettier": "5.0.3", 102 | "type-coverage": "^2.29.7", 103 | "typescript": "5.8.3", 104 | "typescript-eslint": "^8.31.1", 105 | "tailwindcss": "^3.4.15", 106 | "bun-types": "^1.2.12", 107 | "postcss": "8.5.3", 108 | "postcss-nesting": "13.0.1", 109 | "cssnano": "7.0.6", 110 | "postcss-scss": "4.0.9" 111 | }, 112 | "typeCoverage": { 113 | "atLeast": 92, 114 | "ignoreObject": true, 115 | "ignoreAsAssertion": true, 116 | "ignoreTypeAssertion;": true, 117 | "strict": true, 118 | "suppressError": true, 119 | "reportSemanticError": true, 120 | "ignoreCatch": true, 121 | "ignoreFiles": [ 122 | "server/**/*.ts", 123 | "server.ts" 124 | ] 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-nesting': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | cssnano: { preset: 'default' }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-copypaste-lib", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-copypaste", 3 | "version": "19.0.1", 4 | "license": "MIT", 5 | "keywords": [ 6 | "ng2-copypaste", 7 | "ngx-copypaste", 8 | "ng2", 9 | "ng", 10 | "angular-copypaste", 11 | "copypaste", 12 | "angular", 13 | "angular2", 14 | "angular2-clipboard", 15 | "ng2clipboard", 16 | "jsdaddy", 17 | "angular-clipboard", 18 | "clipboard", 19 | "angular2-clipboard", 20 | "ng2clipboard", 21 | "ng2-clipboard", 22 | "ngx-clipboard" 23 | ], 24 | "author": "ngx-copypaste", 25 | "contributors": [ 26 | "ngx-copypaste" 27 | ], 28 | "homepage": "https://github.com/JsDaddy/ngx-copypaste", 29 | "repository": { 30 | "type": "git", 31 | "url": "git@github.com:JsDaddy/ngx-copypaste.git" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/JsDaddy/ngx-copypaste/issues" 35 | }, 36 | "peerDependencies": { 37 | "@angular/common": ">=14.0.0", 38 | "@angular/core": ">=14.0.0" 39 | }, 40 | "dependencies": { 41 | "tslib": "^2.3.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/lib/ngx-copypaste.directive.spec.ts: -------------------------------------------------------------------------------- 1 | describe('NgxCopyPasteDirective', () => { 2 | it('should create an instance', () => { 3 | void expect(1).toEqual(1); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/lib/ngx-copypaste.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, inject, output } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[ngxCopyPaste]', 5 | exportAs: 'copy,ngxCopy', 6 | standalone: true, 7 | }) 8 | export class NgxCopyPasteDirective { 9 | public successCb = output(); 10 | 11 | private readonly _elementRef = inject(ElementRef); 12 | 13 | private copyWithSelection(): void { 14 | let select: Selection | null = window.getSelection(); 15 | if (select) { 16 | select.removeAllRanges(); 17 | } 18 | const element = this._elementRef.nativeElement as HTMLElement; 19 | if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) { 20 | element.select(); 21 | } else { 22 | const range: Range = document.createRange(); 23 | range.selectNodeContents(element); 24 | select = window.getSelection(); 25 | if (select) { 26 | select.addRange(range); 27 | } 28 | } 29 | this.successCb.emit(); 30 | // eslint-disable-next-line @typescript-eslint/no-deprecated 31 | document.execCommand('copy'); 32 | } 33 | 34 | public async copy(): Promise { 35 | this.copyWithSelection(); 36 | try { 37 | if (typeof navigator.clipboard === 'undefined') { 38 | this.copyWithSelection(); 39 | return; 40 | } 41 | const element = this._elementRef.nativeElement as HTMLElement; 42 | const value = 43 | element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement 44 | ? element.value 45 | : element.textContent; 46 | if (!value) { 47 | return; 48 | } 49 | await navigator.clipboard.writeText(value.trim()); 50 | this.successCb.emit(); 51 | } catch (err) { 52 | // eslint-disable-next-line no-console 53 | console.error('Error copying content: ', err); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-copypaste-lib 3 | */ 4 | 5 | export * from './lib/ngx-copypaste.directive'; 6 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | import 'zone.js/testing'; 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { 5 | BrowserDynamicTestingModule, 6 | platformBrowserDynamicTesting, 7 | } from '@angular/platform-browser-dynamic/testing'; 8 | 9 | // First, initialize the Angular testing environment. 10 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { 11 | teardown: { destroyAfterEach: false }, 12 | }); 13 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/test/copy.cy-spec.ts: -------------------------------------------------------------------------------- 1 | import { CypressTestMaskComponent } from './utils/cypress-test.component'; 2 | 3 | describe('Test Date Hh:m0', () => { 4 | it('should return value from ctrl+V', () => { 5 | cy.mount(CypressTestMaskComponent); 6 | 7 | cy.get('#masked').type('testing').should('have.value', 'testing'); 8 | cy.get('#btn').click(); 9 | cy.get('#pre').should('have.text', 'true'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/src/test/utils/cypress-test.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormControl, ReactiveFormsModule } from '@angular/forms'; 3 | import { NgxCopyPasteDirective } from 'ngx-copypaste'; 4 | 5 | @Component({ 6 | selector: 'jsdaddy-open-source-test', 7 | standalone: true, 8 | imports: [ReactiveFormsModule, NgxCopyPasteDirective], 9 | template: ` 10 | 11 | 12 |
{{ copied }}
13 | `, 14 | }) 15 | export class CypressTestMaskComponent { 16 | public form: FormControl = new FormControl(''); 17 | 18 | public copied = false; 19 | public copy(): void { 20 | this.copied = true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": ["src/test.ts", "**/*.spec.ts", "src/test/**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /projects/ngx-copypaste-lib/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": ["jasmine"] 6 | }, 7 | "include": ["**/*.spec.ts", "**/*.d.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 | 9 | 10 | 11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | @apply block h-full; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | describe('AppComponent', () => { 2 | it('First test', () => { 3 | void expect(1).toEqual(1); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { HeaderComponent } from '@open-source/header/header.component'; 3 | import { LinkPath } from '@libraries/link/link.path'; 4 | import { SubHeaderComponent } from '@open-source/sub-header/sub-header.component'; 5 | import { CardsComponent } from './cards/cards.component'; 6 | import { ListItem } from '@open-source/accordion/content.types'; 7 | import { lists } from '../assets/content/lists'; 8 | import { AccordionComponent } from '@open-source/accordion/accordion.component'; 9 | import { CardItem } from './cards/cards.type'; 10 | import { FooterComponent } from '@open-source/footer/footer.component'; 11 | import { Card } from '../assets/content/card'; 12 | import { VersionToken } from '@libraries/version/version.token'; 13 | declare const VERSION: string; 14 | 15 | @Component({ 16 | selector: 'jsdaddy-open-source-root', 17 | templateUrl: './app.component.html', 18 | styleUrls: ['./app.component.scss'], 19 | standalone: true, 20 | imports: [ 21 | HeaderComponent, 22 | HeaderComponent, 23 | SubHeaderComponent, 24 | CardsComponent, 25 | AccordionComponent, 26 | FooterComponent, 27 | ], 28 | providers: [{ provide: VersionToken, useValue: VERSION }], 29 | }) 30 | export class AppComponent { 31 | public readonly card: CardItem[] = Card; 32 | public readonly githubMaskLink = LinkPath.NGX_COPYPASTE; 33 | public readonly lists: ListItem[] = lists; 34 | public readonly title = 'Ngx-Copypaste'; 35 | public readonly subtitle = 'A pure and awesome copy paste directive for Angular'; 36 | public readonly chips = [ 37 | 'Clipboard', 38 | 'Angular', 39 | 'Typescript', 40 | 'Ngx', 41 | 'Copypaste', 42 | 'AngularClipboard', 43 | ]; 44 | } 45 | -------------------------------------------------------------------------------- /src/app/cards/cards.component.html: -------------------------------------------------------------------------------- 1 | @for (card of cardDocs(); track card.id) { 2 |
9 |
10 | {{ card.header }} 11 |
12 |
13 |
14 |
15 | hand-box 20 | Usage 21 |
22 | Source code 25 |
26 |
27 |                         
28 |                         input-vector
29 |                     
30 |
31 |
32 |
33 |
34 | @switch (card.cardType) { 35 | @case (cardTypeInput) { 36 |
37 | 42 | 45 |
46 | } 47 | @case (cardTypeTextarea) { 48 |
49 | 53 | 56 |
57 | } 58 | @case (cardTypeSuccess) { 59 |
60 | 61 | 64 |
65 | } 66 | @case (card.text12 && cardTypeNone) { 67 | 68 | {{ card.text12 }} 69 | 70 | 71 | } 72 | @case (card.text14 && cardTypeNone) { 73 |
77 | {{ card.text18 }} 78 | {{ card.text14 }} 79 | {{ card.text16 }} 80 |
81 | 82 | } 83 | } 84 |
85 |
86 |
87 |
88 | } 89 | -------------------------------------------------------------------------------- /src/app/cards/cards.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | @apply flex flex-col gap-4 p-4 bg-full-white box-border border-t border-t-black/10 py-5 pl-[22px] pr-4; 3 | .input { 4 | @apply flex justify-between w-full h-[51px] text-full-white py-3 px-5 outline-none bg-black border-b-2px border-b-white rounded-10px gap-2.5 focus:border-b-yellow hover:border-b-yellow hover:bg-full-white/25 focus:bg-full-white/25; 5 | input, 6 | textarea { 7 | @apply placeholder:text-white/25 outline-none border-none w-full text-full-white bg-transparent resize-none; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/cards/cards.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, effect, ElementRef, inject, input, viewChildren } from '@angular/core'; 2 | import { NgOptimizedImage } from '@angular/common'; 3 | import { NgxCopyPasteDirective } from 'ngx-copypaste'; 4 | import { HighlightModule } from 'ngx-highlightjs'; 5 | import { AssetPipe } from '@libraries/asset/asset.pipe'; 6 | import { CardItem } from './cards.type'; 7 | import { CopiedComponent } from '../shared/copied/copied.component'; 8 | import { CardType } from './cards.enum'; 9 | import { ScrollService } from '@open-source/scroll/scroll.service'; 10 | import { OpenSourcePath } from '@open-source/path/open-source.path'; 11 | import { toSignal } from '@angular/core/rxjs-interop'; 12 | 13 | @Component({ 14 | selector: 'jsdaddy-open-source-cards', 15 | standalone: true, 16 | imports: [NgOptimizedImage, NgxCopyPasteDirective, HighlightModule, AssetPipe, CopiedComponent], 17 | providers: [ScrollService], 18 | templateUrl: './cards.component.html', 19 | styleUrls: ['./cards.component.scss'], 20 | }) 21 | export class CardsComponent { 22 | public cardDocs = input(); 23 | public cards = viewChildren>('cards', { 24 | read: ElementRef, 25 | }); 26 | 27 | public readonly openSourceCardsPath = OpenSourcePath.CARDS; 28 | public readonly cardTypeInput: CardType = CardType.INPUT; 29 | public readonly cardTypeTextarea: CardType = CardType.TEXTAREA; 30 | public readonly cardTypeNone: CardType = CardType.NONE; 31 | public readonly cardTypeSuccess: CardType = CardType.SUCCESS; 32 | 33 | private readonly scrollService = inject(ScrollService); 34 | public readonly activeCardId = toSignal(this.scrollService.activeCard$); 35 | 36 | public constructor() { 37 | effect(() => { 38 | this.scrollService.onScroll(this.cards()); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/cards/cards.enum.ts: -------------------------------------------------------------------------------- 1 | export const enum CardType { 2 | INPUT = 'Input', 3 | TEXTAREA = 'Textarea', 4 | NONE = 'Hidden', 5 | SUCCESS = 'Success', 6 | } 7 | -------------------------------------------------------------------------------- /src/app/cards/cards.type.ts: -------------------------------------------------------------------------------- 1 | import { CardType } from './cards.enum'; 2 | 3 | export type CardItem = { 4 | header: string; 5 | code: string; 6 | id: number; 7 | anchor: string; 8 | cardType: CardType; 9 | text12?: string; 10 | text14?: string; 11 | text16?: string; 12 | text18?: string; 13 | }; 14 | -------------------------------------------------------------------------------- /src/app/shared/copied/copied.component.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/app/shared/copied/copied.component.scss: -------------------------------------------------------------------------------- 1 | .active { 2 | &.copy-btn { 3 | @apply bg-black text-yellow border border-solid border-yellow; 4 | .active-text, 5 | .copy { 6 | @apply block; 7 | } 8 | 9 | .default-text { 10 | @apply hidden; 11 | } 12 | } 13 | } 14 | 15 | .non-active { 16 | &.copy-btn { 17 | @apply text-black hover:bg-yellow; 18 | .copy, 19 | .active-text { 20 | @apply hidden; 21 | } 22 | .default-text { 23 | @apply block; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/shared/copied/copied.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, DestroyRef, inject } from '@angular/core'; 2 | import { NgClass, NgOptimizedImage } from '@angular/common'; 3 | import { AssetPipe } from '@libraries/asset/asset.pipe'; 4 | import { SharedAssetPath } from './copied.path'; 5 | import { delay, of } from 'rxjs'; 6 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 7 | 8 | @Component({ 9 | selector: 'jsdaddy-open-source-copied-button', 10 | standalone: true, 11 | imports: [NgOptimizedImage, AssetPipe, NgClass], 12 | templateUrl: './copied.component.html', 13 | styleUrls: ['./copied.component.scss'], 14 | }) 15 | export class CopiedComponent { 16 | public readonly assetPath = SharedAssetPath.COPIED; 17 | public copyButtonClass = 'non-active'; 18 | 19 | private readonly destroyRef = inject(DestroyRef); 20 | 21 | public copyText(): void { 22 | this.copyButtonClass = 'active'; 23 | of({}) 24 | .pipe(delay(1000), takeUntilDestroyed(this.destroyRef)) 25 | .subscribe(() => { 26 | this.copyButtonClass = 'non-active'; 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/copied/copied.path.ts: -------------------------------------------------------------------------------- 1 | export const enum SharedAssetPath { 2 | COPIED = 'shared/copied', 3 | } 4 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JsDaddy/ngx-copypaste/360493a1a2ce52d84489b70b477a070f778e8542/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/content/card.ts: -------------------------------------------------------------------------------- 1 | import { CardItem } from '../../app/cards/cards.type'; 2 | import { CardType } from '../../app/cards/cards.enum'; 3 | 4 | export const Card: CardItem[] = [ 5 | { 6 | header: 'Input control', 7 | code: ``, 8 | id: 1, 9 | anchor: 'input', 10 | cardType: CardType.INPUT, 11 | }, 12 | { 13 | header: 'Textarea control', 14 | code: ``, 15 | id: 2, 16 | anchor: 'textarea', 17 | cardType: CardType.TEXTAREA, 18 | }, 19 | { 20 | header: 'Emit Success cb', 21 | code: ``, 22 | id: 5, 23 | anchor: 'success', 24 | cardType: CardType.SUCCESS, 25 | }, 26 | { 27 | header: 'Element own text', 28 | code: `

Lorem ipsum dolor sit amet consectetur adipisicing elit.

`, 29 | id: 3, 30 | anchor: 'element', 31 | cardType: CardType.NONE, 32 | text12: 'Lorem ipsum dolor sit amet consectetur adipisicing elit', 33 | }, 34 | { 35 | header: 'All text in element', 36 | cardType: CardType.NONE, 37 | code: `

Lorem ipsum

38 |

39 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam 40 | rutrum augue at ante sollicitudin posuere. Pellentesque congue 41 | consequat enim quis luctus. 42 |

43 |
44 |

Lorem ipsum

45 |
46 |
47 | `, 48 | id: 4, 49 | anchor: 'all-text', 50 | text18: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', 51 | text16: 'Pellentesque congue consequat enim quis luctus', 52 | text14: 'Nullam rutrum augue at ante sollicitudin posuere', 53 | }, 54 | ]; 55 | -------------------------------------------------------------------------------- /src/assets/content/lists.ts: -------------------------------------------------------------------------------- 1 | import { ListItem } from '@open-source/accordion/content.types'; 2 | 3 | export const lists: ListItem[] = [ 4 | { 5 | header: 'Controls', 6 | id: 1, 7 | defaultSvg: 'options', 8 | activeSvg: 'options-active', 9 | whiteChevron: 'white-chevron-down', 10 | yellowChevron: 'yellow-chevron-down', 11 | text: [ 12 | { 13 | content: 'Input control', 14 | id: 1, 15 | scrollTo: 'input', 16 | }, 17 | { 18 | content: 'Textarea control', 19 | id: 2, 20 | scrollTo: 'textarea', 21 | }, 22 | { 23 | content: 'Success function', 24 | id: 5, 25 | scrollTo: 'success', 26 | }, 27 | { 28 | content: 'Element own text', 29 | id: 3, 30 | scrollTo: 'element', 31 | }, 32 | { 33 | content: 'All text in element', 34 | id: 4, 35 | scrollTo: 'all-text', 36 | }, 37 | ], 38 | }, 39 | ]; 40 | -------------------------------------------------------------------------------- /src/assets/images/content/scroll-shadow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/assets/images/open-source/accordion/options-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/assets/images/open-source/accordion/options.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/assets/images/open-source/accordion/white-chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/open-source/accordion/yellow-chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/open-source/accordion/yellow-chevron-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/open-source/cards/hand-box.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/open-source/cards/input-vector.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/open-source/footer/all-rights-reserved.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/open-source/header/burger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/open-source/header/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/images/open-source/header/logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/assets/images/open-source/header/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/assets/images/open-source/visit-btn/button-chevron.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/shared/copied/copied.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/shared/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JsDaddy/ngx-copypaste/360493a1a2ce52d84489b70b477a070f778e8542/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ngx Copypaste | JsDaddy 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { provideExperimentalZonelessChangeDetection } from '@angular/core'; 2 | import { bootstrapApplication } from '@angular/platform-browser'; 3 | import { provideAnimations } from '@angular/platform-browser/animations'; 4 | import { HIGHLIGHT_OPTIONS } from 'ngx-highlightjs'; 5 | import { AppComponent } from './app/app.component'; 6 | import { provideRouter } from '@angular/router'; 7 | import { GithubStarsService } from '@libraries/github/github-stars.service'; 8 | import { provideHttpClient } from '@angular/common/http'; 9 | import { DOMAIN } from '@libraries/token/token'; 10 | import { BaseHttpService } from '@libraries/base-http/base-http.service'; 11 | 12 | bootstrapApplication(AppComponent, { 13 | providers: [ 14 | provideExperimentalZonelessChangeDetection(), 15 | provideAnimations(), 16 | provideRouter([]), 17 | GithubStarsService, 18 | provideHttpClient(), 19 | { 20 | provide: DOMAIN, 21 | useValue: [BaseHttpService], 22 | }, 23 | BaseHttpService, 24 | { 25 | provide: HIGHLIGHT_OPTIONS, 26 | useValue: { 27 | fullLibraryLoader: () => import('highlight.js'), 28 | }, 29 | }, 30 | ], 31 | }).catch((err: unknown) => { 32 | // eslint-disable-next-line no-console 33 | console.error(err); 34 | }); 35 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | @use './libraries/styles/scroll-bar'; 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import { type Config } from 'tailwindcss'; 2 | 3 | const tailwindConfig: Config = { 4 | content: ['./src/**/*.{html,scss,ts}'], 5 | theme: { 6 | extend: { 7 | screens: { 8 | mob: { min: '1px', max: '700px' }, 9 | tab: { min: '700px', max: '1279px' }, 10 | desk: { min: '1279px' }, 11 | }, 12 | fontFamily: { 13 | sans: ['Varela', 'system-ui', 'sans-serif'], 14 | }, 15 | colors: { 16 | dark: { 17 | DEFAULT: '#191919', 18 | }, 19 | yellow: { 20 | DEFAULT: '#FFD64D', 21 | }, 22 | green: { 23 | DEFAULT: '#1AB77E', 24 | }, 25 | orange: { 26 | DEFAULT: '#FF710A', 27 | }, 28 | 'full-white': '#FFFFFF', 29 | white: { 30 | DEFAULT: '#F8F8F8', 31 | }, 32 | }, 33 | spacing: { 34 | '5px': '5px', 35 | '15px': '15px', 36 | '30px': '30px', 37 | '35px': '35px', 38 | '50px': '50px', 39 | }, 40 | fontSize: { 41 | title: [ 42 | '10px', 43 | { 44 | lineHeight: '14px', 45 | fontWeight: '400', 46 | }, 47 | ], 48 | 'span-12': [ 49 | '12px', 50 | { 51 | lineHeight: '21px', 52 | fontWeight: '400', 53 | }, 54 | ], 55 | span: [ 56 | '14px', 57 | { 58 | lineHeight: '21px', 59 | fontWeight: '400', 60 | }, 61 | ], 62 | 'span-16': [ 63 | '16px', 64 | { 65 | lineHeight: '21px', 66 | fontWeight: '500', 67 | }, 68 | ], 69 | 'span-18': [ 70 | '18px', 71 | { 72 | lineHeight: '22px', 73 | fontWeight: '500', 74 | }, 75 | ], 76 | h3: [ 77 | '25px', 78 | { 79 | lineHeight: '27px', 80 | fontWeight: '500', 81 | }, 82 | ], 83 | h5: [ 84 | '16px', 85 | { 86 | lineHeight: '24px', 87 | fontWeight: '400', 88 | }, 89 | ], 90 | }, 91 | borderRadius: { 92 | '4px': '4px', 93 | '5px': '5px', 94 | '10px': '10px', 95 | '15px': '15px', 96 | '25px': '25px', 97 | }, 98 | borderWidth: { 99 | '2px': '2px', 100 | }, 101 | }, 102 | }, 103 | plugins: [], 104 | }; 105 | 106 | export default tailwindConfig; 107 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app" 5 | }, 6 | "files": ["src/main.ts"], 7 | "include": ["src/**/*.d.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "sourceMap": true, 9 | "declaration": false, 10 | "experimentalDecorators": true, 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "ES2022", 14 | "module": "ES2022", 15 | "lib": ["ES2022", "dom"], 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "noUncheckedIndexedAccess": true, 21 | "noImplicitOverride": true, 22 | "noPropertyAccessFromIndexSignature": true, 23 | "useUnknownInCatchVariables": true, 24 | "exactOptionalPropertyTypes": true, 25 | "useDefineForClassFields": false, 26 | "removeComments": true, 27 | "resolveJsonModule": true, 28 | "paths": { 29 | "@libraries/*": ["./src/libraries/*"], 30 | "@open-source/*": ["./src/libraries/open-source/*"], 31 | "ngx-copypaste": ["./projects/ngx-copypaste-lib/src/public-api"] 32 | }, 33 | "skipLibCheck": true, 34 | "noImplicitAny": true, 35 | "isolatedModules": true 36 | }, 37 | "angularCompilerOptions": { 38 | "strictStandalone": true, 39 | "enableI18nLegacyMessageIdFormat": false, 40 | "strictInjectionParameters": true, 41 | "strictInputAccessModifiers": true, 42 | "strictTemplates": true, 43 | "preserveWhitespaces": true, 44 | "fullTemplateTypeCheck": true, 45 | "extendedDiagnostics": { 46 | "checks": { 47 | "invalidBananaInBox": "error", 48 | "nullishCoalescingNotNullable": "warning", 49 | "unusedStandaloneImports": "error" 50 | }, 51 | "defaultCategory": "suppress" 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": ["jasmine"] 6 | }, 7 | "include": ["**/*.spec.ts"] 8 | } 9 | --------------------------------------------------------------------------------