diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index 728ddcf1a3..b4ab411390 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -1,34 +1,34 @@ { "name": "@ionic/core", - "version": "0.0.2-3", + "version": "0.0.2-4", "lockfileVersion": 1, "requires": true, "dependencies": { "@stencil/core": { - "version": "0.0.4-4", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-0.0.4-4.tgz", - "integrity": "sha512-fcFq1gNxrpIvZu1M7J+9E8mT7Rd2LW2nhKdVkJCxYdQs7UErVyn5ksY0Ckqgvsn0wOPaymUoeNkYAcG/L7sTRQ==", + "version": "0.0.4-11", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-0.0.4-11.tgz", + "integrity": "sha512-CJo2o3RAnzA84AZ0GXMH0TANZR/z6JH1EKd+hnXwnu62CH+KZ37zjEXrMy5tsRCJ1nfqSwS6BOwAJtV1+xoeVA==", "requires": { "chalk": "1.1.3", "chokidar": "1.7.0", "clean-css": "4.1.7", "jsdom": "11.1.0", - "node-fetch": "1.7.1", + "node-fetch": "1.7.2", "node-sass": "4.5.3", "rollup": "0.41.4", "rollup-plugin-commonjs": "8.1.0", "rollup-plugin-node-resolve": "3.0.0", - "typescript": "2.4.0", + "typescript": "2.5.0-dev.20170808", "uglify-es": "3.0.27" } }, "@stencil/dev-server": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@stencil/dev-server/-/dev-server-0.0.11.tgz", - "integrity": "sha512-ZNPsLAxhP5e5SUdEpPZm/mlcRTDHSGctY9CsChncisMm0zjYeKNQFqel+ZKAO8sIdmikQDyCDuZwq2JEMneTwg==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@stencil/dev-server/-/dev-server-0.0.14.tgz", + "integrity": "sha512-sdnuZ1Tgg1I8DsXhkzyZjrwdFkQvI0HrXQXcHARZYeV6CeIJS51+q9EbvoMBHsUBuqPxgTgR8GHySw/DfZY5UQ==", "dev": true, "requires": { - "chalk": "2.0.1", + "chalk": "2.1.0", "chokidar": "1.7.0", "ecstatic": "2.2.1", "lodash.debounce": "4.0.8", @@ -46,9 +46,9 @@ } }, "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", "dev": true, "requires": { "ansi-styles": "3.2.0", @@ -2141,9 +2141,9 @@ "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" }, "node-fetch": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.2.tgz", + "integrity": "sha512-xZZUq2yDhKMIn/UgG5q//IZSNLJIwW2QxS14CNH5spuiXkITM2pUitjdq58yLSaU7m4M0wBNaM2Gh/ggY4YJig==", "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -2959,9 +2959,9 @@ } }, "typescript": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.0.tgz", - "integrity": "sha1-rvWo1AS+ujatM5q/B53d3/+6ht0=" + "version": "2.5.0-dev.20170808", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.0-dev.20170808.tgz", + "integrity": "sha512-Gb+2vCDs47CMtRzpoc41Uia4UDV4biDYZo9Z5nTwINftcI96FecFCQgJQAMLF8G4bKR4pwKmOuiSN1JyGInN3A==" }, "uglify-es": { "version": "3.0.27", diff --git a/packages/core/package.json b/packages/core/package.json index 315bc723b8..7ed57a9a18 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/core", - "version": "0.0.2-3", + "version": "0.0.2-4", "description": "Base components for Ionic", "main": "dist/collection/index.js", "types": "dist/collection/index.d.ts", @@ -10,16 +10,16 @@ "README.md" ], "dependencies": { - "@stencil/core": "^0.0.4-3" + "@stencil/core": "0.0.4-14" }, "devDependencies": { - "@stencil/dev-server": "^0.0.11", - "@stencil/utils": "^0.0.4" + "@stencil/dev-server": "latest", + "@stencil/utils": "latest" }, "scripts": { "build": "stencil build", "dev": "sd concurrent \"stencil build --dev --watch\" \"stencil-dev-server\"", - "publish": "../../node_modules/.bin/np --any-branch", + "publish": "npm run build && node scripts/publish.js && node scripts/publish.js && ../../node_modules/.bin/np --any-branch", "test": "(jest --no-cache || true)" }, "author": "Ionic Team", diff --git a/packages/core/scripts/publish.js b/packages/core/scripts/publish.js new file mode 100644 index 0000000000..9dadee1336 --- /dev/null +++ b/packages/core/scripts/publish.js @@ -0,0 +1,17 @@ +var fs = require('fs'); +var path = require('path'); + + +var DIST = path.join(__dirname, '../dist/collection'); +var SRC = path.join(__dirname, '../src'); +var INDEX_JS_DIST = path.join(DIST, 'index.js'); +var INDEX_DTS_SRC = path.join(SRC, 'index.d.ts'); +var INDEX_DTS_DIST = path.join(DIST, 'index.d.ts'); + +console.log('publish: create', INDEX_JS_DIST); +fs.writeFileSync(INDEX_JS_DIST, ''); + + +console.log('publish: create', INDEX_DTS_DIST); +var srcIndexDTS = fs.readFileSync(INDEX_DTS_SRC, 'utf-8'); +fs.writeFileSync(INDEX_DTS_DIST, srcIndexDTS); \ No newline at end of file diff --git a/packages/core/src/components/button/button.tsx b/packages/core/src/components/button/button.tsx index 67e1a17482..a1a86d4eeb 100644 --- a/packages/core/src/components/button/button.tsx +++ b/packages/core/src/components/button/button.tsx @@ -1,5 +1,7 @@ import { Component, Element, Prop, CssClassMap } from '@stencil/core'; +import { getElementClassObject } from '../../utils/theme'; + /** * @name Button * @module ionic @@ -178,7 +180,9 @@ export class Button { const decorator = (this.strong ? 'strong' : null); - const buttonClasses: CssClassMap = [] + const hostClasses = getElementClassObject(this.el.classList); + + const elementClasses: CssClassMap = [] .concat( getButtonClassList(buttonType, mode), getClassList(buttonType, shape, mode), @@ -186,8 +190,7 @@ export class Button { getClassList(buttonType, size, mode), getClassList(buttonType, decorator, mode), getStyleClassList(mode, this.color, buttonType, this.outline, this.clear, this.solid), - getItemClassList(this.itemButton, size), - getElementClassList(this.el.classList) + getItemClassList(this.itemButton, size) ) .reduce((prevValue, cssClass) => { prevValue[cssClass] = true; @@ -196,6 +199,11 @@ export class Button { const TagType = this.href ? 'a' : 'button'; + const buttonClasses = { + ...hostClasses, + ...elementClasses + } + return ( @@ -292,14 +300,3 @@ function getStyleClassList(mode: string, color: string, buttonType: string, outl function getItemClassList(itemButton: boolean, size: string) { return itemButton && !size ? ['item-button'] : []; } - -/** - * Get the element classes to add to the child element - */ -function getElementClassList(elmClassList: DOMTokenList) { - const classList: string[] = []; - for (var i = 0; i < elmClassList.length; i++) { - classList.push(elmClassList.item(i)); - } - return classList; -} diff --git a/packages/core/src/components/chip-button/chip-button.tsx b/packages/core/src/components/chip-button/chip-button.tsx index 5a32849d97..8faea39758 100644 --- a/packages/core/src/components/chip-button/chip-button.tsx +++ b/packages/core/src/components/chip-button/chip-button.tsx @@ -1,5 +1,6 @@ import { Component, CssClassMap, Element, Prop } from '@stencil/core'; +import { getElementClassObject } from '../../utils/theme'; @Component({ tag: 'ion-chip-button', @@ -71,25 +72,14 @@ export class ChipButton { return classList; } - /** - * @hidden - * Get the element classes to add to the child element - */ - private getElementClassList() { - let classList = [].concat( - this.el.className.length ? this.el.className.split(' ') : [] - ); - - return classList; - } - render() { const buttonType = 'chip-button'; - var buttonClasses: CssClassMap = [] + const hostClasses = getElementClassObject(this.el.classList); + + const elementClasses: CssClassMap = [] .concat( this.getButtonClassList(buttonType, this.mode), - this.getElementClassList(), this.getStyleClassList(buttonType) ) .reduce((prevValue, cssClass) => { @@ -99,6 +89,11 @@ export class ChipButton { const TagType = this.href ? 'a' : 'button'; + const buttonClasses = { + ...hostClasses, + ...elementClasses + } + return ( diff --git a/packages/core/src/components/chip/test/basic.html b/packages/core/src/components/chip/test/basic.html index 85ab904f8f..e9236e5ab2 100644 --- a/packages/core/src/components/chip/test/basic.html +++ b/packages/core/src/components/chip/test/basic.html @@ -76,7 +76,7 @@ Default - + diff --git a/packages/core/src/components/content/content.tsx b/packages/core/src/components/content/content.tsx index 0699e052ee..495c6f71eb 100644 --- a/packages/core/src/components/content/content.tsx +++ b/packages/core/src/components/content/content.tsx @@ -1,6 +1,6 @@ import { Component, Element, Prop } from '@stencil/core'; import { Config, Scroll, ScrollDetail } from '../../index'; -import { createThemedClasses } from '../../utils/theme'; +import { createThemedClasses, getElementClassObject } from '../../utils/theme'; import { getParentElement, getToolbarHeight } from '../../utils/helpers'; @@ -103,11 +103,18 @@ export class Content { if (this.ionScrollEnd) { props['ionScrollEnd'] = this.ionScrollEnd.bind(this); } + const themedClasses = createThemedClasses(this.mode, this.color, 'content'); - themedClasses['statusbar-padding'] = this.config.getBoolean('statusbarPadding'); + const hostClasses = getElementClassObject(this.el.classList); + + const scrollClasses = { + ...themedClasses, + ...hostClasses, + 'statusbar-padding': this.config.getBoolean('statusbarPadding') + } return ( - + ); diff --git a/packages/core/src/components/fab/fab.tsx b/packages/core/src/components/fab/fab.tsx index d9e64de89e..44838af479 100755 --- a/packages/core/src/components/fab/fab.tsx +++ b/packages/core/src/components/fab/fab.tsx @@ -1,5 +1,5 @@ import { Component, Element, CssClassMap, Method, Prop, State } from '@stencil/core'; -import { createThemedClasses } from '../../utils/theme'; +import { createThemedClasses, getElementClassObject } from '../../utils/theme'; /** @@ -110,18 +110,6 @@ export class FabButton { this.setActiveLists(false); } - /** - * @hidden - * Get the element classes to add to the child element - */ - getElementClassList() { - let classList = [].concat( - this.el.className.length ? this.el.className.split(' ') : [] - ); - - return classList; - } - /** * @hidden * Get the classes for fab buttons in lists @@ -164,10 +152,10 @@ export class FabButton { render() { const themedClasses = createThemedClasses(this.mode, this.color, 'fab'); + const hostClasses = getElementClassObject(this.el.classList); - var fabClasses: CssClassMap = [] + const elementClasses: CssClassMap = [] .concat( - this.getElementClassList(), this.getFabListClassList(), this.getFabActiveClassList(), this.getFabShowClassList() @@ -179,7 +167,11 @@ export class FabButton { const TagType = this.href ? 'a' : 'button'; - fabClasses = Object.assign(fabClasses, themedClasses); + const fabClasses = { + ...themedClasses, + ...hostClasses, + ...elementClasses + } return ( diff --git a/packages/core/src/components/icon/icon.tsx b/packages/core/src/components/icon/icon.tsx index 60c8af183d..fceb3af394 100644 --- a/packages/core/src/components/icon/icon.tsx +++ b/packages/core/src/components/icon/icon.tsx @@ -19,7 +19,7 @@ export class Icon { /** * @input {string} Specifies the label to use for accessibility. Defaults to the icon name. */ - @State() ariaLabel: string = ''; + @Prop() ariaLabel: string = ''; /** * @input {string} Specifies which icon to use. The appropriate icon will be used based on the mode. @@ -38,20 +38,13 @@ export class Icon { @Prop() md: string = ''; - @State() svgContent: string = null; + @Prop({ context: 'isServer'}) private isServer: boolean; - getSvgUrl() { - const iconName = this.iconName; - if (iconName !== null) { - return `${publicPath}svg/${iconName}.svg`; - } - - return null; - } + @State() private svgContent: string = null; - get iconName() { + private get iconName() { // if no name was passed set iconName to null if (!this.name) { return null; @@ -117,73 +110,18 @@ export class Icon { } - static loadSvgContent(svgUrl: string, callback: {(loadedSvgContent: string): void}) { - // static since all IonIcons use this same function and pointing at global/shared data - // passed in callback will have instance info - - // add to the list of callbacks to fiure when this url is finished loading - IonIcon.loadCallbacks[svgUrl] = IonIcon.loadCallbacks[svgUrl] || []; - IonIcon.loadCallbacks[svgUrl].push(callback); - - if (IonIcon.activeRequests[svgUrl]) { - // already requesting this url, don't bother again kicking off another - return; + render() { + if (this.isServer) { + return
{/* ssr */}
; } - // add this url to our list of active requests - IonIcon.activeRequests[svgUrl] = true; - - // kick off the request for the external svg file - const xhr = new XMLHttpRequest(); - xhr.addEventListener('load', function() { - // awesome, we've finished loading the svg file - - // remove this url from the active requests - delete IonIcon.activeRequests[svgUrl]; - - // this response is the content of the svg file we're looking for - let svgContent = this.responseText; - - if (this.status >= 400) { - // umm, not awesome, something is up - console.error('Icon could not be loaded:', svgUrl); - svgContent = ``; - } - - // cache the svg content in the global IonIcon constant - IonIcon.svgContents[svgUrl] = svgContent; - - // find any callbacks waiting on this url - const svgLoadCallbacks = IonIcon.loadCallbacks[svgUrl]; - if (svgLoadCallbacks) { - // loop through all the callbacks that are waiting on the svg content - for (var i = 0; i < svgLoadCallbacks.length; i++) { - // fire off this callback which was provided by an instance - svgLoadCallbacks[i](svgContent); - } - delete IonIcon.loadCallbacks[svgUrl]; - } - }); - - xhr.addEventListener('error', () => { - // umm, idk - console.error('Icon could not be loaded:', svgUrl); - }); - - // let's do this! - xhr.open('GET', svgUrl, true); - xhr.send(); - } - - - render() { - const svgUrl = this.getSvgUrl(); + const svgUrl = getSvgUrl(this.iconName); if (!svgUrl) { // we don't have good data return
{/* invalid svg */}
; } - const svgContent = IonIcon.svgContents[svgUrl]; + const svgContent = svgContents[svgUrl]; if (svgContent === this.svgContent) { // we've already loaded up this svg at one point // and the svg content we've loaded and assigned checks out @@ -193,7 +131,7 @@ export class Icon { // haven't loaded this svg yet // start the request - Icon.loadSvgContent(svgUrl, loadedSvgContent => { + loadSvgContent(svgUrl, loadedSvgContent => { // we're finished loading the svg content! // set to this.svgContent so we do another render this.svgContent = loadedSvgContent; @@ -206,15 +144,73 @@ export class Icon { } -const IonIcon: GlobalIonIcon = { - activeRequests: {}, - loadCallbacks: [] as any, - svgContents: {} -}; - - -interface GlobalIonIcon { - activeRequests: {[url: string]: boolean}; - loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]}; - svgContents: {[url: string]: string}; +function getSvgUrl(iconName: string) { + if (iconName !== null) { + return `${publicPath}svg/${iconName}.svg`; + } + return null; } + + +function loadSvgContent(svgUrl: string, callback: {(loadedSvgContent: string): void}) { + // static since all IonIcons use this same function and pointing at global/shared data + // passed in callback will have instance info + + // add to the list of callbacks to fiure when this url is finished loading + loadCallbacks[svgUrl] = loadCallbacks[svgUrl] || []; + loadCallbacks[svgUrl].push(callback); + + if (activeRequests[svgUrl]) { + // already requesting this url, don't bother again kicking off another + return; + } + + // add this url to our list of active requests + activeRequests[svgUrl] = true; + + // kick off the request for the external svg file + const xhr = new XMLHttpRequest(); + xhr.addEventListener('load', function() { + // awesome, we've finished loading the svg file + + // remove this url from the active requests + delete activeRequests[svgUrl]; + + // this response is the content of the svg file we're looking for + let svgContent = this.responseText; + + if (this.status >= 400) { + // umm, not awesome, something is up + console.error('Icon could not be loaded:', svgUrl); + svgContent = ``; + } + + // cache the svg content in the global IonIcon constant + svgContents[svgUrl] = svgContent; + + // find any callbacks waiting on this url + const svgLoadCallbacks = loadCallbacks[svgUrl]; + if (svgLoadCallbacks) { + // loop through all the callbacks that are waiting on the svg content + svgLoadCallbacks.forEach(cb => { + // fire off this callback which was provided by an instance + cb(svgContent); + }); + delete loadCallbacks[svgUrl]; + } + }); + + xhr.addEventListener('error', () => { + // umm, idk + console.error('Icon could not be loaded:', svgUrl); + }); + + // let's do this! + xhr.open('GET', svgUrl, true); + xhr.send(); +} + + +const activeRequests: {[url: string]: boolean} = {}; +const loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]} = [] as any; +const svgContents: {[url: string]: string} = {}; diff --git a/packages/core/src/components/item/item.ios.scss b/packages/core/src/components/item/item.ios.scss index 4de5455c23..6c4d11a704 100644 --- a/packages/core/src/components/item/item.ios.scss +++ b/packages/core/src/components/item/item.ios.scss @@ -47,15 +47,6 @@ $item-ios-detail-push-color: $list-ios-border-color !default; /// @prop - Icon for the detail arrow $item-ios-detail-push-svg: "" !default; -/// @prop - Background for the divider -$item-ios-divider-background: #f7f7f7 !default; - -/// @prop - Color for the divider -$item-ios-divider-color: #222 !default; - -/// @prop - Padding for the divider -$item-ios-divider-padding: 5px 15px !default; - // iOS Item // -------------------------------------------------- diff --git a/packages/core/src/components/item/item.md.scss b/packages/core/src/components/item/item.md.scss index 1dd1800f38..3dadbc067b 100644 --- a/packages/core/src/components/item/item.md.scss +++ b/packages/core/src/components/item/item.md.scss @@ -35,21 +35,6 @@ $item-md-detail-push-color: $list-md-border-color !default; /// @prop - Icon for the detail arrow $item-md-detail-push-svg: "" !default; -/// @prop - Color for the divider -$item-md-divider-color: #858585 !default; - -/// @prop - Background for the divider -$item-md-divider-background: #fff !default; - -/// @prop - Font size for the divider -$item-md-divider-font-size: $item-md-body-text-font-size !default; - -/// @prop - Border bottom for the divider -$item-md-divider-border-bottom: 1px solid $list-md-border-color !default; - -/// @prop - Padding for the divider -$item-md-divider-padding: 5px 15px !default; - .item-md { @include padding-horizontal($item-md-padding-start, 0); diff --git a/packages/core/src/components/item/item.scss b/packages/core/src/components/item/item.scss index 29cb451705..702ee852cb 100644 --- a/packages/core/src/components/item/item.scss +++ b/packages/core/src/components/item/item.scss @@ -86,3 +86,14 @@ ion-input.item { align-items: flex-start; } +.item-cover { + @include position(0, null, null, 0); + + position: absolute; + + width: 100%; + height: 100%; + + background: transparent; + cursor: pointer; +} diff --git a/packages/core/src/components/item/item.wp.scss b/packages/core/src/components/item/item.wp.scss index 2c4aae6796..07b926625a 100644 --- a/packages/core/src/components/item/item.wp.scss +++ b/packages/core/src/components/item/item.wp.scss @@ -41,21 +41,6 @@ $item-wp-detail-push-color: $input-wp-border-color !default; /// @prop - Icon for the detail arrow $item-wp-detail-push-svg: "" !default; -/// @prop - Color for the divider -$item-wp-divider-color: $list-wp-text-color !default; - -/// @prop - Background for the divider -$item-wp-divider-background: #fff !default; - -/// @prop - Bodrer bottom for the divider -$item-wp-divider-border-bottom: 1px solid $list-wp-border-color !default; - -/// @prop - Font size for the divider -$item-wp-divider-font-size: 2rem !default; - -/// @prop - Padding for the divider -$item-wp-divider-padding: 5px 15px !default; - .item-wp { @include padding-horizontal($item-wp-padding-start, 0); diff --git a/packages/core/src/components/list-header/list-header.ios.scss b/packages/core/src/components/list-header/list-header.ios.scss index b665830d2d..902fd8900a 100644 --- a/packages/core/src/components/list-header/list-header.ios.scss +++ b/packages/core/src/components/list-header/list-header.ios.scss @@ -5,10 +5,8 @@ // iOS List Header // -------------------------------------------------- -// deprecated -$list-ios-header-padding-left: $item-ios-padding-start !default; /// @prop - Padding start of the header in a list -$list-ios-header-padding-start: $list-ios-header-padding-left !default; +$list-ios-header-padding-start: $item-ios-padding-start !default; /// @prop - Border bottom of the header in a list $list-ios-header-border-bottom: $hairlines-width solid $list-ios-border-color !default; diff --git a/packages/core/src/components/list-header/list-header.md.scss b/packages/core/src/components/list-header/list-header.md.scss index 857936f299..89c20bffec 100644 --- a/packages/core/src/components/list-header/list-header.md.scss +++ b/packages/core/src/components/list-header/list-header.md.scss @@ -1,4 +1,4 @@ -@import "../../themes/ionic.globals.ios"; +@import "../../themes/ionic.globals.md"; @import "./list-header"; // Material Design List Header @@ -7,10 +7,8 @@ /// @prop - Margin bottom of the header in a list $list-md-header-margin-bottom: 13px !default; -// deprecated -$list-md-header-padding-left: $item-md-padding-start !default; /// @prop - Padding start of the header in a list -$list-md-header-padding-start: $list-md-header-padding-left !default; +$list-md-header-padding-start: $item-md-padding-start !default; /// @prop - Minimum height of the header in a list $list-md-header-min-height: 4.5rem !default; diff --git a/packages/core/src/components/list-header/list-header.tsx b/packages/core/src/components/list-header/list-header.tsx index 50890e45bb..463cf72619 100644 --- a/packages/core/src/components/list-header/list-header.tsx +++ b/packages/core/src/components/list-header/list-header.tsx @@ -3,6 +3,11 @@ import { Component } from '@stencil/core'; @Component({ tag: 'ion-list-header', + styleUrls: { + ios: 'list-header.ios.scss', + md: 'list-header.md.scss', + wp: 'list-header.wp.scss' + }, host: { theme: 'list-header' } diff --git a/packages/core/src/components/list-header/list-header.wp.scss b/packages/core/src/components/list-header/list-header.wp.scss index 0e45f28a2f..71fefb7e4c 100644 --- a/packages/core/src/components/list-header/list-header.wp.scss +++ b/packages/core/src/components/list-header/list-header.wp.scss @@ -4,10 +4,8 @@ // Windows List Header // -------------------------------------------------- -// deprecated -$list-wp-header-padding-left: $item-wp-padding-start !default; /// @prop - Padding start of the header in a list -$list-wp-header-padding-start: $list-wp-header-padding-left !default; +$list-wp-header-padding-start: $item-wp-padding-start !default; /// @prop - Border bottom of the header in a list $list-wp-header-border-bottom: 1px solid $list-wp-border-color !default; diff --git a/packages/core/src/components/segment-button/segment-button.tsx b/packages/core/src/components/segment-button/segment-button.tsx index 5de2d6d60c..c8dee0305f 100644 --- a/packages/core/src/components/segment-button/segment-button.tsx +++ b/packages/core/src/components/segment-button/segment-button.tsx @@ -1,7 +1,7 @@ -import { Component, Event, EventEmitter, Prop, State } from '@stencil/core'; +import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core'; import { CssClassMap } from '../../index'; -import { createThemedClasses } from '../../utils/theme'; +import { createThemedClasses, getElementClassObject } from '../../utils/theme'; /** @@ -49,6 +49,8 @@ export class SegmentButton { mode: string; color: string; + @Element() el: HTMLElement; + @Event() ionClick: EventEmitter; @State() activated: boolean = false; @@ -92,7 +94,7 @@ export class SegmentButton { /** * @hidden - * Get the element classes to add to the child element + * Get the classes for the segment button state */ getElementClassList() { let classList = [].concat( @@ -104,9 +106,10 @@ export class SegmentButton { } render() { - const segmentButtonCss = createThemedClasses(this.mode, this.color, 'segment-button'); + const themedClasses = createThemedClasses(this.mode, this.color, 'segment-button'); + const hostClasses = getElementClassObject(this.el.classList); - var segmentButtonClasses: CssClassMap = [] + const elementClasses: CssClassMap = [] .concat( this.getElementClassList() ) @@ -115,10 +118,14 @@ export class SegmentButton { return prevValue; }, {}); - segmentButtonClasses = Object.assign(segmentButtonClasses, segmentButtonCss); + const buttonClasses = { + ...themedClasses, + ...hostClasses, + ...elementClasses + }; return [ - ]; diff --git a/packages/core/src/components/select/option.tsx b/packages/core/src/components/select/option.tsx new file mode 100644 index 0000000000..19e2e544fc --- /dev/null +++ b/packages/core/src/components/select/option.tsx @@ -0,0 +1,16 @@ +import { Component } from '@stencil/core'; + + +@Component({ + tag: 'ion-option', + host: { + theme: 'option' + } +}) +export class option { + + render() { + return
; + } + +} \ No newline at end of file diff --git a/packages/core/src/components/select/select.ios.scss b/packages/core/src/components/select/select.ios.scss new file mode 100644 index 0000000000..be13730339 --- /dev/null +++ b/packages/core/src/components/select/select.ios.scss @@ -0,0 +1,56 @@ +@import "../../themes/ionic.globals.ios"; +@import "./select"; + +// iOS Select +// -------------------------------------------------- + +/// @prop - Padding top of the select +$select-ios-padding-top: $item-ios-padding-top !default; + +/// @prop - Padding end of the select +$select-ios-padding-end: ($item-ios-padding-end / 2) !default; + +/// @prop - Padding bottom of the select +$select-ios-padding-bottom: $item-ios-padding-bottom !default; + +/// @prop - Padding start of the select +$select-ios-padding-start: $item-ios-padding-start !default; + +/// @prop - Color of the select icon +$select-ios-icon-color: #999 !default; + +/// @prop - Color of the select placeholder +$select-ios-placeholder-color: $select-ios-icon-color !default; + + +.select-ios { + @include padding($select-ios-padding-top, $select-ios-padding-end, $select-ios-padding-bottom, $select-ios-padding-start); +} + +.select-ios .select-placeholder { + color: $select-ios-placeholder-color; +} + +.select-ios .select-icon { + position: relative; + + width: 12px; + height: 18px; +} + +.select-ios .select-icon .select-icon-inner { + @include position(50%, null, null, 5px); + @include margin(-2px, null, null, null); + + position: absolute; + + width: 0; + height: 0; + + border-top: 5px solid; + border-right: 5px solid transparent; + border-left: 5px solid transparent; + color: $select-ios-icon-color; + + pointer-events: none; +} diff --git a/packages/core/src/components/select/select.md.scss b/packages/core/src/components/select/select.md.scss new file mode 100644 index 0000000000..ea2f6f2468 --- /dev/null +++ b/packages/core/src/components/select/select.md.scss @@ -0,0 +1,60 @@ +@import "../../themes/ionic.globals.md"; +@import "./select"; + +// Material Design Select +// -------------------------------------------------- + +/// @prop - Padding top of the select +$select-md-padding-top: $item-md-padding-top !default; + +/// @prop - Padding end of the select +$select-md-padding-end: ($item-md-padding-end / 2) !default; + +/// @prop - Padding bottom of the select +$select-md-padding-bottom: $item-md-padding-bottom !default; + +/// @prop - Padding start of the select +$select-md-padding-start: $item-md-padding-start !default; + +/// @prop - Color of the select icon +$select-md-icon-color: #999 !default; + +/// @prop - Color of the select placeholder +$select-md-placeholder-color: $select-md-icon-color !default; + + +.select-md { + @include padding($select-md-padding-top, $select-md-padding-end, $select-md-padding-bottom, $select-md-padding-start); +} + +.select-md .select-placeholder { + color: $select-md-placeholder-color; +} + +.select-md .item-select ion-label { + @include margin-horizontal(0, null); +} + +.select-md .select-icon { + position: relative; + + width: 12px; + height: 19px; +} + +.select-md .select-icon .select-icon-inner { + @include position(50%, null, null, 5px); + @include margin(-3px, null, null, null); + + position: absolute; + + width: 0; + height: 0; + + border-top: 5px solid; + border-right: 5px solid transparent; + border-left: 5px solid transparent; + color: $select-md-icon-color; + + pointer-events: none; +} diff --git a/packages/core/src/components/select/select.scss b/packages/core/src/components/select/select.scss new file mode 100644 index 0000000000..dcd429f952 --- /dev/null +++ b/packages/core/src/components/select/select.scss @@ -0,0 +1,56 @@ +@import "../../themes/ionic.globals"; + +// Select +// -------------------------------------------------- + +/// @prop - Margin top of the select popover list +$select-popover-list-margin-top: -1px !default; + +/// @prop - Margin end of the select popover list +$select-popover-list-margin-end: 0 !default; + +/// @prop - Margin bottom of the select popover list +$select-popover-list-margin-bottom: -1px !default; + +/// @prop - Margin start of the select popover list +$select-popover-list-margin-start: 0 !default; + + +ion-select { + display: flex; + overflow: hidden; + + max-width: 45%; +} + +.select-text { + overflow: hidden; + + flex: 1; + + min-width: 16px; + + font-size: inherit; + text-overflow: ellipsis; + white-space: nowrap; +} + +.item-multiple-inputs ion-select { + position: relative; +} + +.select-disabled, +.item-select-disabled ion-label { + opacity: .4; + + pointer-events: none; +} + +.select-popover ion-list { + @include margin($select-popover-list-margin-top, $select-popover-list-margin-end, $select-popover-list-margin-bottom, $select-popover-list-margin-start); +} + +// TODO remove +.select .option { + display: none; +} \ No newline at end of file diff --git a/packages/core/src/components/select/select.tsx b/packages/core/src/components/select/select.tsx new file mode 100644 index 0000000000..ab4760bd46 --- /dev/null +++ b/packages/core/src/components/select/select.tsx @@ -0,0 +1,365 @@ +import { Component, CssClassMap, Event, EventEmitter, Prop } from '@stencil/core'; + + +@Component({ + tag: 'ion-select', + styleUrls: { + ios: 'select.ios.scss', + md: 'select.md.scss', + wp: 'select.wp.scss' + }, + host: { + theme: 'select' + } +}) +export class Select { + text: any; + id: any; + labelId: any; + + /** + * @input {boolean} If true, the user cannot interact with this element. Defaults to `false`. + */ + @Prop() disabled: boolean = false; + + /** + * @input {string} The text to display on the cancel button. Default: `Cancel`. + */ + @Prop() cancelText: string = 'Cancel'; + + /** + * @input {string} The text to display on the ok button. Default: `OK`. + */ + @Prop() okText: string = 'OK'; + + /** + * @input {string} The text to display when the select is empty. + */ + @Prop() placeholder: string; + + /** + * @input {any} Any additional options that the `alert` or `action-sheet` interface can take. + * See the [AlertController API docs](../../alert/AlertController/#create) and the + * [ActionSheetController API docs](../../action-sheet/ActionSheetController/#create) for the + * create options for each interface. + */ + @Prop() selectOptions: any = {}; + + /** + * @input {string} The interface the select should use: `action-sheet`, `popover` or `alert`. Default: `alert`. + */ + @Prop() interface: string = ''; + + /** + * @input {string} The text to display instead of the selected option's value. + */ + @Prop() selectedText: string; + + /** + * @input {boolean} If true, the element can accept multiple values. + */ + @Prop() multiple: boolean; + + /** + * @output {EventEmitter} Emitted when the selection is cancelled. + */ + @Event() ionCancel: EventEmitter; + + + hostData() { + return { + class: { + 'select-disabled': this.disabled + } + }; + } + + render() { + let addPlaceholderClass = false + + let selectText = this.selectedText || this.text; + if (!selectText && this.placeholder) { + selectText = this.placeholder; + addPlaceholderClass = true; + } + + const selectTextClasses: CssClassMap = { + 'select-text': true, + 'select-placeholder': addPlaceholderClass + }; + + return [ + // add placeholder class +
{ selectText }
, +
+
+
, + + ]; + } + +} + +// export class Select extends BaseInput implements OnDestroy { + +// _options: QueryList