Skip to content

Commit

Permalink
Adopt builtin components (#1)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthew Beale <matt.beale@madhatted.com>
  • Loading branch information
jamemackson and mixonic committed Nov 10, 2021
1 parent 5fb8a16 commit ea75628
Show file tree
Hide file tree
Showing 28 changed files with 3,924 additions and 1,768 deletions.
19 changes: 19 additions & 0 deletions addon/components/_has-dom.ts
@@ -0,0 +1,19 @@
// check if window exists and actually is the global
export default typeof self === 'object' &&
self !== null &&
(self as Window['self']).Object === Object &&
typeof Window !== 'undefined' &&
self.constructor === Window &&
typeof document === 'object' &&
document !== null &&
self.document === document &&
typeof location === 'object' &&
location !== null &&
self.location === location &&
typeof history === 'object' &&
history !== null &&
self.history === history &&
typeof navigator === 'object' &&
navigator !== null &&
self.navigator === navigator &&
typeof navigator.userAgent === 'string';
78 changes: 78 additions & 0 deletions addon/components/_internals.ts
@@ -0,0 +1,78 @@
function intern(str: string): string {
let obj = {};
//@ts-ignore
obj[str] = 1;
for (let key in obj) {
if (key === str) {
return key;
}
}
return str;
}

const GUID_KEY = intern(`__ember${Date.now()}`);

// `enumerableSymbol` copied from https://github.com/emberjs/ember.js/blob/master/packages/@ember/-internals/utils/lib/symbol.ts
// for not exported code these legacy components are dependant on.

// Some legacy symbols still need to be enumerable for a variety of reasons.
// This code exists for that, and as a fallback in IE11. In general, prefer
// `symbol` below when creating a new symbol.
function enumerableSymbol(debugName: string): string {
let id = GUID_KEY + Math.floor(Math.random() * Date.now());
let symbol = intern(`__${debugName}${id}__`);
return symbol;
}

export const HAS_BLOCK = enumerableSymbol('HAS_BLOCK');

export function isSimpleClick(event: MouseEvent): boolean {
let modifier =
event.shiftKey || event.metaKey || event.altKey || event.ctrlKey;
let secondaryClick = event.which > 1; // IE9 may return undefined

return !modifier && !secondaryClick;
}

// export interface GlobalContext {
// imports: object;
// exports: object;
// lookup: object;
// }

// /* globals global, window, self */
// declare const mainContext: object | undefined;

// // from lodash to catch fake globals
// function checkGlobal(value: any | null | undefined): value is object {
// return value && value.Object === Object ? value : undefined;
// }

// // element ids can ruin global miss checks
// function checkElementIdShadowing(value: any | null | undefined) {
// return value && value.nodeType === undefined ? value : undefined;
// }

// // export real global
// export default checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) ||
// checkGlobal(typeof self === 'object' && self) ||
// checkGlobal(typeof window === 'object' && window) ||
// (typeof mainContext !== 'undefined' && mainContext) || // set before strict mode in Ember loader/wrapper
// new Function('return this')(); // eval outside of strict mode

// // legacy imports/exports/lookup stuff (should we keep this??)
// export const context = (function (
// global: object,
// Ember: Partial<GlobalContext> | undefined
// ): GlobalContext {
// return Ember === undefined
// ? { imports: global, exports: global, lookup: global }
// : {
// // import jQuery
// imports: Ember.imports || global,
// // export Ember
// exports: Ember.exports || global,
// // search for Namespaces
// lookup: Ember.lookup || global,
// };
// })(global, global.Ember);
1 change: 1 addition & 0 deletions addon/components/checkbox.hbs
@@ -0,0 +1 @@
{{yield}}
162 changes: 162 additions & 0 deletions addon/components/checkbox.js
@@ -0,0 +1,162 @@
//@ts-check
/* eslint-disable ember/no-component-lifecycle-hooks */
/* eslint-disable ember/require-tagless-components */
/* eslint-disable ember/no-classic-classes */
/* eslint-disable ember/no-classic-components */
import { set } from '@ember/object';
import { assert } from '@ember/debug';
import { DEBUG } from '@glimmer/env';
import EmberComponent from '@ember/component';

/**
@module @ember/component
*/

/**
The internal class used to create text inputs when the `{{input}}`
helper is used with `type` of `checkbox`.
See [Ember.Templates.helpers.input](/ember/release/classes/Ember.Templates.helpers/methods/input?anchor=input) for usage details.
## Direct manipulation of `checked`
The `checked` attribute of an `Checkbox` object should always be set
through the Ember object or by interacting with its rendered element
representation via the mouse, keyboard, or touch. Updating the value of the
checkbox via jQuery will result in the checked value of the object and its
element losing synchronization.
## Layout and LayoutName properties
Because HTML `input` elements are self closing `layout` and `layoutName`
properties will not be applied.
@class Checkbox
@public
*/
const Checkbox = EmberComponent.extend({
/**
By default, this component will add the `ember-checkbox` class to the component's element.
@property classNames
@type Array | String
@default ['ember-checkbox']
@public
*/
classNames: ['ember-checkbox'],

tagName: 'input',

/**
By default this component will forward a number of arguments to attributes on the the
component's element:
* indeterminate
* disabled
* tabindex
* name
* autofocus
* required
* form
When invoked with curly braces, this is the exhaustive list of HTML attributes you can
customize (i.e. `{{input type="checkbox" disabled=true}}`).
When invoked with angle bracket invocation, this list is irrelevant, because you can use HTML
attribute syntax to customize the element (i.e.
`<Input @type="checkbox" disabled data-custom="custom value" />`). However, `@type` and
`@checked` must be passed as named arguments, not attributes.
@property attributeBindings
@type Array | String
@default ['type', 'checked', 'indeterminate', 'disabled', 'tabindex', 'name', 'autofocus', 'required', 'form']
@public
*/
attributeBindings: [
'type',
'checked',
'indeterminate',
'disabled',
'tabindex',
'name',
'autofocus',
'required',
'form',
],

/**
Sets the `type` attribute of the `Checkbox`'s element
@property disabled
@default false
@private
*/
type: 'checkbox',

/**
Sets the `disabled` attribute of the `Checkbox`'s element
@property disabled
@default false
@public
*/
disabled: false,

/**
Corresponds to the `indeterminate` property of the `Checkbox`'s element
@property disabled
@default false
@public
*/
indeterminate: false,

/**
Whenever the checkbox is inserted into the DOM, perform initialization steps, which include
setting the indeterminate property if needed.
If this method is overridden, `super` must be called.
@method
@public
*/
didInsertElement() {
this._super(...arguments);
this.element.indeterminate = Boolean(this.indeterminate);
},

/**
Whenever the `change` event is fired on the checkbox, update its `checked` property to reflect
whether the checkbox is checked.
If this method is overridden, `super` must be called.
@method
@public
*/
change() {
set(this, 'checked', this.element.checked);
},
});

if (DEBUG) {
const UNSET = {};

Checkbox.reopen({
value: UNSET,

didReceiveAttrs() {
this._super();

assert(
"`<Input @type='checkbox' @value={{...}} />` is not supported; " +
"please use `<Input @type='checkbox' @checked={{...}} />` instead.",
!(this.type === 'checkbox' && this.value !== UNSET)
);
},
});
}

Checkbox.toString = () => '@ember/component/checkbox';

export default Checkbox;
5 changes: 5 additions & 0 deletions addon/components/link-to.hbs
@@ -0,0 +1,5 @@
{{~#if (has-block)~}}
{{yield}}
{{~else~}}
{{this.linkTitle}}
{{~/if~}}

0 comments on commit ea75628

Please sign in to comment.