├── .changeset └── config.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .gitattributes ├── .github └── workflows │ ├── lint.yml │ └── release.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .nojekyll ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc.cjs ├── .versionrc ├── LICENSE.md ├── README.md ├── apps └── site │ ├── .env.example │ ├── .eslintignore │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.cjs │ ├── .versionrc │ ├── CHANGELOG.md │ ├── docker-compose.yml │ ├── package.json │ ├── playwright.config.ts │ ├── postcss.config.cjs │ ├── src │ ├── app.css │ ├── app.d.ts │ ├── app.html │ ├── hooks.server.ts │ ├── lib │ │ ├── components │ │ │ ├── NavLink.svelte │ │ │ ├── examples │ │ │ │ ├── AdvancedPhoneInput.svelte │ │ │ │ ├── BasicPhoneInput.svelte │ │ │ │ └── EventDrivenPhoneInput.svelte │ │ │ └── utils │ │ │ │ ├── PayloadBlock.svelte │ │ │ │ ├── Seo.svelte │ │ │ │ └── SeoTypes.d.ts │ │ ├── index.ts │ │ ├── stores │ │ │ ├── DevExampleStores.ts │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── directives │ │ │ │ ├── clickOutsideAction.ts │ │ │ │ ├── focusAction.ts │ │ │ │ └── seoJsonLdAction.ts │ │ │ ├── examples │ │ │ │ └── exampleHelpers.ts │ │ │ ├── helpers.ts │ │ │ └── typeCheck.ts │ │ └── views │ │ │ ├── NewHeader.svelte │ │ │ ├── OptionsPanel.svelte │ │ │ ├── TheFooter.svelte │ │ │ ├── TheHeader.svelte │ │ │ ├── ThemeSwitch.svelte │ │ │ └── Usage.svelte │ └── routes │ │ ├── +layout.svelte │ │ ├── +layout.ts │ │ └── +page.svelte │ ├── static │ ├── demo.gif │ ├── favicon.ico │ └── robots.txt │ ├── svelte.config.js │ ├── tailwind.config.cjs │ ├── tsconfig.json │ └── vite.config.ts ├── commitlint.config.cjs ├── package.json ├── packages └── svelte-tel-input │ ├── .env.example │ ├── .eslintignore │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.cjs │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── postcss.config.cjs │ ├── scripts │ └── convertExamples.js │ ├── src │ ├── app.d.ts │ ├── app.html │ ├── lib │ │ ├── assets │ │ │ ├── allCountry.ts │ │ │ ├── examplePhoneNumbers.ts │ │ │ ├── flags_responsive.png │ │ │ └── index.ts │ │ ├── components │ │ │ └── input │ │ │ │ └── TelInput.svelte │ │ ├── index.ts │ │ ├── styles │ │ │ └── flags.css │ │ ├── types │ │ │ └── index.d.ts │ │ └── utils │ │ │ ├── directives │ │ │ ├── clickOutsideAction.ts │ │ │ ├── focusAction.ts │ │ │ └── telInputAction.ts │ │ │ ├── helpers.ts │ │ │ └── index.ts │ ├── next │ │ ├── assets │ │ │ ├── regions.ts │ │ │ └── telTypes.ts │ │ └── utils │ │ │ ├── helpers.ts │ │ │ └── typeCheck.ts │ └── tests │ │ ├── inputParserTest.spec.ts │ │ └── testnumbers.spec.json │ ├── svelte.config.js │ ├── tailwind.config.cjs │ ├── tsconfig.json │ └── vite.config.ts ├── playwright.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── changelog-github-custom.cjs ├── changelog-github-custom.js ├── changelog-github-custom.test.ts └── changelog-github-custom.ts └── static ├── demo.gif ├── favicon.ico └── robots.txt /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": ["../scripts/changelog-github-custom.cjs", { "repo": "gyurielf/svelte-tel-input" }], 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "bumpVersionsWithWorkspaceProtocolOnly": true, 11 | "ignore": ["!(@gyurielf/*|svelte-tel-input)"] 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: 2 | # This file is for unifying the coding style for different editors and IDEs. 3 | # More information at http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | indent_size = 4 10 | indent_style = tab 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | build 4 | .svelte-kit 5 | dist 6 | /docs 7 | .env 8 | .env.* 9 | !.env.example 10 | coverage 11 | **/dist/* 12 | 13 | # Ignore files for PNPM, NPM and YARN 14 | pnpm-lock.yaml 15 | package-lock.json 16 | yarn.lock 17 | 18 | # don't lint nyc coverage output 19 | coverage 20 | static 21 | 22 | # Utility and CI tools 23 | zarf 24 | scripts 25 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:svelte/recommended', 8 | 'prettier' 9 | ], 10 | plugins: ['@typescript-eslint', 'import'], 11 | ignorePatterns: ['*.cjs', '.temp/**/*'], 12 | overrides: [ 13 | { 14 | files: ['*.svelte'], 15 | parser: 'svelte-eslint-parser', 16 | parserOptions: { 17 | parser: '@typescript-eslint/parser' 18 | } 19 | } 20 | ], 21 | env: { 22 | browser: true, 23 | es2017: true, 24 | node: true 25 | }, 26 | rules: { 27 | 'svelte/no-at-html-tags': 'off', 28 | // 'import/extensions': [ 29 | // 'error', 30 | // 'always', 31 | // { 32 | // ignorePackages: true, 33 | // pattern: { 34 | // js: 'always', 35 | // ts: 'never' 36 | // } 37 | // } 38 | // ], 39 | 'no-restricted-imports': [ 40 | 'warn', 41 | { 42 | paths: [ 43 | { 44 | name: '.', 45 | message: 'Usage of local index imports is not allowed.' 46 | }, 47 | { 48 | name: './index', 49 | message: 'Import from the source file instead.' 50 | } 51 | ] 52 | } 53 | ], 54 | '@typescript-eslint/no-unused-vars': [ 55 | 'warn', // or "error" 56 | { 57 | argsIgnorePattern: '_', 58 | varsIgnorePattern: '_', 59 | caughtErrorsIgnorePattern: '_' 60 | } 61 | ], 62 | '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }] 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /app/** -linguist-detectable 2 | /**/*.svelte linguist-detectable -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: [push] 3 | permissions: 4 | contents: read # to fetch code (actions/checkout) 5 | jobs: 6 | lint-code: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 5 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: pnpm/action-setup@v4 12 | - uses: actions/setup-node@v4 13 | with: 14 | node-version: 18.x 15 | cache: pnpm 16 | - run: 'pnpm i && pnpm run sync && pnpm run package && pnpm run lint' 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | 8 | permissions: {} 9 | 10 | jobs: 11 | release: 12 | # prevents this action from running on forks 13 | if: github.repository == 'gyurielf/svelte-tel-input' 14 | permissions: 15 | contents: write # to create release (changesets/action) 16 | pull-requests: write # to create pull request (changesets/action) 17 | name: Release 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout Repo 21 | uses: actions/checkout@v4 22 | with: 23 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 24 | fetch-depth: 0 25 | - uses: pnpm/action-setup@v4 26 | with: 27 | version: 8.6.0 28 | - name: Setup Node.js 18.x 29 | uses: actions/setup-node@v4 30 | with: 31 | node-version: 18.x 32 | cache: pnpm 33 | 34 | - name: Install dependencies 35 | run: pnpm install --no-frozen-lockfile 36 | 37 | - name: Package 38 | run: pnpm package 39 | 40 | - name: Create Release Pull Request or Publish to npm 41 | id: changesets 42 | uses: changesets/action@v1 43 | with: 44 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 45 | publish: pnpm ci:release 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 49 | 50 | # TODO alert discord 51 | # - name: Send a Slack notification if a publish happens 52 | # if: steps.changesets.outputs.published == 'true' 53 | # # You can do something when a publish happens. 54 | # run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!" 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # svelte 12 | .svelte-kit 13 | 14 | # misc 15 | !.vscode/launch.json 16 | .vscode 17 | .DS_Store 18 | *.pem 19 | 20 | # debug 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # local env files 26 | .env 27 | .env.local 28 | .env.development.local 29 | .env.test.local 30 | .env.production.local 31 | !.env.example 32 | 33 | # vercel build output 34 | .vercel -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | currentBranch="$(git rev-parse --abbrev-ref HEAD)" 5 | 6 | # if [ "$currentBranch" = "main" ]; then 7 | # echo "You can't commit directly to main branch" 8 | # exit 1 9 | # fi 10 | 11 | # pnpm install ; pnpm run package ; pnpm install ; pnpm lint -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gyurielf/svelte-tel-input/cad0abb3775424ecda8d4860122c502be12828de/.nojekyll -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | auto-install-peers=true -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.15.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .svelte-kit 3 | node_modules 4 | /build 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js* 10 | apps/site/.vercel 11 | 12 | # Ignore files for PNPM, NPM and YARN 13 | pnpm-lock.yaml 14 | pnpm-workspace.yaml 15 | package-lock.json 16 | yarn.lock -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | trailingComma: 'none', 4 | printWidth: 100, 5 | tabWidth: 4, 6 | plugins: ['prettier-plugin-svelte'], 7 | overrides: [ 8 | { files: ['*.svelte'], options: { parser: 'svelte', bracketSameLine: false } }, 9 | { 10 | files: ['**/CHANGELOG.md'], 11 | options: { 12 | requirePragma: true 13 | } 14 | }, 15 | { 16 | files: ['README.md', 'packages/*/README.md'], 17 | options: { 18 | useTabs: false, 19 | tabWidth: 2 20 | } 21 | } 22 | ] 23 | }; 24 | -------------------------------------------------------------------------------- /.versionrc: -------------------------------------------------------------------------------- 1 | { 2 | "skip": { 3 | "tag": true 4 | }, 5 | "types": [ 6 | { 7 | "type": "chore", 8 | "section": "Others (chore)", 9 | "hidden": false 10 | }, 11 | { 12 | "type": "revert", 13 | "section": "Reverts", 14 | "hidden": false 15 | }, 16 | { 17 | "type": "feat", 18 | "section": "Features", 19 | "hidden": false 20 | }, 21 | { 22 | "type": "fix", 23 | "section": "Bug Fixes", 24 | "hidden": false 25 | }, 26 | { 27 | "type": "improvement", 28 | "section": "Feature Improvements", 29 | "hidden": false 30 | }, 31 | { 32 | "type": "docs", 33 | "section": "Docs", 34 | "hidden": false 35 | }, 36 | { 37 | "type": "style", 38 | "section": "Styling", 39 | "hidden": false 40 | }, 41 | { 42 | "type": "refactor", 43 | "section": "Code Refactoring", 44 | "hidden": false 45 | }, 46 | { 47 | "type": "perf", 48 | "section": "Performance Improvements", 49 | "hidden": false 50 | }, 51 | { 52 | "type": "test", 53 | "section": "Tests", 54 | "hidden": false 55 | }, 56 | { 57 | "type": "build", 58 | "section": "Build System", 59 | "hidden": false 60 | }, 61 | { 62 | "type": "ci", 63 | "section": "CI", 64 | "hidden": false 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 - Present Gyorgy Kallai, Budapest, Hungary. 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 | packages/svelte-tel-input/README.md -------------------------------------------------------------------------------- /apps/site/.env.example: -------------------------------------------------------------------------------- 1 | VITE_ENV_MODE=dev -------------------------------------------------------------------------------- /apps/site/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | build 4 | .svelte-kit 5 | dist 6 | /docs 7 | .env 8 | .env.* 9 | !.env.example 10 | coverage 11 | **/dist/* 12 | 13 | # Ignore files for PNPM, NPM and YARN 14 | pnpm-lock.yaml 15 | package-lock.json 16 | yarn.lock 17 | 18 | # don't lint nyc coverage output 19 | coverage 20 | static 21 | 22 | # Utility and CI tools 23 | zarf 24 | scripts 25 | -------------------------------------------------------------------------------- /apps/site/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:svelte/recommended', 8 | 'prettier' 9 | ], 10 | plugins: ['@typescript-eslint', 'import'], 11 | ignorePatterns: ['*.cjs', '.temp/**/*'], 12 | overrides: [ 13 | { 14 | files: ['*.svelte'], 15 | parser: 'svelte-eslint-parser', 16 | parserOptions: { 17 | parser: '@typescript-eslint/parser' 18 | } 19 | }, 20 | { 21 | files: ['*.test.ts'], 22 | rules: { 23 | '@typescript-eslint/no-restricted-imports': ['off'], 24 | 'no-restricted-imports': ['off'] 25 | } 26 | } 27 | ], 28 | parserOptions: { 29 | sourceType: 'module', 30 | ecmaVersion: 2020, 31 | extraFileExtensions: ['.svelte'] 32 | }, 33 | env: { 34 | browser: true, 35 | es2017: true, 36 | node: true 37 | }, 38 | globals: { $$Generic: 'readable' }, 39 | rules: { 40 | 'svelte/no-at-html-tags': 'off', 41 | // 'import/extensions': [ 42 | // 'error', 43 | // 'always', 44 | // { 45 | // ignorePackages: true, 46 | // js: 'always', 47 | // ts: 'never' 48 | // } 49 | // ], 50 | 'no-restricted-imports': [ 51 | 'warn', 52 | { 53 | paths: [ 54 | { 55 | name: '.', 56 | message: 'Usage of local index imports is not allowed.' 57 | }, 58 | { 59 | name: './index', 60 | message: 'Import from the source file instead.' 61 | } 62 | ] 63 | } 64 | ], 65 | // '@typescript-eslint/no-restricted-imports': [ 66 | // 'error', 67 | // { 68 | // patterns: [ 69 | // { 70 | // group: ['$app', '$app/*', '!./*', '!../*'], 71 | // message: 'Please only use RELATIVE import paths instead.' 72 | // } 73 | // ] 74 | // } 75 | // ], 76 | '@typescript-eslint/no-unused-vars': [ 77 | 'warn', // or "error" 78 | { 79 | argsIgnorePattern: '_', 80 | varsIgnorePattern: '_', 81 | caughtErrorsIgnorePattern: '_' 82 | } 83 | ], 84 | 'no-empty-function': 'off', 85 | '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }] 86 | } 87 | }; 88 | -------------------------------------------------------------------------------- /apps/site/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /dist 5 | /.svelte-kit 6 | /package 7 | .env 8 | .env.* 9 | !.env.example 10 | .vercel 11 | .output 12 | coverage 13 | .vscode 14 | /src/lib/exportGen.sh -------------------------------------------------------------------------------- /apps/site/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /dist 5 | /.svelte-kit 6 | /package 7 | /docs 8 | .env 9 | .env.* 10 | !.env.example 11 | CHANGELOG.md 12 | .changeset 13 | static 14 | /coverage 15 | 16 | # Ignore files for PNPM, NPM and YARN 17 | pnpm-lock.yaml 18 | package-lock.json 19 | yarn.lock 20 | 21 | # Utility and CI tools 22 | zarf 23 | scripts -------------------------------------------------------------------------------- /apps/site/.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | useTabs: true, 3 | singleQuote: true, 4 | trailingComma: 'none', 5 | printWidth: 100, 6 | tabWidth: 4, 7 | plugins: ['prettier-plugin-svelte'], 8 | overrides: [{ files: '*.svelte', options: { parser: 'svelte' } }] 9 | }; 10 | -------------------------------------------------------------------------------- /apps/site/.versionrc: -------------------------------------------------------------------------------- 1 | { 2 | "skip": { 3 | "tag": true 4 | }, 5 | "types": [ 6 | { 7 | "type": "chore", 8 | "section": "Others (chore)", 9 | "hidden": false 10 | }, 11 | { 12 | "type": "revert", 13 | "section": "Reverts", 14 | "hidden": false 15 | }, 16 | { 17 | "type": "feat", 18 | "section": "Features", 19 | "hidden": false 20 | }, 21 | { 22 | "type": "fix", 23 | "section": "Bug Fixes", 24 | "hidden": false 25 | }, 26 | { 27 | "type": "improvement", 28 | "section": "Feature Improvements", 29 | "hidden": false 30 | }, 31 | { 32 | "type": "docs", 33 | "section": "Docs", 34 | "hidden": false 35 | }, 36 | { 37 | "type": "style", 38 | "section": "Styling", 39 | "hidden": false 40 | }, 41 | { 42 | "type": "refactor", 43 | "section": "Code Refactoring", 44 | "hidden": false 45 | }, 46 | { 47 | "type": "perf", 48 | "section": "Performance Improvements", 49 | "hidden": false 50 | }, 51 | { 52 | "type": "test", 53 | "section": "Tests", 54 | "hidden": false 55 | }, 56 | { 57 | "type": "build", 58 | "section": "Build System", 59 | "hidden": false 60 | }, 61 | { 62 | "type": "ci", 63 | "section": "CI", 64 | "hidden": false 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /apps/site/CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gyurielf/svelte-tel-input/cad0abb3775424ecda8d4860122c502be12828de/apps/site/CHANGELOG.md -------------------------------------------------------------------------------- /apps/site/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | services: 3 | node: 4 | image: 'node:18.15-alpine3.17' 5 | container_name: mono-sti 6 | working_dir: /home/node/app 7 | command: 'sh -c "pnpm i && pnpm run prepare && pnpm run dev -- --host"' 8 | user: node 9 | tty: true 10 | ports: 11 | # Server 12 | - '3000:3000' 13 | # Vite 14 | - '24678:24678' 15 | volumes: 16 | - ./:/home/node/app 17 | -------------------------------------------------------------------------------- /apps/site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sti-examples", 3 | "description": "sti-examples", 4 | "version": "1.0.0", 5 | "private": true, 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/gyurielf/svelte-tel-input.git" 9 | }, 10 | "homepage": "https://github.com/gyurielf/svelte-tel-input#readme", 11 | "keywords": [ 12 | "svelte", 13 | "tel input", 14 | "phone", 15 | "phone input", 16 | "intl", 17 | "intl tel input" 18 | ], 19 | "engines": { 20 | "npm": ">= 8", 21 | "yarn": ">= 1", 22 | "node": ">= 16", 23 | "pnpm": ">= 8" 24 | }, 25 | "scripts": { 26 | "build": "vite build", 27 | "dev": "vite dev", 28 | "eslint": "eslint --ext .js,.ts,.svelte .", 29 | "eslint:fix": "eslint --fix", 30 | "lint": "npm run prettier:check && npm run eslint && npm run ts && npm run svelte-check", 31 | "lint:fix": "npm run eslint:fix && npm run prettier:fix", 32 | "preview": "vite preview", 33 | "sync": "svelte-kit sync", 34 | "test": "playwright test", 35 | "ts": "tsc --noEmit", 36 | "prettier:check": "prettier --check .", 37 | "prettier:fix": "prettier --write .", 38 | "svelte-check": "svelte-kit sync && svelte-check --ignore 'dist,build,coverage,.svelte-kit,package' --fail-on-warnings" 39 | }, 40 | "dependencies": { 41 | "svelte-tel-input": "workspace:*", 42 | "svelte": "^4.2.18" 43 | }, 44 | "devDependencies": { 45 | "@macfja/svelte-persistent-store": "^2.4.1", 46 | "@playwright/test": "^1.45.0", 47 | "@sveltejs/adapter-static": "^3.0.2", 48 | "@sveltejs/kit": "^2.5.17", 49 | "@sveltejs/vite-plugin-svelte": "^3.1.1", 50 | "@types/micromatch": "^4.0.8", 51 | "@typescript-eslint/eslint-plugin": "^7.14.1", 52 | "@typescript-eslint/parser": "^7.14.1", 53 | "autoprefixer": "^10.4.19", 54 | "cssnano": "^7.0.3", 55 | "dotenv": "^16.4.5", 56 | "eslint": "^8.57.0", 57 | "eslint-config-prettier": "^9.1.0", 58 | "eslint-plugin-svelte": "^2.41.0", 59 | "postcss": "^8.4.38", 60 | "prettier": "^3.3.2", 61 | "prettier-plugin-svelte": "^3.2.5", 62 | "schema-dts": "^1.1.2", 63 | "svelte-check": "^3.8.4", 64 | "svelte2tsx": "^0.7.13", 65 | "tailwindcss": "^3.4.4", 66 | "tslib": "^2.6.3", 67 | "typescript": "^5.5.2", 68 | "vite": "^5.3.1" 69 | }, 70 | "type": "module", 71 | "license": "MIT" 72 | } 73 | -------------------------------------------------------------------------------- /apps/site/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: 'npm run build && npm run preview', 6 | port: 4173 7 | }, 8 | testDir: 'tests' 9 | }; 10 | 11 | export default config; 12 | -------------------------------------------------------------------------------- /apps/site/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require('tailwindcss'); 2 | const autoprefixer = require('autoprefixer'); 3 | const cssnano = require('cssnano'); 4 | 5 | const mode = process.env.NODE_ENV; 6 | const dev = mode === 'development'; 7 | 8 | const config = { 9 | plugins: [ 10 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 11 | tailwindcss(), 12 | //But others, like autoprefixer, need to run after, 13 | autoprefixer(), 14 | !dev && 15 | cssnano({ 16 | preset: 'default' 17 | }) 18 | ] 19 | }; 20 | 21 | module.exports = config; 22 | -------------------------------------------------------------------------------- /apps/site/src/app.css: -------------------------------------------------------------------------------- 1 | /* Write your global styles here, in PostCSS syntax */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | -------------------------------------------------------------------------------- /apps/site/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare global { 5 | declare namespace App { 6 | // interface Error {} 7 | // interface Locals {} 8 | // interface PageData {} 9 | // interface Platform {} 10 | } 11 | } 12 | 13 | export {}; 14 | -------------------------------------------------------------------------------- /apps/site/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | %sveltekit.head% 28 | 29 | 30 | 33 |
%sveltekit.body%
34 | 35 | 36 | -------------------------------------------------------------------------------- /apps/site/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit'; 2 | 3 | export const handle: Handle = async ({ event, resolve }) => { 4 | return await resolve(event); 5 | }; 6 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/NavLink.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if external} 18 | 19 | {:else} 20 | 23 | {/if} 24 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/examples/AdvancedPhoneInput.svelte: -------------------------------------------------------------------------------- 1 | 100 | 101 |
106 |
107 | 144 | {#if isOpen} 145 | 194 | {/if} 195 |
196 | 197 | 207 |
208 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/examples/BasicPhoneInput.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | 52 | 53 | 64 |
65 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/examples/EventDrivenPhoneInput.svelte: -------------------------------------------------------------------------------- 1 | 42 | 43 |
44 | 70 | 71 | 85 | 93 |
94 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/utils/PayloadBlock.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | 68 | 69 | {#if isOpen} 70 |
74 | 75 |
76 |
77 | value 81 |
82 |
83 |
84 |
85 |

Key

86 |
value
87 |
88 |
89 |

Value

90 |
{value}
91 |
92 |
93 |
94 |

Payload

95 | {#key value} 96 |
"{value}"
97 | {/key} 98 |
99 | 100 |
101 |
102 |
103 | detailedValue 107 |
108 |
109 |
110 |
111 |

Key

112 | {#each exampleDataEntries as [key, _]} 113 |
{key}
114 | {/each} 115 |
116 |
117 |

Value

118 | {#each exampleDataEntries as [_, val]} 119 |
{val}
120 | {/each} 121 |
122 |
123 |
124 |

Payload

125 | {#key exampleData} 126 | {#if exampleData !== null} 127 |
132 | 					{:else}
133 | 						
"{exampleData}"
134 | {/if} 135 | {/key} 136 |
137 | 138 |
139 |
140 |
141 | valid 145 |
146 |
147 |
148 |
149 |

Key

150 |
valid
151 |
152 |
153 |

Value

154 |
{valid}
155 |
156 |
157 |
158 |

Payload

159 | {#key valid} 160 |
"{valid}"
161 | {/key} 162 |
163 | 164 |
165 |
166 |
167 | country 171 |
172 |
173 |
174 |
175 |

Key

176 |
country
177 |
178 |
179 |

Value

180 |
{country}
181 |
182 |
183 |
184 |

Payload

185 | {#key country} 186 |
"{country}"
187 | {/key} 188 |
189 |
190 | {/if} 191 |
192 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/utils/Seo.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | {#if title} 18 | {title} 19 | {/if} 20 | 21 | 25 | 29 | 30 | {#if description} 31 | 32 | {/if} 33 | 34 | {#if canonical} 35 | 36 | {/if} 37 | 38 | {#if openGraph} 39 | {#if openGraph.title} 40 | 41 | {/if} 42 | 43 | {#if openGraph.description} 44 | 45 | {/if} 46 | 47 | {#if openGraph.url || canonical} 48 | 49 | {/if} 50 | 51 | {#if openGraph.type} 52 | 53 | {/if} 54 | 55 | {#if openGraph.article} 56 | {#if openGraph.article.publishedTime} 57 | 58 | {/if} 59 | 60 | {#if openGraph.article.modifiedTime} 61 | 62 | {/if} 63 | 64 | {#if openGraph.article.expirationTime} 65 | 69 | {/if} 70 | 71 | {#if openGraph.article.section} 72 | 73 | {/if} 74 | 75 | {#if openGraph.article.authors && openGraph.article.authors.length} 76 | {#each openGraph.article.authors as author} 77 | 78 | {/each} 79 | {/if} 80 | 81 | {#if openGraph.article.tags && openGraph.article.tags.length} 82 | {#each openGraph.article.tags as tag} 83 | 84 | {/each} 85 | {/if} 86 | {/if} 87 | 88 | {#if openGraph.images && openGraph.images.length} 89 | {#each openGraph.images as image} 90 | 91 | {#if image.alt} 92 | 93 | {/if} 94 | {#if image.width} 95 | 96 | {/if} 97 | {#if image.height} 98 | 99 | {/if} 100 | {/each} 101 | {/if} 102 | {/if} 103 | 104 | {#if twitter} 105 | 106 | {#if twitter.site} 107 | 108 | {/if} 109 | {#if twitter.title} 110 | 111 | {/if} 112 | {#if twitter.description} 113 | 114 | {/if} 115 | {#if twitter.image} 116 | 117 | {/if} 118 | {#if twitter.imageAlt} 119 | 120 | {/if} 121 | {#if twitter.player} 122 | 123 | {/if} 124 | {#if twitter.playerWidth} 125 | 126 | {/if} 127 | {#if twitter.playerHeight} 128 | 129 | {/if} 130 | {/if} 131 | 132 | {#if jsonLd} 133 | 134 | {/if} 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /apps/site/src/lib/components/utils/SeoTypes.d.ts: -------------------------------------------------------------------------------- 1 | export interface OpenGraph { 2 | title?: string; 3 | description?: string; 4 | url?: string; 5 | type?: string; 6 | article?: OpenGraphArticle; 7 | images?: OpenGraphImage[]; 8 | } 9 | 10 | export interface OpenGraphArticle { 11 | publishedTime?: string; 12 | modifiedTime?: string; 13 | expirationTime?: string; 14 | section?: string; 15 | authors?: string[]; 16 | tags?: string[]; 17 | } 18 | 19 | export interface OpenGraphImage { 20 | url: string; 21 | alt?: string; 22 | width?: number | string; 23 | height?: number | string; 24 | } 25 | 26 | export interface Twitter { 27 | card?: TwitterCard; 28 | site?: string; 29 | title?: string; 30 | description?: string; 31 | image?: string; 32 | imageAlt?: string; 33 | player?: string; 34 | playerWidth?: string; 35 | playerHeight?: string; 36 | } 37 | 38 | export type TwitterCard = 'summary' | 'summary_large_image' | 'player'; 39 | -------------------------------------------------------------------------------- /apps/site/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export { clickOutsideAction } from './utils/directives/clickOutsideAction.js'; 2 | -------------------------------------------------------------------------------- /apps/site/src/lib/stores/DevExampleStores.ts: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | import { createLocalStorage, persist } from '@macfja/svelte-persistent-store'; 3 | import type { PersistentStore } from '@macfja/svelte-persistent-store'; 4 | import type { DetailedValue } from 'svelte-tel-input/types'; 5 | 6 | export const exampleDataStore = writable(); 7 | 8 | // Theme 9 | export const theme: PersistentStore = persist( 10 | writable(null), 11 | createLocalStorage(), 12 | 'theme' 13 | ); 14 | 15 | let preferedTheme: string | null = null; 16 | 17 | export const initTheme = () => { 18 | try { 19 | const unsubscribe = theme.subscribe((theme) => { 20 | preferedTheme = theme; 21 | }); 22 | unsubscribe(); 23 | } catch (error) { 24 | console.error(error); 25 | } 26 | }; 27 | 28 | export const toggleTheme = (): void => { 29 | initTheme(); 30 | 31 | const { classList } = document.querySelector('html') as HTMLElement; 32 | 33 | if (preferedTheme !== null) { 34 | classList.remove(preferedTheme); 35 | preferedTheme = null; 36 | } else { 37 | preferedTheme = 'dark'; 38 | classList.add(preferedTheme); 39 | } 40 | 41 | theme.update((newTheme) => { 42 | newTheme = preferedTheme; 43 | return newTheme; 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /apps/site/src/lib/stores/index.ts: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | // Watch variable changes. 4 | export const watcher = ( 5 | initialValue: string | null, 6 | watchFunction: (oldVal: string | null, newVal: string | null) => void 7 | ) => { 8 | const { subscribe, update } = writable(initialValue); 9 | return { 10 | subscribe, 11 | set: (value: string | null) => { 12 | update((oldvalue) => { 13 | watchFunction(oldvalue, value); 14 | return value; 15 | }); 16 | } 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/directives/clickOutsideAction.ts: -------------------------------------------------------------------------------- 1 | export const clickOutsideAction = ( 2 | node: HTMLElement, 3 | handler: () => void 4 | ): { destroy: () => void } => { 5 | const onClick = (event: MouseEvent) => 6 | node && !node.contains(event.target as HTMLElement) && !event.defaultPrevented && handler(); 7 | document.addEventListener('click', onClick, true); 8 | return { 9 | destroy() { 10 | document.removeEventListener('click', onClick, true); 11 | } 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/directives/focusAction.ts: -------------------------------------------------------------------------------- 1 | export function focusable_children(node: HTMLElement) { 2 | const nodes = Array.from( 3 | node.querySelectorAll( 4 | 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])' 5 | ) 6 | ); 7 | 8 | const index = document.activeElement ? nodes.indexOf(document.activeElement) : -1; 9 | 10 | const update = (d: number) => { 11 | let i = index + d; 12 | i += nodes.length; 13 | i %= nodes.length; 14 | 15 | // @ts-expect-error Element is not HTMLElement 16 | nodes[i].focus(); 17 | }; 18 | 19 | return { 20 | next: (selector: string) => { 21 | const reordered = [...nodes.slice(index + 1), ...nodes.slice(0, index + 1)]; 22 | 23 | for (let i = 0; i < reordered.length; i += 1) { 24 | if (!selector || reordered[i].matches(selector)) { 25 | // @ts-expect-error Element is not HTMLElement 26 | reordered[i].focus(); 27 | return; 28 | } 29 | } 30 | }, 31 | prev: (selector: string) => { 32 | const reordered = [...nodes.slice(index + 1), ...nodes.slice(0, index + 1)]; 33 | 34 | for (let i = reordered.length - 2; i >= 0; i -= 1) { 35 | if (!selector || reordered[i].matches(selector)) { 36 | // @ts-expect-error Element is not HTMLElement 37 | reordered[i].focus(); 38 | return; 39 | } 40 | } 41 | }, 42 | update 43 | }; 44 | } 45 | 46 | export function trap(node: HTMLElement) { 47 | const handle_keydown = (e: KeyboardEvent) => { 48 | if (e.key === 'Tab') { 49 | e.preventDefault(); 50 | 51 | const group = focusable_children(node); 52 | if (e.shiftKey) { 53 | // @ts-expect-error Element is not HTMLElement 54 | group.prev(); 55 | } else { 56 | // @ts-expect-error Element is not HTMLElement 57 | group.next(); 58 | } 59 | } 60 | }; 61 | 62 | node.addEventListener('keydown', handle_keydown); 63 | 64 | return { 65 | destroy: () => { 66 | node.removeEventListener('keydown', handle_keydown); 67 | } 68 | }; 69 | } 70 | 71 | // Put onto the element, where you want to use the keyboard navigation. 72 | // on:keydown={(e) => { 73 | // if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { 74 | // e.preventDefault(); 75 | // const group = focusable_children(e.currentTarget); 76 | // // when using arrow keys (as opposed to tab), don't focus buttons 77 | // const selector = 'a, input'; 78 | // if (e.key === 'ArrowDown') { 79 | // group.next(selector); 80 | // } else { 81 | // group.prev(selector); 82 | // } 83 | // } 84 | // }} 85 | // use:trap 86 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/directives/seoJsonLdAction.ts: -------------------------------------------------------------------------------- 1 | import type { Thing, WithContext } from 'schema-dts'; 2 | 3 | export const jsonLdScript = (node: HTMLScriptElement, jsonLd: (Thing | WithContext)[]) => { 4 | if (node) { 5 | node.type = 'application/ld+json'; 6 | node.text = JSON.stringify(jsonLd, null, 2); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/examples/exampleHelpers.ts: -------------------------------------------------------------------------------- 1 | import type { DetailedValue } from 'svelte-tel-input/types'; 2 | 3 | export const jsonPrettyParser = (node: HTMLElement, data: DetailedValue | null) => { 4 | data !== null && (node.innerHTML = `${JSON.stringify(data, null, 2)}`); 5 | return { 6 | destroy: () => { 7 | node.remove(); 8 | } 9 | }; 10 | }; 11 | 12 | export const cubeIn = ( 13 | node: HTMLElement, 14 | { rotateFrom, duration }: { rotateFrom: number; duration: number } 15 | ) => ({ 16 | duration, 17 | css: (t: number) => { 18 | const o = +getComputedStyle(node).opacity; 19 | 20 | return ` 21 | transform: translateZ(${-64 + t * 64}px) translateY(${-64 + t * 64}%) rotate3d(1, 0, 0, ${ 22 | rotateFrom - t * 90 23 | }deg); 24 | opacity: ${0.25 + t * o} 25 | `; 26 | } 27 | }); 28 | 29 | export const cubeOut = ( 30 | node: HTMLElement, 31 | { rotateTo, duration }: { rotateTo: number; duration: number } 32 | ) => ({ 33 | duration, 34 | css: (t: number) => { 35 | const o = +getComputedStyle(node).opacity; 36 | 37 | return ` 38 | transform: translateZ(${-64 + t * 64}px) translateY(${(1 - t) * 64}%) rotate3d(1, 0, 0, ${ 39 | (1 - t) * rotateTo 40 | }deg); 41 | opacity: ${0.25 + t * o} 42 | `; 43 | } 44 | }); 45 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/helpers.ts: -------------------------------------------------------------------------------- 1 | export const capitalize = (str: string) => { 2 | return (str && str[0].toUpperCase() + str.slice(1).toLowerCase()) || ''; 3 | }; 4 | 5 | export const isNumber = (value: number) => { 6 | return typeof value === 'number' && isFinite(value); 7 | }; 8 | -------------------------------------------------------------------------------- /apps/site/src/lib/utils/typeCheck.ts: -------------------------------------------------------------------------------- 1 | export const isStringArray = (items: unknown): items is string[] => { 2 | return Array.isArray(items) && items.length > 0 && typeof items[0] === 'string'; 3 | }; 4 | -------------------------------------------------------------------------------- /apps/site/src/lib/views/NewHeader.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
20 | 94 |
95 | -------------------------------------------------------------------------------- /apps/site/src/lib/views/OptionsPanel.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 |
14 | 57 | {#if isOpen} 58 |
62 |