diff --git a/.github/COMPONENT-GUIDE.md b/.github/COMPONENT-GUIDE.md index ad0d240ffa..7e710592b0 100644 --- a/.github/COMPONENT-GUIDE.md +++ b/.github/COMPONENT-GUIDE.md @@ -17,6 +17,7 @@ * [Example Components](#example-components-1) * [Component Structure](#component-structure-1) - [Converting Scoped to Shadow](#converting-scoped-to-shadow) +- [RTL](#rtl) ## Button States @@ -717,3 +718,39 @@ There will be some CSS issues when converting to shadow. Below are some of the d /* IN SHADOW*/ :host-context(ion-toolbar:not(.ion-color)):host(:not(.ion-color)) ::slotted(ion-segment-button) { ``` + +## RTL + +When you need to support both LTR and RTL modes, try to avoid using values such as `left` and `right`. For certain CSS properties, you can use the appropriate mixin to have this handled for you automatically. + +For example, if you wanted `transform-origin` to be RTL-aware, you would use the `transform-origin` mixin: + +```css +@include transform-origin(start, center); +``` + +This would output `transform-origin: left center` in LTR mode and `transform-origin: right center` in RTL mode. + +These mixins depend on the `:host-context` pseudo-class when used inside of shadow components, which is not supported in WebKit. As a result, these mixins will not work in Safari for macOS and iOS when applied to shadow components. + +To work around this, you should set an RTL class on the host of your component and set your RTL styles by targeting that class: + +```tsx + + ... + +``` + +```css +:host { + transform-origin: left center; +} + +:host(.my-cmp-rtl) { + transform-origin: right center; +} +``` \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b77584e9..90379b29bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## [5.6.9](https://github.com/ionic-team/ionic/compare/v5.6.8...v5.6.9) (2021-06-08) + + +### Bug Fixes + +* **modal:** swipe to close modal is no longer swipeable on footer ([#23401](https://github.com/ionic-team/ionic/issues/23401)) ([ae96563](https://github.com/ionic-team/ionic/commit/ae96563fb3c4612cb8585292b389ee746f5759f7)), closes [#23398](https://github.com/ionic-team/ionic/issues/23398) +* **title:** inherit padding for iOS title in a toolbar ([#23343](https://github.com/ionic-team/ionic/issues/23343)) ([82cfa55](https://github.com/ionic-team/ionic/commit/82cfa5565347704b0e9f7dac792ed2aa6dd30505)), closes [#23072](https://github.com/ionic-team/ionic/issues/23072) +* **vue:** improve v-model integration for Vue 3.1.0+ ([#23420](https://github.com/ionic-team/ionic/issues/23420)) ([f008628](https://github.com/ionic-team/ionic/commit/f0086288512bd7f7d1929d79bfd8bf702efc732e)) +* **vue:** prevent error from being thrown when testing on certain jest runners ([#23421](https://github.com/ionic-team/ionic/issues/23421)) ([60bedb5](https://github.com/ionic-team/ionic/commit/60bedb5599b286bffccfc54c4861a269d9b8df73)), closes [#23397](https://github.com/ionic-team/ionic/issues/23397) + + + +## [5.6.8](https://github.com/ionic-team/ionic/compare/v5.6.7...v5.6.8) (2021-05-27) + + +### Bug Fixes + +* **action-sheet:** subheader no longer overlaps action sheet buttons ([#23318](https://github.com/ionic-team/ionic/issues/23318)) ([d473a53](https://github.com/ionic-team/ionic/commit/d473a5385108ef5f39d7c9a2b2924e89fec631de)), closes [#23316](https://github.com/ionic-team/ionic/issues/23316) +* **all:** reflect color property as an attribute for vue ([#23345](https://github.com/ionic-team/ionic/issues/23345)) ([dc430af](https://github.com/ionic-team/ionic/commit/dc430af906c608f948c8d404ad73ae0e0ac36076)), closes [#23323](https://github.com/ionic-team/ionic/issues/23323) +* **range:** knob can now have an accessible name ([#23338](https://github.com/ionic-team/ionic/issues/23338)) ([881dcff](https://github.com/ionic-team/ionic/commit/881dcff40b8bdcb07b27d4ee812ce4ee64b6ea9a)), closes [#23295](https://github.com/ionic-team/ionic/issues/23295) +* **react:** remove @ionic/core dependency in @ionic/react-router to resolve yarn install warning ([#23351](https://github.com/ionic-team/ionic/issues/23351)) ([36bfa33](https://github.com/ionic-team/ionic/commit/36bfa3350354e09be6c62f4e4bee0c553c5981a3)), closes [#23346](https://github.com/ionic-team/ionic/issues/23346) +* **react:** support history@5 in preparation for react router 6 ([#23297](https://github.com/ionic-team/ionic/issues/23297)) ([4da5216](https://github.com/ionic-team/ionic/commit/4da5216b4f65f3d893cc81ebee77261835218f7f)), closes [#23294](https://github.com/ionic-team/ionic/issues/23294) +* **router:** guards are now triggered on initial navigation ([#23123](https://github.com/ionic-team/ionic/issues/23123)) ([56f6f56](https://github.com/ionic-team/ionic/commit/56f6f56c6665f40ea6bf41be463cd416883359f7)), closes [#22936](https://github.com/ionic-team/ionic/issues/22936) +* **router:** redirects now account for query string ([#23337](https://github.com/ionic-team/ionic/issues/23337)) ([08a9f3a](https://github.com/ionic-team/ionic/commit/08a9f3ac94685c5782dd2fa6b56bf3448729a768)), closes [#23136](https://github.com/ionic-team/ionic/issues/23136) +* **skeleton-text:** animation no longer jumps on large skeleton text elements ([#22697](https://github.com/ionic-team/ionic/issues/22697)) ([1a36922](https://github.com/ionic-team/ionic/commit/1a36922f41f2890c778feedbad9c5b74a72a3907)), closes [#22694](https://github.com/ionic-team/ionic/issues/22694) +* **slides:** resolve prototype pollution in swiper v5 ([#23344](https://github.com/ionic-team/ionic/issues/23344)) ([a708c41](https://github.com/ionic-team/ionic/commit/a708c412625cba475ec7863468dcc2146b8feb7a)), closes [#23342](https://github.com/ionic-team/ionic/issues/23342) +* **title:** large title scale animation is now correct in rtl mode ([#23372](https://github.com/ionic-team/ionic/issues/23372)) ([3d474ec](https://github.com/ionic-team/ionic/commit/3d474ec67ff4192fa3d08e370e20fecbee99a6aa)), closes [#23371](https://github.com/ionic-team/ionic/issues/23371) + + + ## [5.6.7](https://github.com/ionic-team/ionic/compare/v5.6.6...v5.6.7) (2021-05-13) diff --git a/angular/package-lock.json b/angular/package-lock.json index 5ac75559c7..cc018bd375 100644 --- a/angular/package-lock.json +++ b/angular/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/angular", - "version": "5.6.7", + "version": "5.6.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/angular", - "version": "5.6.7", + "version": "5.6.9", "license": "MIT", "dependencies": { - "@ionic/core": "5.6.6", + "@ionic/core": "5.6.8", "tslib": "^1.9.3" }, "devDependencies": { @@ -204,9 +204,9 @@ } }, "node_modules/@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "dependencies": { "@stencil/core": "^2.4.0", "ionicons": "^5.5.1", @@ -5156,9 +5156,9 @@ } }, "@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "requires": { "@stencil/core": "^2.4.0", "ionicons": "^5.5.1", diff --git a/angular/package.json b/angular/package.json index b0b75c4a3f..08a52fe241 100644 --- a/angular/package.json +++ b/angular/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/angular", - "version": "5.6.7", + "version": "5.6.9", "description": "Angular specific wrappers for @ionic/core", "keywords": [ "ionic", @@ -42,7 +42,7 @@ "validate": "npm i && npm run lint && npm run test && npm run build" }, "dependencies": { - "@ionic/core": "5.6.7", + "@ionic/core": "5.6.9", "tslib": "^1.9.3" }, "peerDependencies": { diff --git a/angular/src/providers/platform.ts b/angular/src/providers/platform.ts index c757075af3..38b04a0f15 100644 --- a/angular/src/providers/platform.ts +++ b/angular/src/providers/platform.ts @@ -209,7 +209,7 @@ export class Platform { } /** - * Returns `true` if the app is in portait mode. + * Returns `true` if the app is in portrait mode. */ isPortrait(): boolean { return this.win.matchMedia && this.win.matchMedia('(orientation: portrait)').matches; diff --git a/core/package-lock.json b/core/package-lock.json index 5260ec2112..322a6d9783 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ionic/core", - "version": "5.7.0-dev.202106081605.0bc250e", + "version": "5.6.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/core", - "version": "5.7.0-dev.202106081605.0bc250e", + "version": "5.6.9", "license": "MIT", "dependencies": { "@stencil/core": "^2.6.0", diff --git a/core/package.json b/core/package.json index 53aed53553..dd53ee23c5 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/core", - "version": "5.6.7", + "version": "5.6.9", "description": "Base components for Ionic", "keywords": [ "ionic", diff --git a/core/src/components/button/button.md.scss b/core/src/components/button/button.md.scss index f01520a164..a8493a2dbf 100644 --- a/core/src/components/button/button.md.scss +++ b/core/src/components/button/button.md.scss @@ -129,30 +129,29 @@ // Material Design Button: Hover // -------------------------------------------------- +/** + * Only allow overriding of opacity here + * as developers should not be overriding + * colors when using the color prop. + */ + :host(.button-solid.ion-color.ion-focused) .button-native::after { background: #{current-color(contrast)}; - - opacity: .24; } :host(.button-clear.ion-color.ion-focused) .button-native::after, :host(.button-outline.ion-color.ion-focused) .button-native::after { background: #{current-color(base)}; - - opacity: .12; } + @media (any-hover: hover) { :host(.button-solid.ion-color:hover) .button-native::after { background: #{current-color(contrast)}; - - opacity: .08; } :host(.button-clear.ion-color:hover) .button-native::after, :host(.button-outline.ion-color:hover) .button-native::after { background: #{current-color(base)}; - - opacity: .04; } } diff --git a/core/src/components/button/test/outline/index.html b/core/src/components/button/test/outline/index.html index 27db3c617a..0383bcb93a 100644 --- a/core/src/components/button/test/outline/index.html +++ b/core/src/components/button/test/outline/index.html @@ -90,6 +90,7 @@ Dark.focused Dark.activated.focused

+

Disabled Secondary Disabled diff --git a/core/src/components/button/test/states/index.html b/core/src/components/button/test/states/index.html index acfb1e16fd..9bff07e624 100644 --- a/core/src/components/button/test/states/index.html +++ b/core/src/components/button/test/states/index.html @@ -89,6 +89,31 @@ Outline Clear

+ +
+ Button + Button + Button + +
+ + Button + Button + Button + +
+ + Button + Button + Button + +
+ + Button + Button + Button +
+ @@ -110,6 +135,17 @@ .custom { --color: red; } + + .custom-variables ion-button { + --color: black; + + --background: pink; + --background-focused: red; + --background-hover: green; + + --background-focused-opacity: .5; + --background-hover-opacity: .5; + } diff --git a/core/src/components/item/item.tsx b/core/src/components/item/item.tsx index 608abd0830..0a981ee3a8 100644 --- a/core/src/components/item/item.tsx +++ b/core/src/components/item/item.tsx @@ -207,7 +207,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac } componentDidLoad() { - this.setMultipleInputs(); + raf(() => this.setMultipleInputs()); } // If the item contains multiple clickable elements and/or inputs, then the item diff --git a/core/src/components/modal/gestures/swipe-to-close.ts b/core/src/components/modal/gestures/swipe-to-close.ts index e39f05473c..5f4715dc5f 100644 --- a/core/src/components/modal/gestures/swipe-to-close.ts +++ b/core/src/components/modal/gestures/swipe-to-close.ts @@ -24,11 +24,11 @@ export const createSwipeToCloseGesture = ( return true; } - const content = target.closest('ion-content'); - if (content === null) { + const contentOrFooter = target.closest('ion-content, ion-footer'); + if (contentOrFooter === null) { return true; } - // Target is in the content so we don't start the gesture. + // Target is in the content or the footer so do not start the gesture. // We could be more nuanced here and allow it for content that // does not need to scroll. return false; diff --git a/core/src/components/modal/test/custom/index.html b/core/src/components/modal/test/custom/index.html index 1f7fa7cf5e..978a1ec72e 100644 --- a/core/src/components/modal/test/custom/index.html +++ b/core/src/components/modal/test/custom/index.html @@ -3,7 +3,7 @@ - Modal - Basic + Modal - Custom @@ -11,22 +11,27 @@ @@ -35,7 +40,7 @@ - Modal - Basic + Modal - Custom @@ -55,13 +60,23 @@ element.innerHTML = ` + + + + + Super Modal + + + Close + +

Content of doom

Here's some more content
- Dismiss Modal + Dismiss Modal
`; @@ -72,10 +87,12 @@ }); // listen for close event - const button = element.querySelector('ion-button'); - button.addEventListener('click', () => { - modalElement.dismiss(); - }); + const buttons = element.querySelectorAll('.dismiss'); + for (var button of buttons) { + button.addEventListener('click', () => { + modalElement.dismiss(); + }); + } document.body.appendChild(modalElement); return modalElement; } diff --git a/core/src/components/popover/readme.md b/core/src/components/popover/readme.md index f26046ee06..af22da4d6c 100644 --- a/core/src/components/popover/readme.md +++ b/core/src/components/popover/readme.md @@ -490,8 +490,8 @@ export default defineComponent({ setup() { const isOpenRef = ref(false); const event = ref(); - const setOpen = (state: boolean, event?: Event) => { - event.value = event; + const setOpen = (state: boolean, ev?: Event) => { + event.value = ev; isOpenRef.value = state; } return { isOpenRef, setOpen, event } diff --git a/core/src/components/popover/usage/vue.md b/core/src/components/popover/usage/vue.md index 85ced6c2c6..516fd867b0 100644 --- a/core/src/components/popover/usage/vue.md +++ b/core/src/components/popover/usage/vue.md @@ -76,8 +76,8 @@ export default defineComponent({ setup() { const isOpenRef = ref(false); const event = ref(); - const setOpen = (state: boolean, event?: Event) => { - event.value = event; + const setOpen = (state: boolean, ev?: Event) => { + event.value = ev; isOpenRef.value = state; } return { isOpenRef, setOpen, event } diff --git a/core/src/components/radio-group/radio-group.tsx b/core/src/components/radio-group/radio-group.tsx index 8f9ed6a693..d5c67b00cd 100644 --- a/core/src/components/radio-group/radio-group.tsx +++ b/core/src/components/radio-group/radio-group.tsx @@ -107,7 +107,7 @@ export class RadioGroup implements ComponentInterface { // Get all radios inside of the radio group and then // filter out disabled radios since we need to skip those - const radios = Array.from(this.el.querySelectorAll('ion-radio')).filter(radio => !radio.disabled); + const radios = this.getRadios().filter(radio => !radio.disabled); // Only move the radio if the current focus is in the radio group if (ev.target && radios.includes(ev.target)) { diff --git a/core/src/components/router/router.tsx b/core/src/components/router/router.tsx index 45e00d3718..bcb29e3fe4 100644 --- a/core/src/components/router/router.tsx +++ b/core/src/components/router/router.tsx @@ -2,6 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Me import { AnimationBuilder, BackButtonEvent, RouteChain, RouterDirection, RouterEventDetail } from '../../interface'; import { debounce } from '../../utils/helpers'; +import { NavigationHookResult } from '../route/route-interface'; import { ROUTER_INTENT_BACK, ROUTER_INTENT_FORWARD, ROUTER_INTENT_NONE } from './utils/constants'; import { printRedirects, printRoutes } from './utils/debug'; @@ -186,6 +187,7 @@ export class Router implements ComponentInterface { return true; } + // This handler gets called when a `ion-route-redirect` component is added to the DOM or if the from or to property of such node changes. private onRedirectChanged() { const path = this.getPath(); if (path && findRouteRedirect(path, readRedirects(this.el))) { @@ -193,6 +195,7 @@ export class Router implements ComponentInterface { } } + // This handler gets called when a `ion-route` component is added to the DOM or if the from or to property of such node changes. private onRoutesChanged() { return this.writeNavStateRoot(this.getPath(), ROUTER_INTENT_NONE); } @@ -202,7 +205,7 @@ export class Router implements ComponentInterface { if (win.history.state === null) { this.state++; - win.history.replaceState(this.state, win.document.title, win.document.location && win.document.location.href); + win.history.replaceState(this.state, win.document.title, win.document.location?.href); } const state = win.history.state; @@ -211,11 +214,11 @@ export class Router implements ComponentInterface { if (state > lastState || (state >= lastState && lastState > 0)) { return ROUTER_INTENT_FORWARD; - } else if (state < lastState) { - return ROUTER_INTENT_BACK; - } else { - return ROUTER_INTENT_NONE; } + if (state < lastState) { + return ROUTER_INTENT_BACK; + } + return ROUTER_INTENT_NONE; } private async writeNavStateRoot(path: string[] | null, direction: RouterDirection, animation?: AnimationBuilder): Promise { @@ -281,7 +284,7 @@ export class Router implements ComponentInterface { // // When the beforeLeave hook does not return true (to allow navigating) then that value is returned early and the beforeEnter is executed. // Otherwise the beforeEnterHook hook of the target route is executed. - private async runGuards(to: string[] | null = this.getPath(), from?: string[] | null) { + private async runGuards(to: string[] | null = this.getPath(), from?: string[] | null): Promise { if (from === undefined) { from = parsePath(this.previousPath).segments; } diff --git a/core/src/components/router/utils/dom.ts b/core/src/components/router/utils/dom.ts index 1f4f3e6f3c..c2f724062a 100644 --- a/core/src/components/router/utils/dom.ts +++ b/core/src/components/router/utils/dom.ts @@ -88,5 +88,5 @@ const searchNavNode = (root: HTMLElement | undefined): NavOutletElement | undefi return root as NavOutletElement; } const outlet = root.querySelector(QUERY); - return outlet ? outlet : undefined; + return outlet ?? undefined; }; diff --git a/core/src/components/router/utils/parser.ts b/core/src/components/router/utils/parser.ts index 3af2ffc203..e749c897b8 100644 --- a/core/src/components/router/utils/parser.ts +++ b/core/src/components/router/utils/parser.ts @@ -1,6 +1,16 @@ import { RouteChain, RouteNode, RouteRedirect, RouteTree } from './interface'; import { parsePath } from './path'; +const readProp = (el: HTMLElement, prop: string): string | null | undefined => { + if (prop in el) { + return (el as any)[prop]; + } + if (el.hasAttribute(prop)) { + return el.getAttribute(prop); + } + return null; +}; + export const readRedirects = (root: Element): RouteRedirect[] => { return (Array.from(root.children) as HTMLIonRouteRedirectElement[]) .filter(el => el.tagName === 'ION-ROUTE-REDIRECT') @@ -17,46 +27,33 @@ export const readRoutes = (root: Element): RouteChain[] => { return flattenRouterTree(readRouteNodes(root)); }; -export const readRouteNodes = (root: Element, node = root): RouteTree => { +export const readRouteNodes = (node: Element): RouteTree => { return (Array.from(node.children) as HTMLIonRouteElement[]) .filter(el => el.tagName === 'ION-ROUTE' && el.component) .map(el => { - const component = readProp(el, 'component'); - if (component == null) { - throw new Error('component missing in ion-route'); - } + const component = readProp(el, 'component') as string; return { path: parsePath(readProp(el, 'url')).segments, id: component.toLowerCase(), params: el.componentProps, beforeLeave: el.beforeLeave, beforeEnter: el.beforeEnter, - children: readRouteNodes(root, el) + children: readRouteNodes(el) }; }); }; -export const readProp = (el: HTMLElement, prop: string): string | null | undefined => { - if (prop in el) { - return (el as any)[prop]; - } - if (el.hasAttribute(prop)) { - return el.getAttribute(prop); - } - return null; -}; - export const flattenRouterTree = (nodes: RouteTree): RouteChain[] => { - const routes: RouteChain[] = []; + const chains: RouteChain[] = []; for (const node of nodes) { - flattenNode([], routes, node); + flattenNode([], chains, node); } - return routes; + return chains; }; -const flattenNode = (chain: RouteChain, routes: RouteChain[], node: RouteNode) => { - const s = chain.slice(); - s.push({ +const flattenNode = (chain: RouteChain, chains: RouteChain[], node: RouteNode) => { + chain = chain.slice(); + chain.push({ id: node.id, path: node.path, params: node.params, @@ -65,10 +62,10 @@ const flattenNode = (chain: RouteChain, routes: RouteChain[], node: RouteNode) = }); if (node.children.length === 0) { - routes.push(s); + chains.push(chain); return; } - for (const sub of node.children) { - flattenNode(s, routes, sub); + for (const child of node.children) { + flattenNode(chain, chains, child); } }; diff --git a/core/src/components/router/utils/path.ts b/core/src/components/router/utils/path.ts index 588fcd2097..e4fae43860 100644 --- a/core/src/components/router/utils/path.ts +++ b/core/src/components/router/utils/path.ts @@ -1,6 +1,7 @@ import { ROUTER_INTENT_FORWARD } from './constants'; import { ParsedRoute, RouteChain, RouterDirection } from './interface'; +// Join the non empty segments with "/". export const generatePath = (segments: string[]): string => { const path = segments .filter(s => s.length > 0) @@ -9,6 +10,26 @@ export const generatePath = (segments: string[]): string => { return '/' + path; }; +const generateUrl = (segments: string[], useHash: boolean, queryString?: string) => { + let url = generatePath(segments); + if (useHash) { + url = '#' + url; + } + if (queryString !== undefined) { + url += '?' + queryString; + } + return url; +} + +export const writePath = (history: History, root: string, useHash: boolean, path: string[], direction: RouterDirection, state: number, queryString?: string) => { + const url = generateUrl([...parsePath(root).segments, ...path], useHash, queryString); + if (direction === ROUTER_INTENT_FORWARD) { + history.pushState(state, '', url); + } else { + history.replaceState(state, '', url); + } +}; + export const chainToPath = (chain: RouteChain): string[] | null => { const path = []; for (const route of chain) { @@ -27,25 +48,12 @@ export const chainToPath = (chain: RouteChain): string[] | null => { return path; }; -export const writePath = (history: History, root: string, useHash: boolean, path: string[], direction: RouterDirection, state: number, queryString?: string) => { - let url = generatePath([ - ...parsePath(root).segments, - ...path - ]); - if (useHash) { - url = '#' + url; - } - if (queryString !== undefined) { - url = url + '?' + queryString; - } - if (direction === ROUTER_INTENT_FORWARD) { - history.pushState(state, '', url); - } else { - history.replaceState(state, '', url); - } -}; - -export const removePrefix = (prefix: string[], path: string[]): string[] | null => { +// Remove the prefix segments from the path segments. +// +// Return: +// - null when the path segments do not start with the passed prefix, +// - the path segments after the prefix otherwise. +const removePrefix = (prefix: string[], path: string[]): string[] | null => { if (prefix.length > path.length) { return null; } @@ -53,7 +61,7 @@ export const removePrefix = (prefix: string[], path: string[]): string[] | null return path; } for (let i = 0; i < prefix.length; i++) { - if (prefix[i].length > 0 && prefix[i] !== path[i]) { + if (prefix[i] !== path[i]) { return null; } } @@ -64,15 +72,8 @@ export const removePrefix = (prefix: string[], path: string[]): string[] | null }; export const readPath = (loc: Location, root: string, useHash: boolean): string[] | null => { - let pathname = loc.pathname; - if (useHash) { - const hash = loc.hash; - pathname = (hash[0] === '#') - ? hash.slice(1) - : ''; - } - const prefix = parsePath(root).segments; + const pathname = useHash ? loc.hash.slice(1) : loc.pathname; const path = parsePath(pathname).segments; return removePrefix(prefix, path); }; diff --git a/core/src/components/title/title.ios.scss b/core/src/components/title/title.ios.scss index 21473fb8b4..4031126a20 100644 --- a/core/src/components/title/title.ios.scss +++ b/core/src/components/title/title.ios.scss @@ -5,7 +5,7 @@ :host { @include position(0, null, null, 0); - @include padding(0, 90px, 0); + @include padding(var(--padding-top), 90px, var(--padding-bottom)); position: absolute; @@ -41,7 +41,7 @@ :host(.title-large) { @include padding(0, 16px); - @include transform-origin(start, center); + @include transform-origin(left, center); bottom: 0; @@ -57,6 +57,10 @@ text-align: start; } +:host(.title-large.title-rtl) { + @include transform-origin(right, center); +} + :host(.title-large.ion-cloned-element) { --color: #{$text-color}; } diff --git a/core/src/components/title/title.tsx b/core/src/components/title/title.tsx index e70d8bd14b..36c4decf7d 100644 --- a/core/src/components/title/title.tsx +++ b/core/src/components/title/title.tsx @@ -64,6 +64,7 @@ export class ToolbarTitle implements ComponentInterface { class={createColorClasses(this.color, { [mode]: true, [`title-${size}`]: true, + 'title-rtl': document.dir === 'rtl' })} >
diff --git a/core/src/utils/config.ts b/core/src/utils/config.ts index 3a83c2b18b..97ddab103a 100644 --- a/core/src/utils/config.ts +++ b/core/src/utils/config.ts @@ -197,7 +197,6 @@ export const setupConfig = (config: IonicConfig) => { const win = window as any; const Ionic = win.Ionic; if (Ionic && Ionic.config && Ionic.config.constructor.name !== 'Object') { - console.error('ionic config was already initialized'); return; } win.Ionic = win.Ionic || {}; diff --git a/docs/package.json b/docs/package.json index c0492f334b..870dabd322 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/docs", - "version": "5.6.7", + "version": "5.6.9", "description": "Pre-packaged API documentation for the Ionic docs.", "main": "core.json", "types": "core.d.ts", diff --git a/packages/angular-server/package-lock.json b/packages/angular-server/package-lock.json index a744ac95a4..e8282fd60d 100644 --- a/packages/angular-server/package-lock.json +++ b/packages/angular-server/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ionic/angular-server", - "version": "5.6.7", + "version": "5.6.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/angular-server", - "version": "5.6.7", + "version": "5.6.9", "license": "MIT", "devDependencies": { "@angular/animations": "8.2.13", @@ -16,7 +16,7 @@ "@angular/core": "8.2.13", "@angular/platform-browser": "8.2.13", "@angular/platform-server": "8.2.13", - "@ionic/core": "5.6.6", + "@ionic/core": "5.6.8", "ng-packagr": "5.7.1", "tslint": "^5.12.1", "tslint-ionic-rules": "0.0.21", @@ -137,9 +137,9 @@ } }, "node_modules/@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "dev": true, "dependencies": { "@stencil/core": "^2.4.0", @@ -5424,9 +5424,9 @@ } }, "@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "dev": true, "requires": { "@stencil/core": "^2.4.0", diff --git a/packages/angular-server/package.json b/packages/angular-server/package.json index e0084f5158..aa74d4de7a 100644 --- a/packages/angular-server/package.json +++ b/packages/angular-server/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/angular-server", - "version": "5.6.7", + "version": "5.6.9", "description": "Angular SSR Module for Ionic", "keywords": [ "ionic", @@ -49,7 +49,7 @@ "@angular/core": "8.2.13", "@angular/platform-browser": "8.2.13", "@angular/platform-server": "8.2.13", - "@ionic/core": "5.6.7", + "@ionic/core": "5.6.9", "ng-packagr": "5.7.1", "tslint": "^5.12.1", "tslint-ionic-rules": "0.0.21", diff --git a/packages/react-router/package.json b/packages/react-router/package.json index b5939e0fde..8591931318 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/react-router", - "version": "5.6.7", + "version": "5.6.9", "description": "React Router wrapper for @ionic/react", "keywords": [ "ionic", @@ -39,15 +39,15 @@ "tslib": "*" }, "peerDependencies": { - "@ionic/react": "5.6.7", + "@ionic/react": "5.6.9", "react": ">=16.8.6", "react-dom": ">=16.8.6", "react-router": "^5.0.1", "react-router-dom": "^5.0.1" }, "devDependencies": { - "@ionic/core": "5.6.7", - "@ionic/react": "5.6.7", + "@ionic/core": "5.6.9", + "@ionic/react": "5.6.9", "@rollup/plugin-node-resolve": "^8.1.0", "@testing-library/jest-dom": "^5.11.6", "@testing-library/react": "^11.2.2", diff --git a/packages/react/package.json b/packages/react/package.json index 04eb77b2c3..99fc3e857c 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/react", - "version": "5.6.7", + "version": "5.6.9", "description": "React specific wrapper for @ionic/core", "keywords": [ "ionic", @@ -39,7 +39,7 @@ "css/" ], "dependencies": { - "@ionic/core": "5.6.7", + "@ionic/core": "5.6.9", "ionicons": "^5.1.2", "tslib": "*" }, diff --git a/packages/vue-router/package-lock.json b/packages/vue-router/package-lock.json index fe523ffab7..de6b37e723 100644 --- a/packages/vue-router/package-lock.json +++ b/packages/vue-router/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ionic/vue-router", - "version": "5.6.7", + "version": "5.6.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/vue-router", - "version": "5.6.7", + "version": "5.6.9", "license": "MIT", "devDependencies": { "@ionic/vue": "5.4.1", @@ -23,7 +23,7 @@ }, "../../core": { "name": "@ionic/core", - "version": "5.6.6", + "version": "5.6.8", "dev": true, "license": "MIT", "dependencies": { @@ -37,7 +37,7 @@ "@rollup/plugin-node-resolve": "^8.4.0", "@rollup/plugin-virtual": "^2.0.3", "@stencil/sass": "1.3.2", - "@stencil/vue-output-target": "^0.4.2", + "@stencil/vue-output-target": "^0.4.3", "@types/jest": "^26.0.20", "@types/node": "^14.6.0", "@types/puppeteer": "5.4.3", @@ -45,6 +45,7 @@ "aws-sdk": "^2.738.0", "clean-css-cli": "^4.1.11", "domino": "^2.1.6", + "execa": "^5.0.0", "fs-extra": "^9.0.1", "jest": "^26.4.1", "jest-cli": "^26.4.1", @@ -8248,7 +8249,7 @@ "@rollup/plugin-virtual": "^2.0.3", "@stencil/core": "^2.4.0", "@stencil/sass": "1.3.2", - "@stencil/vue-output-target": "^0.4.2", + "@stencil/vue-output-target": "^0.4.3", "@types/jest": "^26.0.20", "@types/node": "^14.6.0", "@types/puppeteer": "5.4.3", @@ -8256,6 +8257,7 @@ "aws-sdk": "^2.738.0", "clean-css-cli": "^4.1.11", "domino": "^2.1.6", + "execa": "^5.0.0", "fs-extra": "^9.0.1", "ionicons": "^5.5.1", "jest": "^26.4.1", diff --git a/packages/vue-router/package.json b/packages/vue-router/package.json index 7e2bad5a6e..7918e1defa 100644 --- a/packages/vue-router/package.json +++ b/packages/vue-router/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/vue-router", - "version": "5.6.7", + "version": "5.6.9", "description": "Vue Router integration for @ionic/vue", "scripts": { "test.spec": "jest", diff --git a/packages/vue/package-lock.json b/packages/vue/package-lock.json index db3f307176..7b2cd90ad9 100644 --- a/packages/vue/package-lock.json +++ b/packages/vue/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/vue", - "version": "5.6.7", + "version": "5.6.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/vue", - "version": "5.6.7", + "version": "5.6.9", "license": "MIT", "dependencies": { - "@ionic/core": "5.6.6", + "@ionic/core": "5.6.8", "ionicons": "^5.1.2" }, "devDependencies": { @@ -53,9 +53,9 @@ } }, "node_modules/@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "dependencies": { "@stencil/core": "^2.4.0", "ionicons": "^5.5.1", @@ -633,9 +633,9 @@ } }, "@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.8.tgz", + "integrity": "sha512-JWrRGzw4SyyemjycPEh516fAkgFVtLp6RMPTH3uzK8L+DLfqJ/QU4Uccu89QqdcG/TBD75r3wkUtbKL2YlL8PQ==", "requires": { "@stencil/core": "^2.4.0", "ionicons": "^5.5.1", diff --git a/packages/vue/package.json b/packages/vue/package.json index 4f9dda3ff6..43c2e141ed 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/vue", - "version": "5.6.7", + "version": "5.6.9", "description": "Vue specific wrapper for @ionic/core", "scripts": { "lint": "echo add linter", @@ -57,7 +57,7 @@ "vue-router": "^4.0.0-rc.4" }, "dependencies": { - "@ionic/core": "5.6.7", + "@ionic/core": "5.6.9", "ionicons": "^5.1.2" }, "vetur": {