From b1ecd4748b29c159a593324ac4bef70ff20fd128 Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Thu, 24 Apr 2025 16:22:19 -0700 Subject: [PATCH] feat(core): separate mode and theme --- core/api.txt | 15 ++ core/src/components.d.ts | 77 +++++++++ core/src/components/my-chip/my-chip.base.scss | 156 ++++++++++++++++++ core/src/components/my-chip/my-chip.tsx | 106 ++++++++++++ .../components/my-chip/test/basic/index.html | 95 +++++++++++ core/src/global/ionic-global.ts | 34 ++++ core/src/themes/base/base.tokens.ts | 63 +++++++ core/src/themes/base/dark.tokens.ts | 58 +++++++ core/src/themes/base/generate-css-vars.ts | 30 ++++ core/src/themes/base/light.tokens.ts | 57 +++++++ core/src/utils/config.ts | 2 + .../angular/src/directives/proxies-list.ts | 1 + packages/angular/src/directives/proxies.ts | 22 +++ .../standalone/src/directives/proxies.ts | 25 +++ packages/react/src/components/proxies.ts | 2 + packages/vue/src/proxies.ts | 11 ++ 16 files changed, 754 insertions(+) create mode 100644 core/src/components/my-chip/my-chip.base.scss create mode 100644 core/src/components/my-chip/my-chip.tsx create mode 100644 core/src/components/my-chip/test/basic/index.html create mode 100644 core/src/themes/base/base.tokens.ts create mode 100644 core/src/themes/base/dark.tokens.ts create mode 100644 core/src/themes/base/generate-css-vars.ts create mode 100644 core/src/themes/base/light.tokens.ts diff --git a/core/api.txt b/core/api.txt index 11f31c39ec..8ea80afe8f 100644 --- a/core/api.txt +++ b/core/api.txt @@ -1498,6 +1498,21 @@ ion-modal,part,backdrop ion-modal,part,content ion-modal,part,handle +ion-my-chip,shadow +ion-my-chip,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true +ion-my-chip,prop,disabled,boolean,false,false,false +ion-my-chip,prop,hue,"bold" | "subtle" | undefined,'subtle',false,false +ion-my-chip,prop,mode,"ios" | "md",undefined,false,false +ion-my-chip,prop,outline,boolean,false,false,false +ion-my-chip,prop,shape,"rectangular" | "round" | "soft" | undefined,'soft',false,false +ion-my-chip,prop,size,"large" | "small" | undefined,'small',false,false +ion-my-chip,prop,theme,"ios" | "md" | "ionic",undefined,false,false +ion-my-chip,css-prop,--background +ion-my-chip,css-prop,--border-radius +ion-my-chip,css-prop,--color +ion-my-chip,css-prop,--focus-ring-color +ion-my-chip,css-prop,--focus-ring-width + ion-nav,shadow ion-nav,prop,animated,boolean,true,false,false ion-nav,prop,animation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 82ace58b59..a1df798bff 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2173,6 +2173,40 @@ export namespace Components { */ "trigger": string | undefined; } + interface IonMyChip { + /** + * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). + */ + "color"?: Color; + /** + * If `true`, the user cannot interact with the chip. + */ + "disabled": boolean; + /** + * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme. + */ + "hue"?: 'bold' | 'subtle'; + /** + * The mode determines the platform behaviors of the component. + */ + "mode"?: "ios" | "md"; + /** + * Display an outline style button. + */ + "outline": boolean; + /** + * Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes. + */ + "shape"?: 'soft' | 'round' | 'rectangular'; + /** + * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes. + */ + "size"?: 'small' | 'large'; + /** + * The theme determines the visual appearance of the component. + */ + "theme"?: "ios" | "md" | "ionic"; + } interface IonNav { /** * If `true`, the nav should animate the transition of components. @@ -4759,6 +4793,12 @@ declare global { prototype: HTMLIonModalElement; new (): HTMLIonModalElement; }; + interface HTMLIonMyChipElement extends Components.IonMyChip, HTMLStencilElement { + } + var HTMLIonMyChipElement: { + prototype: HTMLIonMyChipElement; + new (): HTMLIonMyChipElement; + }; interface HTMLIonNavElementEventMap { "ionNavWillLoad": void; "ionNavWillChange": void; @@ -5457,6 +5497,7 @@ declare global { "ion-menu-button": HTMLIonMenuButtonElement; "ion-menu-toggle": HTMLIonMenuToggleElement; "ion-modal": HTMLIonModalElement; + "ion-my-chip": HTMLIonMyChipElement; "ion-nav": HTMLIonNavElement; "ion-nav-link": HTMLIonNavLinkElement; "ion-note": HTMLIonNoteElement; @@ -7695,6 +7736,40 @@ declare namespace LocalJSX { */ "trigger"?: string | undefined; } + interface IonMyChip { + /** + * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). + */ + "color"?: Color; + /** + * If `true`, the user cannot interact with the chip. + */ + "disabled"?: boolean; + /** + * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme. + */ + "hue"?: 'bold' | 'subtle'; + /** + * The mode determines the platform behaviors of the component. + */ + "mode"?: "ios" | "md"; + /** + * Display an outline style button. + */ + "outline"?: boolean; + /** + * Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes. + */ + "shape"?: 'soft' | 'round' | 'rectangular'; + /** + * Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes. + */ + "size"?: 'small' | 'large'; + /** + * The theme determines the visual appearance of the component. + */ + "theme"?: "ios" | "md" | "ionic"; + } interface IonNav { /** * If `true`, the nav should animate the transition of components. @@ -9617,6 +9692,7 @@ declare namespace LocalJSX { "ion-menu-button": IonMenuButton; "ion-menu-toggle": IonMenuToggle; "ion-modal": IonModal; + "ion-my-chip": IonMyChip; "ion-nav": IonNav; "ion-nav-link": IonNavLink; "ion-note": IonNote; @@ -9720,6 +9796,7 @@ declare module "@stencil/core" { "ion-menu-button": LocalJSX.IonMenuButton & JSXBase.HTMLAttributes; "ion-menu-toggle": LocalJSX.IonMenuToggle & JSXBase.HTMLAttributes; "ion-modal": LocalJSX.IonModal & JSXBase.HTMLAttributes; + "ion-my-chip": LocalJSX.IonMyChip & JSXBase.HTMLAttributes; "ion-nav": LocalJSX.IonNav & JSXBase.HTMLAttributes; "ion-nav-link": LocalJSX.IonNavLink & JSXBase.HTMLAttributes; "ion-note": LocalJSX.IonNote & JSXBase.HTMLAttributes; diff --git a/core/src/components/my-chip/my-chip.base.scss b/core/src/components/my-chip/my-chip.base.scss new file mode 100644 index 0000000000..04cd965db7 --- /dev/null +++ b/core/src/components/my-chip/my-chip.base.scss @@ -0,0 +1,156 @@ +// @import "../../themes/native/native.globals"; +@use "../../themes/functions.color" as color; +@use "../../themes/mixins" as mixins; + +:host { + /** + * @prop --background: Background of the chip + * @prop --color: Color of the chip + * @prop --border-radius: Border radius of the chip + * @prop --focus-ring-color: Color of the focus ring + * @prop --focus-ring-width: Width of the focus ring + */ + --focus-ring-color: var(--ion-color-blue-50); + --focus-ring-width: var(--ion-spacing-xs); + + @include mixins.font-smoothing(); + @include mixins.padding(var(--ion-spacing-xs), var(--ion-spacing-sm)); + @include mixins.border-radius(var(--border-radius)); + + display: inline-flex; + + position: relative; + + align-items: center; + justify-content: center; + + background: var(--background); + color: var(--color); + + font-weight: var(--ion-font-weights-normal); + + line-height: var(--ion-line-heights-md); + + cursor: pointer; + + overflow: hidden; + + vertical-align: middle; + + gap: var(--ion-spacing-xs); + + box-sizing: border-box; +} + +:host(.chip-disabled) { + cursor: default; + pointer-events: none; +} + +// Outline Chip +// --------------------------------------------- + +:host(.chip-outline) { + border-width: var(--ion-spacing-xxs); + border-style: solid; // Do we need to use a variable here? ionic uses tokens but all themes use solid so it's not really necessary +} + +// Chip: Focus +// --------------------------------------------- + +:host(.ion-focused) { + outline: var(--focus-ring-width) solid var(--focus-ring-color); + outline-offset: var(--focus-ring-width); +} + +// Chip Shapes +// --------------------------------------------- + +:host(.chip-soft) { + --border-radius: var(--ion-radii-lg); +} + +:host(.chip-round) { + --border-radius: var(--ion-radii-xxl); +} + +:host(.chip-rectangular) { + --border-radius: var(--ion-radii-none); +} + +// Size +// --------------------------------------------- + +:host(.chip-small) { + min-height: var(--ion-spacing-lg); + + font-size: var(--ion-font-sizs-sm); +} + +:host(.chip-large) { + min-height: var(--ion-spacing-xxl); + + font-size: var(--ion-font-sizes-lg); +} + +// Subtle Chip +// --------------------------------------------- + +:host(.chip-subtle) { + --background: var(--ion-color-gray-100); + --color: var(--ion-color-gray-800); +} + +:host(.chip-outline.chip-subtle) { + border-color: var(--ion-color-gray-300); +} + +// Bold Chip +// --------------------------------------------- + +:host(.chip-bold) { + --background: var(--ion-color-gray-700); + --color: var(--ion-color-white); +} + +:host(.chip-outline.chip-bold) { + border-color: var(--ion-color-gray-800); +} + +// Chip Colors +// --------------------------------------------- + +// Subtle +:host(.chip-subtle.ion-color) { + background: color.current-color( + base, + $subtle: true + ); // these don't work because we need to update the function to use the new color system + color: color.current-color( + contrast, + $subtle: true + ); // these don't work because we need to update the function to use the new color system +} + +:host(.chip-subtle.chip-outline.ion-color) { + border-color: color.current-color( + shade, + $subtle: true + ); // these don't work because we need to update the function to use the new color system +} + +// Bold +:host(.chip-bold.ion-color) { + background: color.current-color( + base + ); // these don't work because we need to update the function to use the new color system + color: color.current-color( + contrast + ); // these don't work because we need to update the function to use the new color system +} + +:host(.chip-bold.chip-outline.ion-color) { + border-color: color.current-color( + shade + ); // these don't work because we need to update the function to use the new color system +} diff --git a/core/src/components/my-chip/my-chip.tsx b/core/src/components/my-chip/my-chip.tsx new file mode 100644 index 0000000000..47bc4e7832 --- /dev/null +++ b/core/src/components/my-chip/my-chip.tsx @@ -0,0 +1,106 @@ +import type { ComponentInterface } from '@stencil/core'; +import { Component, Host, Prop, h, Element } from '@stencil/core'; +import { createColorClasses } from '@utils/theme'; + +import { getIonMode, getIonCustomTheme } from '../../global/ionic-global'; +import type { Color } from '../../interface'; +import { generateCSSVars } from '../../themes/base/generate-css-vars'; + +/** + * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component. + * @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component. + */ +@Component({ + tag: 'ion-my-chip', + styleUrl: 'my-chip.base.scss', + shadow: true, +}) +export class MyChip implements ComponentInterface { + @Element() el!: HTMLElement; + + /** + * The color to use from your application's color palette. + * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. + * For more information on colors, see [theming](/docs/theming/basics). + */ + @Prop({ reflect: true }) color?: Color; + + /** + * Display an outline style button. + */ + @Prop() outline = false; + + /** + * If `true`, the user cannot interact with the chip. + */ + @Prop() disabled = false; + + /** + * Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for + * a chip with muted, subtle colors. + * + * Only applies to the `ionic` theme. + */ + // THOUGHT: Comparing to ChakraUI, they use variants (aka fills) for this + // maybe we should consider using variants: solid, outline, subtle + // they use solid for bold solid background, no outline, has states + // subtle for light background, no outline, has states + // outline for outline style, no background, has states + // surface for light background, with outline, has states + // ghost for no background, no outline, has states + // plain for no background, no outline, no states + @Prop() hue?: 'bold' | 'subtle' = 'subtle'; + + /** + * Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully + * rounded corners, or `"rectangular"` for a chip without rounded corners. + * Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes. + */ + @Prop() shape?: 'soft' | 'round' | 'rectangular' = 'soft'; + + /** + * Set to `"small"` for a chip with less height and padding. + * + * Defaults to `"large"` for the ionic theme, and undefined for all other themes. + */ + @Prop() size?: 'small' | 'large' = 'small'; + + componentWillLoad() { + const myCustomTheme = getIonCustomTheme(); + const componentTheme = myCustomTheme.components['IonChip']; + + // check if componentTheme is not an empty object or undefined + if (componentTheme !== undefined || Object.keys(componentTheme).length > 0) { + // apply a style tag to this component + const style = document.createElement('style'); + style.innerHTML = [generateCSSVars(componentTheme, '--ion-', ':host')].join('\n\n'); + + // Attach to Shadow Root if available, otherwise Light DOM + const root = this.el.shadowRoot ?? this.el; + root.appendChild(style); + } + } + + render() { + const { hue, shape, size } = this; + const mode = getIonMode(this); + + return ( + + + {mode === 'md' && } + + ); + } +} diff --git a/core/src/components/my-chip/test/basic/index.html b/core/src/components/my-chip/test/basic/index.html new file mode 100644 index 0000000000..2ce59ca860 --- /dev/null +++ b/core/src/components/my-chip/test/basic/index.html @@ -0,0 +1,95 @@ + + + + + MyChip - Basic + + + + + + + + + + + + + MyChip - Basic + + + + +

My Chip

+

+ This is a POC, not all the features are working as expected. For example, the color property still needs to be + worked on. +

+

You can verify that the variables are being generated correctly by inspecting the root element.

+ + default + + outline + + large + + bold + bold with outline + + primary, subtle hue + primary, bold hue + + secondary, subtle hue + secondary, bold hue +
+
+ + + + diff --git a/core/src/global/ionic-global.ts b/core/src/global/ionic-global.ts index 0b7b62658f..6180a3933a 100644 --- a/core/src/global/ionic-global.ts +++ b/core/src/global/ionic-global.ts @@ -2,6 +2,9 @@ import { Build, getMode, setMode, getElement } from '@stencil/core'; import { printIonWarning } from '@utils/logging'; import type { IonicConfig, Mode, Theme } from '../interface'; +import { defaultTheme as baseTheme } from '../themes/base/base.tokens'; +import type { Theme as BaseTheme } from '../themes/base/base.tokens'; +import { deepMerge, generateCSSVars } from '../themes/base/generate-css-vars'; import { shouldUseCloseWatcher } from '../utils/hardware-back-button'; import { isPlatform, setupPlatforms } from '../utils/platform'; @@ -25,6 +28,23 @@ const printInvalidModeWarning = (mode: Mode, theme: Theme, ref?: any) => { ); }; +const applyTheme = (userTheme: BaseTheme, prefix?: string) => { + const mergedTheme = deepMerge(baseTheme, userTheme); + const { palette, components, ...restTokens } = mergedTheme; + const { enabled, ...restDarkTokens } = palette.dark; + + config.set('customTheme', mergedTheme); + + const style = document.createElement('style'); + style.innerHTML = [generateCSSVars(restTokens, prefix), generateCSSVars(palette.light, prefix)].join('\n\n'); + + if (enabled === 'system') { + style.innerHTML += `@media (prefers-color-scheme: dark) {\n${generateCSSVars(restDarkTokens, prefix)}\n}`; + } + + document.head.appendChild(style); +}; + /** * Validates if a mode is accepted for a theme configuration. * @param mode The mode to validate. @@ -132,6 +152,14 @@ export const getIonTheme = (ref?: any): Theme => { return defaultTheme; }; +export const getIonCustomTheme = (): any => { + const customTheme = config.get('customTheme'); + if (customTheme) { + return customTheme; + } + return defaultTheme; +}; + export const rIC = (callback: () => void) => { if ('requestIdleCallback' in window) { (window as any).requestIdleCallback(callback); @@ -225,6 +253,12 @@ export const initialize = (userConfig: IonicConfig = {}) => { doc.documentElement.setAttribute('theme', defaultTheme); doc.documentElement.classList.add(defaultTheme); + const customTheme: BaseTheme | undefined = configObj.customTheme; + + if (customTheme) { + applyTheme(customTheme); + } + if (config.getBoolean('_testing')) { config.set('animated', false); } diff --git a/core/src/themes/base/base.tokens.ts b/core/src/themes/base/base.tokens.ts new file mode 100644 index 0000000000..85bc4c7c68 --- /dev/null +++ b/core/src/themes/base/base.tokens.ts @@ -0,0 +1,63 @@ +import { defaultDarkTheme } from './dark.tokens'; +import { defaultLightTheme } from './light.tokens'; + +export const defaultTheme = { + palette: { + light: defaultLightTheme, + dark: defaultDarkTheme, + }, + // so far spacing is being used for + // padding, margin, gap, border-width, height, width + // should we create scale for height and width instead? + // or keep it as is but change the keys to be numerical + // like 0.5, 1, 1.5, 2, 2.5, 3, etc? + spacing: { + none: '0', + xxs: '2px', + xs: '4px', + sm: '8px', + md: '16px', + lg: '24px', + xl: '32px', + xxl: '40px', + }, + radii: { + none: '0', + xs: '1px', + sm: '2px', + md: '4px', + lg: '8px', + xl: '16px', + xxl: '32px', + }, + fontWeights: { + thin: '100', + extraLight: '200', + light: '300', + normal: '400', + medium: '500', + semiBold: '600', + bold: '700', + extraBold: '800', + black: '900', + }, + fontSizes: { + xs: '12px', + sm: '14px', + md: '16px', + lg: '18px', + xl: '20px', + xxl: '24px', + }, + lineHeights: { + xs: '1.2', + sm: '1.4', + md: '1.6', + lg: '1.8', + xl: '2', + xxl: '2.4', + }, + components: {}, +}; + +export type Theme = typeof defaultTheme; diff --git a/core/src/themes/base/dark.tokens.ts b/core/src/themes/base/dark.tokens.ts new file mode 100644 index 0000000000..955a147490 --- /dev/null +++ b/core/src/themes/base/dark.tokens.ts @@ -0,0 +1,58 @@ +export const defaultDarkTheme = { + enabled: 'never', // 'always' | 'system' | 'class' | 'never' + color: { + primary: { + bold: { + base: '#0054e9', + constrast: '#ffffff', + shade: '#0041c4', // darker version + tint: '#0065ff', // lighter version + }, + subtle: { + base: '#0054e9', + constrast: '#ffffff', + shade: '#0041c4', // darker version + tint: '#0065ff', // lighter version + }, + }, + secondary: { + bold: { + base: '#0163aa', + constrast: '#ffffff', + shade: '#015a9e', + tint: '#0176c4', + }, + subtle: { + base: '#0163aa', + constrast: '#ffffff', + shade: '#015a9e', + tint: '#0176c4', + }, + }, + red: { + 50: '#ffebee', + 100: '#ffcdd2', + 200: '#ef9a9a', + }, + blue: { + 50: '#e3f2fd', + 100: '#bbdefb', + 200: '#90caf9', + }, + gray: { + 50: '#f5f5f5', + 100: '#eeeeee', + 200: '#e0e0e0', + 300: '#bdbdbd', + 400: '#9e9e9e', + 500: '#757575', + 600: '#616161', + 700: '#424242', + 800: '#212121', + }, + white: 'green', + black: '#000000', + }, +}; + +export type Theme = typeof defaultDarkTheme; diff --git a/core/src/themes/base/generate-css-vars.ts b/core/src/themes/base/generate-css-vars.ts new file mode 100644 index 0000000000..479e6895d7 --- /dev/null +++ b/core/src/themes/base/generate-css-vars.ts @@ -0,0 +1,30 @@ +// import type { Theme } from './base.tokens'; + +export function generateCSSVars(theme: any, themePrefix = '--ion-', selector = ':root'): string { + const flatten = (obj: any, prefix = themePrefix): string => + Object.entries(obj) + .flatMap(([key, val]) => { + // if key is camelCase, convert to kebab-case + if (key.match(/([a-z])([A-Z])/g)) { + key = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + } + return typeof val === 'object' && val !== null + ? flatten(val, `${prefix}${key}-`) + : [`${prefix}${key}: ${val};`]; + }) + .join('\n'); + + return `${selector} {\n${flatten(theme)}\n}`; +} + +// Simple deep merge function +export function deepMerge(target: any, source: any): any { + for (const key in source) { + if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { + target[key] = deepMerge(target[key] ?? {}, source[key]); + } else { + target[key] = source[key]; + } + } + return target; +} diff --git a/core/src/themes/base/light.tokens.ts b/core/src/themes/base/light.tokens.ts new file mode 100644 index 0000000000..f949766c58 --- /dev/null +++ b/core/src/themes/base/light.tokens.ts @@ -0,0 +1,57 @@ +export const defaultLightTheme = { + color: { + primary: { + bold: { + base: '#0054e9', + constrast: '#ffffff', + shade: '#0041c4', // darker version + tint: '#0065ff', // lighter version + }, + subtle: { + base: '#0054e9', + constrast: '#ffffff', + shade: '#0041c4', // darker version + tint: '#0065ff', // lighter version + }, + }, + secondary: { + bold: { + base: '#0163aa', + constrast: '#ffffff', + shade: '#015a9e', + tint: '#0176c4', + }, + subtle: { + base: '#0163aa', + constrast: '#ffffff', + shade: '#015a9e', + tint: '#0176c4', + }, + }, + red: { + 50: '#ffebee', + 100: '#ffcdd2', + 200: '#ef9a9a', + }, + blue: { + 50: '#e3f2fd', + 100: '#bbdefb', + 200: '#90caf9', + }, + gray: { + 50: '#f5f5f5', + 100: '#eeeeee', + 200: '#e0e0e0', + 300: '#bdbdbd', + 400: '#9e9e9e', + 500: '#757575', + 600: '#616161', + 700: '#424242', + 800: '#212121', + }, + white: '#ffffff', + black: '#000000', + }, +}; + +export type Theme = typeof defaultLightTheme; diff --git a/core/src/utils/config.ts b/core/src/utils/config.ts index 24ea27b73d..bf231b546c 100644 --- a/core/src/utils/config.ts +++ b/core/src/utils/config.ts @@ -364,6 +364,8 @@ export interface IonicConfig { scrollAssist?: boolean; hideCaretOnScroll?: boolean; + customTheme?: any; + // INTERNAL configs // TODO(FW-2832): types persistConfig?: boolean; diff --git a/packages/angular/src/directives/proxies-list.ts b/packages/angular/src/directives/proxies-list.ts index 76325ada4d..ef1aba90a3 100644 --- a/packages/angular/src/directives/proxies-list.ts +++ b/packages/angular/src/directives/proxies-list.ts @@ -51,6 +51,7 @@ export const DIRECTIVES = [ d.IonMenu, d.IonMenuButton, d.IonMenuToggle, + d.IonMyChip, d.IonNavLink, d.IonNote, d.IonPicker, diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index 815b742a0d..d02495907e 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -1426,6 +1426,28 @@ export class IonMenuToggle { export declare interface IonMenuToggle extends Components.IonMenuToggle {} +@ProxyCmp({ + inputs: ['color', 'disabled', 'hue', 'mode', 'outline', 'shape', 'size', 'theme'] +}) +@Component({ + selector: 'ion-my-chip', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property + inputs: ['color', 'disabled', 'hue', 'mode', 'outline', 'shape', 'size', 'theme'], +}) +export class IonMyChip { + protected el: HTMLIonMyChipElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + } +} + + +export declare interface IonMyChip extends Components.IonMyChip {} + + @ProxyCmp({ inputs: ['component', 'componentProps', 'mode', 'routerAnimation', 'routerDirection', 'theme'] }) diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 590555cdc8..93f7727cca 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -51,6 +51,7 @@ import { defineCustomElement as defineIonLoading } from '@ionic/core/components/ import { defineCustomElement as defineIonMenu } from '@ionic/core/components/ion-menu.js'; import { defineCustomElement as defineIonMenuButton } from '@ionic/core/components/ion-menu-button.js'; import { defineCustomElement as defineIonMenuToggle } from '@ionic/core/components/ion-menu-toggle.js'; +import { defineCustomElement as defineIonMyChip } from '@ionic/core/components/ion-my-chip.js'; import { defineCustomElement as defineIonNavLink } from '@ionic/core/components/ion-nav-link.js'; import { defineCustomElement as defineIonNote } from '@ionic/core/components/ion-note.js'; import { defineCustomElement as defineIonPicker } from '@ionic/core/components/ion-picker.js'; @@ -1420,6 +1421,30 @@ export class IonMenuToggle { export declare interface IonMenuToggle extends Components.IonMenuToggle {} +@ProxyCmp({ + defineCustomElementFn: defineIonMyChip, + inputs: ['color', 'disabled', 'hue', 'mode', 'outline', 'shape', 'size', 'theme'] +}) +@Component({ + selector: 'ion-my-chip', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property + inputs: ['color', 'disabled', 'hue', 'mode', 'outline', 'shape', 'size', 'theme'], + standalone: true +}) +export class IonMyChip { + protected el: HTMLIonMyChipElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + } +} + + +export declare interface IonMyChip extends Components.IonMyChip {} + + @ProxyCmp({ defineCustomElementFn: defineIonNavLink, inputs: ['component', 'componentProps', 'mode', 'routerAnimation', 'routerDirection', 'theme'] diff --git a/packages/react/src/components/proxies.ts b/packages/react/src/components/proxies.ts index 4bb4ff8958..4c04f5c662 100644 --- a/packages/react/src/components/proxies.ts +++ b/packages/react/src/components/proxies.ts @@ -43,6 +43,7 @@ import { defineCustomElement as defineIonListHeader } from '@ionic/core/componen import { defineCustomElement as defineIonMenu } from '@ionic/core/components/ion-menu.js'; import { defineCustomElement as defineIonMenuButton } from '@ionic/core/components/ion-menu-button.js'; import { defineCustomElement as defineIonMenuToggle } from '@ionic/core/components/ion-menu-toggle.js'; +import { defineCustomElement as defineIonMyChip } from '@ionic/core/components/ion-my-chip.js'; import { defineCustomElement as defineIonNav } from '@ionic/core/components/ion-nav.js'; import { defineCustomElement as defineIonNavLink } from '@ionic/core/components/ion-nav-link.js'; import { defineCustomElement as defineIonNote } from '@ionic/core/components/ion-note.js'; @@ -116,6 +117,7 @@ export const IonListHeader = /*@__PURE__*/createReactComponent('ion-menu', undefined, undefined, defineIonMenu); export const IonMenuButton = /*@__PURE__*/createReactComponent('ion-menu-button', undefined, undefined, defineIonMenuButton); export const IonMenuToggle = /*@__PURE__*/createReactComponent('ion-menu-toggle', undefined, undefined, defineIonMenuToggle); +export const IonMyChip = /*@__PURE__*/createReactComponent('ion-my-chip', undefined, undefined, defineIonMyChip); export const IonNav = /*@__PURE__*/createReactComponent('ion-nav', undefined, undefined, defineIonNav); export const IonNavLink = /*@__PURE__*/createReactComponent('ion-nav-link', undefined, undefined, defineIonNavLink); export const IonNote = /*@__PURE__*/createReactComponent('ion-note', undefined, undefined, defineIonNote); diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 0c5a6ba2d4..bef60e6c53 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -49,6 +49,7 @@ import { defineCustomElement as defineIonListHeader } from '@ionic/core/componen import { defineCustomElement as defineIonMenu } from '@ionic/core/components/ion-menu.js'; import { defineCustomElement as defineIonMenuButton } from '@ionic/core/components/ion-menu-button.js'; import { defineCustomElement as defineIonMenuToggle } from '@ionic/core/components/ion-menu-toggle.js'; +import { defineCustomElement as defineIonMyChip } from '@ionic/core/components/ion-my-chip.js'; import { defineCustomElement as defineIonNav } from '@ionic/core/components/ion-nav.js'; import { defineCustomElement as defineIonNavLink } from '@ionic/core/components/ion-nav-link.js'; import { defineCustomElement as defineIonNote } from '@ionic/core/components/ion-note.js'; @@ -639,6 +640,16 @@ export const IonMenuToggle: StencilVueComponent = /*@__PURE__ ]); +export const IonMyChip: StencilVueComponent = /*@__PURE__*/ defineContainer('ion-my-chip', defineIonMyChip, [ + 'color', + 'outline', + 'disabled', + 'hue', + 'shape', + 'size' +]); + + export const IonNav: StencilVueComponent = /*@__PURE__*/ defineContainer('ion-nav', defineIonNav, [ 'delegate', 'swipeGesture',