├── .editorconfig
├── .ember-cli
├── .eslintignore
├── .eslintrc.js
├── .github
├── dependabot.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc.js
├── .template-lintrc.js
├── .watchmanconfig
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── RELEASE.md
├── addon
├── .gitkeep
└── components
│ ├── radio-button-input.hbs
│ ├── radio-button-input.js
│ ├── radio-button.hbs
│ └── radio-button.js
├── app
├── .gitkeep
└── components
│ ├── radio-button-input.js
│ └── radio-button.js
├── config
├── ember-try.js
└── environment.js
├── ember-cli-build.js
├── index.js
├── package.json
├── testem.js
├── tests
├── .eslintrc.js
├── dummy
│ ├── app
│ │ ├── app.js
│ │ ├── components
│ │ │ ├── .gitkeep
│ │ │ ├── aria-example.js
│ │ │ ├── autofocus-example.js
│ │ │ ├── basic-example.js
│ │ │ ├── disabled-example.js
│ │ │ ├── id-and-class-example.js
│ │ │ ├── legacy-actions-example.js
│ │ │ ├── object-value-example.js
│ │ │ ├── required-example.js
│ │ │ ├── tab-index-example.js
│ │ │ └── user-checked-class-example.js
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── index.html
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── resolver.js
│ │ ├── router.js
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── styles
│ │ │ └── app.css
│ │ └── templates
│ │ │ ├── application.hbs
│ │ │ ├── components
│ │ │ ├── .gitkeep
│ │ │ ├── aria-example.hbs
│ │ │ ├── autofocus-example.hbs
│ │ │ ├── basic-example.hbs
│ │ │ ├── disabled-example.hbs
│ │ │ ├── id-and-class-example.hbs
│ │ │ ├── object-value-example.hbs
│ │ │ ├── required-example.hbs
│ │ │ ├── tab-index-example.hbs
│ │ │ └── user-checked-class-example.hbs
│ │ │ └── index.hbs
│ ├── config
│ │ ├── ember-cli-update.json
│ │ ├── environment.js
│ │ ├── optional-features.json
│ │ └── targets.js
│ └── public
│ │ ├── crossdomain.xml
│ │ └── robots.txt
├── helpers
│ └── person.js
├── index.html
├── integration
│ ├── .gitkeep
│ └── components
│ │ └── radio-button-test.js
├── test-helper.js
└── unit
│ └── .gitkeep
├── vendor
└── .gitkeep
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 | indent_style = space
13 | indent_size = 2
14 |
15 | [*.hbs]
16 | insert_final_newline = false
17 |
18 | [*.{diff,md}]
19 | trim_trailing_whitespace = false
20 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 | /vendor/
4 |
5 | # compiled output
6 | /dist/
7 | /tmp/
8 |
9 | # dependencies
10 | /bower_components/
11 | /node_modules/
12 |
13 | # misc
14 | /coverage/
15 | !.*
16 | .*/
17 | .eslintcache
18 |
19 | # ember-try
20 | /.node_modules.ember-try/
21 | /bower.json.ember-try
22 | /package.json.ember-try
23 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | root: true,
5 | parser: 'babel-eslint',
6 | parserOptions: {
7 | ecmaVersion: 2018,
8 | sourceType: 'module',
9 | ecmaFeatures: {
10 | legacyDecorators: true,
11 | },
12 | },
13 | plugins: ['ember'],
14 | extends: [
15 | 'eslint:recommended',
16 | 'plugin:ember/recommended',
17 | 'plugin:prettier/recommended',
18 | ],
19 | env: {
20 | browser: true,
21 | },
22 | rules: {},
23 | overrides: [
24 | // node files
25 | {
26 | files: [
27 | './.eslintrc.js',
28 | './.prettierrc.js',
29 | './.template-lintrc.js',
30 | './ember-cli-build.js',
31 | './index.js',
32 | './testem.js',
33 | './blueprints/*/index.js',
34 | './config/**/*.js',
35 | './tests/dummy/config/**/*.js',
36 | ],
37 | parserOptions: {
38 | sourceType: 'script',
39 | },
40 | env: {
41 | browser: false,
42 | node: true,
43 | },
44 | plugins: ['node'],
45 | extends: ['plugin:node/recommended'],
46 | },
47 | {
48 | // Test files:
49 | files: ['tests/**/*-test.{js,ts}'],
50 | extends: ['plugin:qunit/recommended'],
51 | },
52 | ],
53 | };
54 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - commit-message:
4 | include: "scope"
5 | prefix: "chore"
6 | directory: "/"
7 | open-pull-requests-limit: 10
8 | package-ecosystem: "npm"
9 | schedule:
10 | interval: "weekly"
11 | time: "10:00"
12 | versioning-strategy: "increase"
13 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - master
8 | pull_request: {}
9 |
10 | concurrency:
11 | group: ci-${{ github.head_ref || github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | test:
16 | name: "Tests"
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - uses: actions/checkout@v2
21 | - name: Install Node
22 | uses: actions/setup-node@v2
23 | with:
24 | node-version: 12.x
25 | cache: yarn
26 | - name: Install Dependencies
27 | run: yarn install --frozen-lockfile
28 | - name: Lint
29 | run: yarn lint
30 | - name: Run Tests
31 | run: yarn test:ember
32 |
33 | floating:
34 | name: "Floating Dependencies"
35 | runs-on: ubuntu-latest
36 |
37 | steps:
38 | - uses: actions/checkout@v2
39 | - uses: actions/setup-node@v2
40 | with:
41 | node-version: 12.x
42 | cache: yarn
43 | - name: Install Dependencies
44 | run: yarn install --no-lockfile
45 | - name: Run Tests
46 | run: yarn test:ember
47 |
48 | try-scenarios:
49 | name: ${{ matrix.try-scenario }}
50 | runs-on: ubuntu-latest
51 | needs: "test"
52 |
53 | strategy:
54 | fail-fast: false
55 | matrix:
56 | try-scenario:
57 | - ember-lts-3.20
58 | - ember-lts-3.24
59 | - ember-lts-3.28
60 | - ember-release
61 | - ember-beta
62 | - ember-canary
63 | - ember-classic
64 | - embroider-safe
65 | - embroider-optimized
66 |
67 | steps:
68 | - uses: actions/checkout@v2
69 | - name: Install Node
70 | uses: actions/setup-node@v2
71 | with:
72 | node-version: 12.x
73 | cache: yarn
74 | - name: Install Dependencies
75 | run: yarn install --frozen-lockfile
76 | - name: Run Tests
77 | run: ./node_modules/.bin/ember try:one ${{ matrix.try-scenario }}
78 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist/
5 | /tmp/
6 |
7 | # dependencies
8 | /bower_components/
9 | /node_modules/
10 |
11 | # misc
12 | /.env*
13 | /.pnp*
14 | /.sass-cache
15 | /.eslintcache
16 | /connect.lock
17 | /coverage/
18 | /libpeerconnection.log
19 | /npm-debug.log*
20 | /testem.log
21 | /yarn-error.log
22 |
23 | # ember-try
24 | /.node_modules.ember-try/
25 | /bower.json.ember-try
26 | /package.json.ember-try
27 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist/
3 | /tmp/
4 |
5 | # dependencies
6 | /bower_components/
7 |
8 | # misc
9 | /.bowerrc
10 | /.editorconfig
11 | /.ember-cli
12 | /.env*
13 | /.eslintcache
14 | /.eslintignore
15 | /.eslintrc.js
16 | /.git/
17 | /.gitignore
18 | /.prettierignore
19 | /.prettierrc.js
20 | /.template-lintrc.js
21 | /.travis.yml
22 | /.watchmanconfig
23 | /bower.json
24 | /config/ember-try.js
25 | /CONTRIBUTING.md
26 | /ember-cli-build.js
27 | /testem.js
28 | /tests/
29 | /yarn-error.log
30 | /yarn.lock
31 | .gitkeep
32 |
33 | # ember-try
34 | /.node_modules.ember-try/
35 | /bower.json.ember-try
36 | /package.json.ember-try
37 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 | /vendor/
4 |
5 | # compiled output
6 | /dist/
7 | /tmp/
8 |
9 | # dependencies
10 | /bower_components/
11 | /node_modules/
12 |
13 | # misc
14 | /coverage/
15 | !.*
16 | .eslintcache
17 |
18 | # ember-try
19 | /.node_modules.ember-try/
20 | /bower.json.ember-try
21 | /package.json.ember-try
22 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | singleQuote: true,
5 | };
6 |
--------------------------------------------------------------------------------
/.template-lintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | extends: 'recommended',
5 | rules: {
6 | 'no-positive-tabindex': 'off',
7 | },
8 | overrides: [
9 | {
10 | files: ['tests/dummy/app/**/*.hbs'],
11 | rules: {
12 | 'no-inline-styles': 'off',
13 | 'require-input-label': 'off',
14 | },
15 | },
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## v3.0.0-beta.1 (2022-12-06)
3 |
4 | ## v3.0.0-beta.0 (2022-05-31)
5 |
6 | #### :boom: Breaking Change
7 | * [#119](https://github.com/yapplabs/ember-radio-button/pull/119) [BREAKING] Update dependencies, including ember-auto-import and add CI ([@lukemelia](https://github.com/lukemelia))
8 |
9 | #### Committers: 4
10 | - Gabriel Cousin ([@GabrielCousin](https://github.com/GabrielCousin))
11 | - Luke Melia ([@lukemelia](https://github.com/lukemelia))
12 | - Ray Cohen ([@raycohen](https://github.com/raycohen))
13 | - Will Bagby ([@bagby](https://github.com/bagby))
14 |
15 | ### 2.0.1
16 | - fix to use valid `aria-checked` attribute values
17 |
18 | ### 2.0.0
19 | - fixes `sendAction` deprecation warnings, using closure actions internally
20 | - removes support for Ember versions below 2.8
21 | - removes `labeled-radio-button` which was replaced by the block usage of `radio-button`
22 |
23 | ### 1.3.0
24 | - adds support for passing a closure action to the `changed` property
25 |
26 | ### 1.2.4
27 | - adds `aria-checked` attribute binding
28 |
29 | ### 1.2.3
30 | - adds `checkedClass` to override the default "checked" classname on the label when it is checked
31 |
32 | ### 1.2.2
33 | - adds `ariaDescribedby`
34 |
35 | ### 1.2.1
36 | - adds `ariaLabelledby`
37 |
38 | ### 1.2.0
39 | - README overhaul
40 | - adds `tabindex` and `autofocus`
41 | - use `Ember.isEqual` for comparison
42 | - updated examples in the test application to be implemented with components
43 | - fix for ember engine support
44 |
45 | ### 1.1.1
46 | - adds support for engines
47 | - Potential Breaking Change: The addon now uses templates from the addon folder.
48 | If you were supplying your own templates at the previous location
49 | (`app/templates/components/radio-button.hbs` for example)
50 | You will need to instead extend the provided component and explicitly
51 | supply your own template.
52 |
53 | ### 1.0.7
54 |
55 | - adds a `radioClass` property to put any classes you want on the input element
56 | - adds a `radioId` property to specify an id for the input element, allows
57 | associating non-wrapping label elements
58 |
59 | ### 1.0.6
60 |
61 | - Use `hasBlock` internally and remove deprecation warnings from
62 | accessing the component's `template` property
63 |
64 | ### 1.0.5
65 |
66 | - Improve IE8 Support
67 |
68 | ### 1.0.4
69 |
70 | - Fix putting additional classNames on the label
71 |
72 | ### 1.0.3
73 |
74 | - Put additional classNames on the label
75 |
76 | ### 1.0.2
77 |
78 | - Add `ember-radio-button` class to the label when used as a block
79 |
80 | ### 1.0.1
81 |
82 | - Put a `checked` classname on the label element when a block form
83 | radio-button is checked
84 |
85 | ### 1.0.0
86 |
87 | - Update to htmlbars
88 | - Rely on the `change` event, not `click`
89 | - Only `label` and `input` elements emitted, no more `span`
90 |
91 | ### 0.1.3
92 |
93 | - Add `required` and `name` bound attributes
94 |
95 | ### 0.1.2
96 |
97 | - Add `disabled` bound attribute
98 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-radio-button [](https://travis-ci.org/yapplabs/ember-radio-button) [](https://emberobserver.com/addons/ember-radio-button)
2 |
3 | This addon provides a `radio-button` component.
4 |
5 | A `radio-button` will be in a checked state when the `value` property matches the `groupValue` property.
6 | `value` should be unique per radio-button, while the same `groupValue` should be provided to each
7 | `radio-button` in the group.
8 |
9 | Clicking on a `radio-button` will set `groupValue` to its `value`.
10 |
11 | * Ember.js v3.20 or above
12 | * Ember CLI v3.20 or above
13 | * Node.js v12 or above
14 |
15 | ## Usage
16 | ### Block Form
17 |
18 | The block form emits a label wrapping the input element and any elements passed to the block.
19 |
20 | **Template:**
21 |
22 | ```javascript
23 |
28 | Blue
29 |
30 |
31 | /* results in */
32 |
33 |
34 | Blue
35 |
36 | ```
37 |
38 | ### Non-block form
39 |
40 | If you want more control over the DOM, the non-block form only emits a single input element
41 |
42 | ```javascript
43 |
49 |
50 | /* results in */
51 |
52 | ```
53 |
54 | ### Examples in the test application
55 |
56 | [More example usage](https://github.com/yapplabs/ember-radio-button/tree/master/tests/dummy/app/components) can be seen in the test application.
57 |
58 | ## Supported Ember Versions
59 |
60 | | ember-radio-button version | supports |
61 | | -------------------------- | ----------- |
62 | | 3.x | Ember 3.16+ |
63 | | 2.x | Ember 2.8+ |
64 | | 1.x | Ember 1.11+ |
65 |
66 | ## Properties
67 |
68 | _Required:_
69 |
70 | | name | type | description |
71 | | ---------- | ---- | ------------------------------------------------------------------------------------------------------------------- |
72 | | value | any | the unique value represented by the radio button |
73 | | groupValue | any | the value representing a radio group's current value. supply the same `groupValue` to every radio-button in a group |
74 |
75 | _Optional:_
76 |
77 | | name | type | description |
78 | | --------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- |
79 | | ariaDescribedby | string | applies an `aria-describedby` attribute to the input element |
80 | | ariaLabelledby | string | applies an `aria-labelledby` attribute to the input element |
81 | | autofocus | boolean | applies the `autofocus` property to the input element |
82 | | checkedClass | string | classname to apply to the `label` element when the input it wraps is checked. block form only. defaults to `"checked"` |
83 | | classNames | string | applies additional classnames to the `label` element (block form only) |
84 | | disabled | boolean | applies the `disabled` property to the input element |
85 | | name | string | applies the `name` property to the input element |
86 | | radioClass | string | applies additional classnames to the input element |
87 | | radioId | string | sets the `id` of the input element and the `for` property to the label element |
88 | | required | boolean | applies the `required` property to the input element |
89 | | tabindex | number | applies a `tabindex` property to the input element |
90 |
91 | _Actions:_
92 |
93 | | name | description |
94 | | ------- | ------------------------------------------------------------------------ |
95 | | changed | fires when user interaction causes a radio-button to update `groupValue` |
96 |
97 | ## Installing
98 |
99 | `ember install ember-radio-button`
100 |
101 | ## Legacy Action Support
102 |
103 | A string can be supplied for the `changed` property to enable legacy `sendAction` style action propagation.
104 |
105 | ## Older versions of ember
106 |
107 | ember-radio-button 1.0.0+ requires using htmlbars.
108 | Applications not using htmlbars should use version 0.1.3 or the `pre-htmlbars` branch.
109 |
110 | ## Collaborating on this repo
111 |
112 | - `git clone ` this repository
113 | - `cd ember-radio-button`
114 | - `npm install`
115 |
116 | ## Running
117 |
118 | - `ember serve`
119 | - Visit your app at [http://localhost:4200](http://localhost:4200).
120 |
121 | ## Running Tests
122 |
123 | - `npm test` (Runs `ember try:each` to test your addon against multiple Ember versions)
124 | - `ember test`
125 | - `ember test --server`
126 |
127 | ## Building
128 |
129 | - `ember build`
130 |
131 | For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).
132 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Release Process
2 |
3 | Releases are mostly automated using
4 | [release-it](https://github.com/release-it/release-it/) and
5 | [lerna-changelog](https://github.com/lerna/lerna-changelog/).
6 |
7 | ## Preparation
8 |
9 | Since the majority of the actual release process is automated, the primary
10 | remaining task prior to releasing is confirming that all pull requests that
11 | have been merged since the last release have been labeled with the appropriate
12 | `lerna-changelog` labels and the titles have been updated to ensure they
13 | represent something that would make sense to our users. Some great information
14 | on why this is important can be found at
15 | [keepachangelog.com](https://keepachangelog.com/en/1.0.0/), but the overall
16 | guiding principle here is that changelogs are for humans, not machines.
17 |
18 | When reviewing merged PR's the labels to be used are:
19 |
20 | * breaking - Used when the PR is considered a breaking change.
21 | * enhancement - Used when the PR adds a new feature or enhancement.
22 | * bug - Used when the PR fixes a bug included in a previous release.
23 | * documentation - Used when the PR adds or updates documentation.
24 | * internal - Used for internal changes that still require a mention in the
25 | changelog/release notes.
26 |
27 | ## Release
28 |
29 | Once the prep work is completed, the actual release is straight forward:
30 |
31 | * First, ensure that you have installed your projects dependencies:
32 |
33 | ```sh
34 | yarn install
35 | ```
36 |
37 | * Second, ensure that you have obtained a
38 | [GitHub personal access token][generate-token] with the `repo` scope (no
39 | other permissions are needed). Make sure the token is available as the
40 | `GITHUB_AUTH` environment variable.
41 |
42 | For instance:
43 |
44 | ```bash
45 | export GITHUB_AUTH=abc123def456
46 | ```
47 |
48 | [generate-token]: https://github.com/settings/tokens/new?scopes=repo&description=GITHUB_AUTH+env+variable
49 |
50 | * And last (but not least 😁) do your release.
51 |
52 | ```sh
53 | npx release-it
54 | ```
55 |
56 | [release-it](https://github.com/release-it/release-it/) manages the actual
57 | release process. It will prompt you to to choose the version number after which
58 | you will have the chance to hand tweak the changelog to be used (for the
59 | `CHANGELOG.md` and GitHub release), then `release-it` continues on to tagging,
60 | pushing the tag and commits, etc.
61 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/addon/.gitkeep
--------------------------------------------------------------------------------
/addon/components/radio-button-input.hbs:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/addon/components/radio-button-input.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { once } from '@ember/runloop';
3 | import { action } from '@ember/object';
4 |
5 | export default class RadioButtonInputComponent extends Component {
6 | get checkedStr() {
7 | const checked = this.args.checked;
8 |
9 | if (typeof checked === 'boolean') {
10 | return checked.toString();
11 | }
12 |
13 | return null;
14 | }
15 |
16 | @action change() {
17 | if (this.args.groupValue !== this.args.value) {
18 | // this.set('groupValue', value);
19 | once(this.args, 'changed', this.args.value);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/addon/components/radio-button.hbs:
--------------------------------------------------------------------------------
1 | {{#if (has-block)}}
2 |
3 |
18 | {{yield}}
19 |
20 | {{else}}
21 |
36 | {{/if}}
37 |
--------------------------------------------------------------------------------
/addon/components/radio-button.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { isEqual } from '@ember/utils';
4 |
5 | export default class RadioButtonComponent extends Component {
6 | // value - passed in, required, the value for this radio button
7 | // groupValue - passed in, required, the currently selected value
8 |
9 | // optionally passed in:
10 | // disabled - boolean
11 | // required - boolean
12 | // name - string
13 | // radioClass - string
14 | // radioId - string
15 | // ariaLabelledby - string
16 | // ariaDescribedby - string
17 |
18 | get joinedClassNames() {
19 | const classNames = this.args.classNames;
20 | if (classNames && classNames.length && classNames.join) {
21 | return classNames.join(' ');
22 | }
23 | return classNames;
24 | }
25 |
26 | get checkedClass() {
27 | return this.args.checkedClass || 'checked';
28 | }
29 |
30 | get checked() {
31 | return isEqual(this.args.groupValue, this.args.value);
32 | }
33 |
34 | @action changed(newValue) {
35 | let changedAction = this.args.changed;
36 |
37 | // providing a closure action is optional
38 | if (changedAction) {
39 | changedAction(newValue);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/app/.gitkeep
--------------------------------------------------------------------------------
/app/components/radio-button-input.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-radio-button/components/radio-button-input';
2 |
--------------------------------------------------------------------------------
/app/components/radio-button.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-radio-button/components/radio-button';
2 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getChannelURL = require('ember-source-channel-url');
4 | const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');
5 |
6 | module.exports = async function () {
7 | return {
8 | useYarn: true,
9 | scenarios: [
10 | {
11 | name: 'ember-lts-3.20',
12 | npm: {
13 | devDependencies: {
14 | 'ember-source': '~3.20.5',
15 | },
16 | },
17 | },
18 | {
19 | name: 'ember-lts-3.24',
20 | npm: {
21 | devDependencies: {
22 | 'ember-source': '~3.24.3',
23 | },
24 | },
25 | },
26 | {
27 | name: 'ember-lts-3.28',
28 | npm: {
29 | devDependencies: {
30 | 'ember-source': '~3.28.9',
31 | },
32 | },
33 | },
34 | {
35 | name: 'ember-release',
36 | npm: {
37 | devDependencies: {
38 | 'ember-source': await getChannelURL('release'),
39 | },
40 | },
41 | },
42 | {
43 | name: 'ember-beta',
44 | npm: {
45 | devDependencies: {
46 | 'ember-source': await getChannelURL('beta'),
47 | },
48 | },
49 | },
50 | {
51 | name: 'ember-canary',
52 | npm: {
53 | devDependencies: {
54 | 'ember-source': await getChannelURL('canary'),
55 | },
56 | },
57 | },
58 | {
59 | name: 'ember-default-with-jquery',
60 | env: {
61 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
62 | 'jquery-integration': true,
63 | }),
64 | },
65 | npm: {
66 | devDependencies: {
67 | '@ember/jquery': '^1.1.0',
68 | },
69 | },
70 | },
71 | {
72 | name: 'ember-classic',
73 | env: {
74 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
75 | 'application-template-wrapper': true,
76 | 'default-async-observers': false,
77 | 'template-only-glimmer-components': false,
78 | }),
79 | },
80 | npm: {
81 | ember: {
82 | edition: 'classic',
83 | },
84 | },
85 | },
86 | embroiderSafe(),
87 | embroiderOptimized(),
88 | ],
89 | };
90 | };
91 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (/* environment, appConfig */) {
4 | return {};
5 | };
6 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function (defaults) {
6 | let app = new EmberAddon(defaults, {
7 | // Add options here
8 | });
9 |
10 | /*
11 | This build file specifies the options for the dummy test app of this
12 | addon, located in `/tests/dummy`
13 | This build file does *not* influence how the addon or the app using it
14 | behave. You most likely want to be modifying `./index.js` or app's build file
15 | */
16 |
17 | const { maybeEmbroider } = require('@embroider/test-setup');
18 | return maybeEmbroider(app, {
19 | skipBabel: [
20 | {
21 | package: 'qunit',
22 | },
23 | ],
24 | });
25 | };
26 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | name: require('./package').name,
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-radio-button",
3 | "version": "3.0.0-beta.1",
4 | "description": "This addon provides a RadioButton component",
5 | "keywords": [
6 | "ember-addon"
7 | ],
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:yapplabs/ember-radio-button.git"
11 | },
12 | "license": "MIT",
13 | "author": "",
14 | "directories": {
15 | "doc": "doc",
16 | "test": "tests"
17 | },
18 | "scripts": {
19 | "build": "ember build --environment=production",
20 | "lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"",
21 | "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
22 | "lint:hbs": "ember-template-lint .",
23 | "lint:hbs:fix": "ember-template-lint . --fix",
24 | "lint:js": "eslint . --cache",
25 | "lint:js:fix": "eslint . --fix",
26 | "start": "ember serve",
27 | "test": "npm-run-all lint test:*",
28 | "test:ember": "ember test",
29 | "test:ember-compatibility": "ember try:each"
30 | },
31 | "dependencies": {
32 | "ember-cli-babel": "^7.26.11",
33 | "ember-cli-htmlbars": "^5.7.1",
34 | "webpack": "^5.72.1"
35 | },
36 | "devDependencies": {
37 | "@ember/optional-features": "^2.0.0",
38 | "@ember/test-helpers": "^2.4.2",
39 | "@embroider/test-setup": "^1.7.1",
40 | "@glimmer/component": "^1.1.2",
41 | "@glimmer/tracking": "^1.1.2",
42 | "babel-eslint": "^10.1.0",
43 | "broccoli-asset-rev": "^3.0.0",
44 | "ember-auto-import": "^2.4.2",
45 | "ember-cli": "~3.28.0",
46 | "ember-cli-dependency-checker": "^3.3.1",
47 | "ember-cli-inject-live-reload": "^2.1.0",
48 | "ember-cli-sri": "^2.1.1",
49 | "ember-cli-terser": "^4.0.2",
50 | "ember-disable-prototype-extensions": "^1.1.3",
51 | "ember-export-application-global": "^2.0.1",
52 | "ember-load-initializers": "^2.1.2",
53 | "ember-maybe-import-regenerator": "^1.0.0",
54 | "ember-page-title": "^7.0.0",
55 | "ember-qunit": "^5.1.5",
56 | "ember-resolver": "^8.0.3",
57 | "ember-source": "~3.28.0",
58 | "ember-source-channel-url": "^3.0.0",
59 | "ember-template-lint": "^3.6.0",
60 | "ember-try": "^1.4.0",
61 | "ember-welcome-page": "^6.2.0",
62 | "eslint": "^7.32.0",
63 | "eslint-config-prettier": "^8.3.0",
64 | "eslint-plugin-ember": "^10.5.4",
65 | "eslint-plugin-node": "^11.1.0",
66 | "eslint-plugin-prettier": "^3.4.1",
67 | "eslint-plugin-qunit": "^6.2.0",
68 | "loader.js": "^4.7.0",
69 | "npm-run-all": "^4.1.5",
70 | "prettier": "^2.3.2",
71 | "qunit": "^2.16.0",
72 | "qunit-dom": "^2.0.0",
73 | "release-it": "^14.2.1",
74 | "release-it-lerna-changelog": "^3.1.0"
75 | },
76 | "engines": {
77 | "node": "12.* || 14.* || >= 16"
78 | },
79 | "volta": {
80 | "node": "14.19.3",
81 | "yarn": "1.22.18"
82 | },
83 | "publishConfig": {
84 | "registry": "https://registry.npmjs.org"
85 | },
86 | "ember": {
87 | "edition": "octane"
88 | },
89 | "ember-addon": {
90 | "configPath": "tests/dummy/config"
91 | },
92 | "release-it": {
93 | "plugins": {
94 | "release-it-lerna-changelog": {
95 | "infile": "CHANGELOG.md",
96 | "launchEditor": false
97 | }
98 | },
99 | "git": {
100 | "tagName": "v${version}"
101 | },
102 | "github": {
103 | "release": true,
104 | "tokenRef": "GITHUB_AUTH"
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | test_page: 'tests/index.html?hidepassed',
5 | disable_watching: true,
6 | launch_in_ci: ['Chrome'],
7 | launch_in_dev: ['Chrome'],
8 | browser_start_timeout: 120,
9 | browser_args: {
10 | Chrome: {
11 | ci: [
12 | // --no-sandbox is needed when running Chrome inside a container
13 | process.env.CI ? '--no-sandbox' : null,
14 | '--headless',
15 | '--disable-dev-shm-usage',
16 | '--disable-software-rasterizer',
17 | '--mute-audio',
18 | '--remote-debugging-port=0',
19 | '--window-size=1440,900',
20 | ].filter(Boolean),
21 | },
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/tests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | 'use strict';
3 |
4 | module.exports = {
5 | env: {
6 | embertest: true,
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Application from '@ember/application';
2 | import Resolver from 'ember-resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from 'dummy/config/environment';
5 |
6 | export default class App extends Application {
7 | modulePrefix = config.modulePrefix;
8 | podModulePrefix = config.podModulePrefix;
9 | Resolver = Resolver;
10 | }
11 |
12 | loadInitializers(App, config.modulePrefix);
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/components/aria-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class AriaExample extends Component {
6 | @tracked color = 'red';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/autofocus-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class AutofocusExample extends Component {
6 | @tracked color = 'green';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/basic-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class BasicExample extends Component {
6 | @tracked color = 'green';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | window.alert(`Color changed to ${color}`);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/disabled-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class DisabledExample extends Component {
6 | @tracked number = 'one';
7 | @tracked numbersDisabled = true;
8 |
9 | @action colorChanged(color) {
10 | this.color = color;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/id-and-class-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class IdAndClassExample extends Component {
6 | @tracked color = 'purple';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | window.alert(`Color changed to ${color}`);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/legacy-actions-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class LegacyActionsExample extends Component {
6 | @tracked color = 'maroon';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | window.alert(`Color changed to ${color}`);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/object-value-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import EmberObject from '@ember/object';
3 |
4 | export default class ObjectValueExample extends Component {
5 | greenObject = { name: 'green object' };
6 |
7 | blueObject = { name: 'blue object' };
8 |
9 | reservation = EmberObject.create({
10 | number: 'one',
11 | });
12 |
13 | constructor() {
14 | super(...arguments);
15 | this.selectedColorObject = this.blueObject;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/required-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { tracked } from '@glimmer/tracking';
3 |
4 | export default class RequiredExample extends Component {
5 | @tracked noDefault = '';
6 | }
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/tab-index-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { tracked } from '@glimmer/tracking';
3 |
4 | export default class TabIndexExample extends Component {
5 | @tracked color = 'blue';
6 | @tracked size = 'small';
7 | }
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/user-checked-class-example.js:
--------------------------------------------------------------------------------
1 | import Component from '@glimmer/component';
2 | import { action } from '@ember/object';
3 | import { tracked } from '@glimmer/tracking';
4 |
5 | export default class UserCheckedClassExample extends Component {
6 | @tracked color = 'green';
7 |
8 | @action colorChanged(color) {
9 | this.color = color;
10 | window.alert(`Color changed to ${color}`);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/helpers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 | {{content-for "body-footer"}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import EmberRouter from '@ember/routing/router';
2 | import config from 'dummy/config/environment';
3 |
4 | export default class Router extends EmberRouter {
5 | location = config.locationType;
6 | rootURL = config.rootURL;
7 | }
8 |
9 | Router.map(function () {});
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/routes/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 20px;
3 | }
4 |
5 | input:focus {
6 | outline: 2px dashed red;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | radio-button component
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/dummy/app/templates/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/aria-example.hbs:
--------------------------------------------------------------------------------
1 | Aria Labelled by
2 |
3 | Red
4 |
5 |
6 | Blue
7 |
8 |
9 | Purple
10 |
11 |
12 | This color is created by combining Blue and Red.
13 |
14 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/autofocus-example.hbs:
--------------------------------------------------------------------------------
1 | Autofocus
2 |
3 |
4 | green (autofocused)
5 |
6 |
7 | red
8 |
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/basic-example.hbs:
--------------------------------------------------------------------------------
1 | Basic Usage
2 |
3 | Selected Color: {{this.color}}
4 |
5 |
6 | Green
7 |
8 |
9 | Blue
10 |
11 |
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/disabled-example.hbs:
--------------------------------------------------------------------------------
1 | Disabled flag
2 | Numbers Disabled: {{this.numbersDisabled}}
3 | Number: {{this.number}}
4 |
5 |
6 | Disabled
7 |
8 |
9 | Enabled
10 |
11 |
12 |
13 |
14 | One
15 |
16 |
17 | Two
18 |
19 |
20 | Three
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/id-and-class-example.hbs:
--------------------------------------------------------------------------------
1 | Using radioId and radioClass properties
2 | Selected Color: {{this.color}}
3 |
4 |
5 | Purple
6 |
7 |
8 | Orange
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/object-value-example.hbs:
--------------------------------------------------------------------------------
1 | Using objects as radio button values
2 |
3 | selectedColorObject.name: {{this.selectedColorObject.name}}
4 |
5 |
6 | Green Object
7 |
8 |
9 | Blue Object
10 |
11 |
12 |
13 | Chained group value properties
14 |
15 |
16 | Model.number: {{this.reservation.number}}
17 |
18 |
19 |
20 | One
21 |
22 |
23 | Two
24 |
25 |
26 | Three
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/required-example.hbs:
--------------------------------------------------------------------------------
1 | Required
2 | No Default: {{this.noDefault}}
3 |
4 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/tab-index-example.hbs:
--------------------------------------------------------------------------------
1 | Tab Index
2 | Selected Color: {{this.color}}
3 |
4 | Selected Size: {{this.size}}
5 |
6 |
7 |
8 | Use the arrow keys to move between radio buttons with the same `name`.
9 | The tab key moves between groups of radio buttons and other input elements.
10 |
11 |
12 |
See the w3 RadioButton wiki for details
13 |
14 |
15 |
16 | Tab index 4:
17 |
18 |
19 | Red
20 |
21 |
22 |
23 | Blue
24 |
25 |
26 |
27 | Green
28 |
29 |
30 |
31 |
32 | Tab index 2:
33 |
34 | Small
35 | Medium
36 | Large
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/user-checked-class-example.hbs:
--------------------------------------------------------------------------------
1 | Using a different 'checked' class
2 | Selected Color: {{this.color}}
3 |
4 |
5 | Green
6 |
7 |
8 | Blue
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/tests/dummy/config/ember-cli-update.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": "1.0.0",
3 | "packages": [
4 | {
5 | "name": "ember-cli",
6 | "version": "3.28.0",
7 | "blueprints": [
8 | {
9 | "name": "addon",
10 | "outputRepo": "https://github.com/ember-cli/ember-addon-output",
11 | "codemodsSource": "ember-addon-codemods-manifest@1",
12 | "isBaseBlueprint": true,
13 | "options": [
14 | "--welcome",
15 | "--yarn"
16 | ]
17 | }
18 | ]
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (environment) {
4 | let ENV = {
5 | modulePrefix: 'dummy',
6 | environment,
7 | rootURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true
13 | },
14 | EXTEND_PROTOTYPES: {
15 | // Prevent Ember Data from overriding Date.parse.
16 | Date: false,
17 | },
18 | },
19 |
20 | APP: {
21 | // Here you can pass flags/options to your application instance
22 | // when it is created
23 | },
24 | };
25 |
26 | if (environment === 'development') {
27 | // ENV.APP.LOG_RESOLVER = true;
28 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
29 | // ENV.APP.LOG_TRANSITIONS = true;
30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
31 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
32 | }
33 |
34 | if (environment === 'test') {
35 | // Testem prefers this...
36 | ENV.locationType = 'none';
37 |
38 | // keep test console output quieter
39 | ENV.APP.LOG_ACTIVE_GENERATION = false;
40 | ENV.APP.LOG_VIEW_LOOKUPS = false;
41 |
42 | ENV.APP.rootElement = '#ember-testing';
43 | ENV.APP.autoboot = false;
44 | }
45 |
46 | if (environment === 'production') {
47 | // here you can enable a production-specific feature
48 | }
49 |
50 | return ENV;
51 | };
52 |
--------------------------------------------------------------------------------
/tests/dummy/config/optional-features.json:
--------------------------------------------------------------------------------
1 | {
2 | "application-template-wrapper": false,
3 | "default-async-observers": true,
4 | "jquery-integration": false,
5 | "template-only-glimmer-components": true
6 | }
7 |
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const browsers = [
4 | 'last 1 Chrome versions',
5 | 'last 1 Firefox versions',
6 | 'last 1 Safari versions',
7 | ];
8 |
9 | // Ember's browser support policy is changing, and IE11 support will end in
10 | // v4.0 onwards.
11 | //
12 | // See https://deprecations.emberjs.com/v3.x#toc_3-0-browser-support-policy
13 | //
14 | // If you need IE11 support on a version of Ember that still offers support
15 | // for it, uncomment the code block below.
16 | //
17 | // const isCI = Boolean(process.env.CI);
18 | // const isProduction = process.env.EMBER_ENV === 'production';
19 | //
20 | // if (isCI || isProduction) {
21 | // browsers.push('ie 11');
22 | // }
23 |
24 | module.exports = {
25 | browsers,
26 | };
27 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/tests/helpers/person.js:
--------------------------------------------------------------------------------
1 | export class Person {
2 | constructor({ name, ssn }) {
3 | this.name = name;
4 | this.ssn = ssn;
5 | }
6 |
7 | isEqual(other) {
8 | return this.ssn == other.ssn;
9 | }
10 | }
11 |
12 | const matchingSSN = '123-45-6789';
13 |
14 | export const alice = new Person({ name: 'Alice', ssn: matchingSSN });
15 | export const alice2 = new Person({ name: 'Alice 2', ssn: matchingSSN });
16 | export const bob = new Person({ name: 'Bob', ssn: '999-99-9999' });
17 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{content-for "body-footer"}}
38 | {{content-for "test-body-footer"}}
39 |
40 |
41 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/integration/.gitkeep
--------------------------------------------------------------------------------
/tests/integration/components/radio-button-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { setupRenderingTest } from 'ember-qunit';
3 | import { render, triggerEvent } from '@ember/test-helpers';
4 | import { hbs } from 'ember-cli-htmlbars';
5 | import { alice, alice2, bob } from '../../helpers/person';
6 |
7 | module('Integration | Components | Radio Button', function (hooks) {
8 | setupRenderingTest(hooks);
9 |
10 | test('begins checked when groupValue matches value', async function (assert) {
11 | assert.expect(2);
12 |
13 | await render(hbs`
14 |
18 | `);
19 |
20 | assert.dom('input').isChecked();
21 | assert.dom('input').hasAttribute('aria-checked', 'true');
22 | });
23 |
24 | test('it updates when clicked, and triggers the `changed` action', async function (assert) {
25 | assert.expect(7);
26 |
27 | let changedActionCallCount = 0;
28 |
29 | this.set('groupValue', 'initial-group-value');
30 |
31 | this.set('changed', (newValue) => {
32 | changedActionCallCount++;
33 | assert.strictEqual(newValue, 'component-value', 'updates groupValue');
34 | this.set('groupValue', newValue);
35 | });
36 |
37 | await render(hbs`
38 |
43 | `);
44 |
45 | assert.strictEqual(changedActionCallCount, 0);
46 | assert.dom('input').isNotChecked();
47 | assert
48 | .dom('input')
49 | .hasAttribute(
50 | 'aria-checked',
51 | 'false',
52 | 'aria-checked property starts false'
53 | );
54 |
55 | await triggerEvent('input', 'click');
56 |
57 | assert.dom('input').isChecked('updates element property');
58 | assert
59 | .dom('input')
60 | .hasAttribute('aria-checked', 'true', 'updates aria-checked property');
61 |
62 | assert.strictEqual(changedActionCallCount, 1);
63 | });
64 |
65 | test('it updates when the browser change event is fired', async function (assert) {
66 | assert.expect(5);
67 | let changedActionCallCount = 0;
68 | this.set('changed', function (newValue) {
69 | changedActionCallCount++;
70 | assert.strictEqual(newValue, 'component-value', 'updates groupValue');
71 | });
72 |
73 | this.set('groupValue', 'initial-group-value');
74 |
75 | await render(hbs`
76 |
81 | `);
82 |
83 | assert.strictEqual(changedActionCallCount, 0);
84 | assert.dom('input').isNotChecked();
85 |
86 | await triggerEvent('input', 'click');
87 |
88 | assert.dom('input').isChecked('updates DOM property');
89 |
90 | assert.strictEqual(changedActionCallCount, 1);
91 | });
92 |
93 | test('it gives the label of a wrapped checkbox a `checked` className', async function (assert) {
94 | assert.expect(4);
95 |
96 | this.set('groupValue', 'initial-group-value');
97 | this.set('value', 'component-value');
98 |
99 | await render(hbs`
100 |
105 | Blue
106 |
107 | `);
108 |
109 | assert.dom('label').doesNotHaveClass('checked');
110 |
111 | this.set('value', 'initial-group-value');
112 |
113 | assert.dom('label').hasClass('checked');
114 | assert.dom('label').hasClass('ember-radio-button');
115 | assert.dom('label').hasClass('blue-radio');
116 | });
117 |
118 | test('providing `checkedClass` gives the label a custom classname when the radio is checked', async function (assert) {
119 | assert.expect(5);
120 |
121 | this.set('groupValue', 'initial-group-value');
122 | this.set('value', 'component-value');
123 |
124 | await render(hbs`
125 |
131 | Blue
132 |
133 | `);
134 |
135 | assert
136 | .dom('label')
137 | .doesNotHaveClass(
138 | 'my-custom-class',
139 | 'does not have user-provided checkedClass'
140 | );
141 |
142 | this.set('value', 'initial-group-value');
143 |
144 | assert
145 | .dom('label')
146 | .doesNotHaveClass('checked', 'does not have the `checked` class');
147 | assert
148 | .dom('label')
149 | .hasClass('my-custom-class', 'has user-provided checkedClass');
150 | assert
151 | .dom('label')
152 | .hasClass('ember-radio-button', 'has class `ember-radio-button`');
153 | assert.dom('label').hasClass('blue-radio', 'has class `blue-radio`');
154 | });
155 |
156 | test('it updates when setting `value`', async function (assert) {
157 | assert.expect(3);
158 |
159 | this.set('groupValue', 'initial-group-value');
160 | this.set('value', 'component-value');
161 |
162 | await render(hbs`
163 |
167 | `);
168 |
169 | assert.dom('input').isNotChecked();
170 |
171 | this.set('value', 'initial-group-value');
172 |
173 | assert.dom('input').isChecked();
174 |
175 | this.set('value', 'component-value');
176 |
177 | assert.dom('input').isNotChecked();
178 | });
179 |
180 | test('begins disabled when disabled is true', async function (assert) {
181 | assert.expect(1);
182 |
183 | await render(hbs` `);
184 |
185 | assert.dom('input').isDisabled();
186 | });
187 |
188 | test('updates disabled when the disabled attribute changes', async function (assert) {
189 | this.set('isDisabled', false);
190 |
191 | await render(hbs` `);
192 |
193 | assert.dom('input').isNotDisabled();
194 |
195 | this.set('isDisabled', true);
196 |
197 | assert.dom('input').isDisabled();
198 |
199 | this.set('isDisabled', false);
200 |
201 | assert.dom('input').isNotDisabled();
202 | });
203 |
204 | test('begins with the `required` and `name` attributes when specified', async function (assert) {
205 | await render(hbs` `);
206 |
207 | assert.dom('input').isRequired();
208 | assert.dom('input').hasAttribute('name', 'colors');
209 | });
210 |
211 | test('updates the `required` attribute when the property changes', async function (assert) {
212 | this.set('isRequired', false);
213 |
214 | await render(hbs` `);
215 |
216 | assert.dom('input').isNotRequired();
217 |
218 | this.set('isRequired', true);
219 |
220 | assert.dom('input').isRequired();
221 |
222 | this.set('isRequired', false);
223 |
224 | assert.dom('input').isNotRequired();
225 | });
226 |
227 | test('updates the `name` attribute when the property changes', async function (assert) {
228 | this.set('name', undefined);
229 |
230 | await render(hbs` `);
231 |
232 | assert.dom('input').hasNoAttribute('name');
233 |
234 | this.set('name', 'colors');
235 |
236 | assert.dom('input').hasAttribute('name', 'colors');
237 | });
238 |
239 | test('uses a layout, tagName=label, when given a template', async function (assert) {
240 | await render(hbs`Red `);
241 |
242 | assert.dom('label').hasText('Red');
243 | assert.dom('input[type="radio"]').exists({ count: 1 });
244 | assert.dom('.ember-radio-button').exists();
245 | });
246 |
247 | test('it binds attributes only to the input when used as a block', async function (assert) {
248 | await render(hbs`
249 |
256 | Blue
257 |
258 | `);
259 |
260 | assert.dom('.ember-radio-button').hasTagName('label', 'is a label');
261 | assert.dom('.ember-radio-button').isNotChecked();
262 |
263 | assert
264 | .dom('.ember-radio-button')
265 | .hasNoAttribute('name', 'does not have name set');
266 | assert
267 | .dom('.ember-radio-button')
268 | .hasNoAttribute('required', 'is not required');
269 | assert
270 | .dom('.ember-radio-button')
271 | .hasNoAttribute('type', 'does not have attribute type');
272 | assert
273 | .dom('.ember-radio-button')
274 | .hasNoAttribute('value', 'does not have attribute value');
275 |
276 | const inputSelector = '.ember-radio-button input[type="radio"]';
277 |
278 | assert.dom(inputSelector).exists();
279 | assert.dom(inputSelector).isChecked();
280 | assert.dom(inputSelector).isDisabled();
281 | assert.dom(inputSelector).hasAttribute('name', 'some-name', 'has name set');
282 | assert.dom(inputSelector).isRequired('is required');
283 | assert.dom(inputSelector).hasValue('blue');
284 | });
285 |
286 | test('it checks the input when the label is clicked and has a `for` attribute', async function (assert) {
287 | assert.expect(4);
288 |
289 | this.set('value', 'component-value');
290 |
291 | await render(hbs`
292 |
298 | Green
299 |
300 | `);
301 |
302 | await triggerEvent('label', 'click');
303 |
304 | assert
305 | .dom('label')
306 | .hasAttribute(
307 | 'for',
308 | 'green-0',
309 | 'the label has the correct `for` attribute'
310 | );
311 | assert
312 | .dom('input')
313 | .hasAttribute(
314 | 'id',
315 | 'green-0',
316 | 'the input has the correct `id` attribute'
317 | );
318 |
319 | assert.dom('input').hasClass('my-radio-class');
320 | assert.dom('input').isChecked('clicking the label checks the radio');
321 | });
322 |
323 | test('it updates when setting `value` with isEqual', async function (assert) {
324 | assert.expect(3);
325 |
326 | this.set('groupValue', alice);
327 | this.set('value', bob);
328 |
329 | await render(hbs`
330 |
334 | `);
335 |
336 | assert.dom('input').isNotChecked();
337 |
338 | this.set('value', alice2);
339 |
340 | assert.dom('input').isChecked();
341 |
342 | this.set('value', bob);
343 |
344 | assert.dom('input').isNotChecked();
345 | });
346 |
347 | test('it binds `aria-labelledby` when specified', async function (assert) {
348 | assert.expect(1);
349 |
350 | this.set('ariaLabelledby', 'green-label');
351 |
352 | await render(hbs`
353 |
358 | Green
359 |
360 | `);
361 |
362 | assert.dom('input').hasAttribute('aria-labelledby', 'green-label');
363 | });
364 |
365 | test('it binds `aria-describedby` when specified', async function (assert) {
366 | assert.expect(1);
367 |
368 | this.set('ariaDescribedby', 'green-label');
369 |
370 | await render(hbs`
371 |
376 | Green
377 |
378 | `);
379 |
380 | assert.dom('input').hasAttribute('aria-describedby', 'green-label');
381 | });
382 | });
383 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import Application from 'dummy/app';
2 | import config from 'dummy/config/environment';
3 | import * as QUnit from 'qunit';
4 | import { setApplication } from '@ember/test-helpers';
5 | import { setup } from 'qunit-dom';
6 | import { start } from 'ember-qunit';
7 |
8 | setApplication(Application.create(config.APP));
9 |
10 | setup(QUnit.assert);
11 |
12 | start();
13 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/tests/unit/.gitkeep
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yapplabs/ember-radio-button/732619a8557bd0ecc5f5e769426940bde1c52c1b/vendor/.gitkeep
--------------------------------------------------------------------------------