Compare commits

...

10 Commits

Author SHA1 Message Date
Liam DeBeasi
629d862c54 tests 2023-12-01 15:38:09 -05:00
Liam DeBeasi
2c773ed0e6 fix: do not emit ionChange if value did not change 2023-12-01 15:29:40 -05:00
Liam DeBeasi
b1fc67227c fix: column scrolls into view when option is ready 2023-12-01 15:16:59 -05:00
Liam DeBeasi
75ee951ce8 chore: lint 2023-12-01 14:58:06 -05:00
Liam DeBeasi
2f3f9dc9ca refactor: clicking option sets value 2023-12-01 14:58:01 -05:00
Liam DeBeasi
b68c93d55d refactor: scrolling column sets value 2023-12-01 14:49:23 -05:00
Liam DeBeasi
eace6425a2 refactor: add slot to integrate basic options 2023-12-01 14:28:07 -05:00
Liam DeBeasi
1aeb19403b chore: run build 2023-12-01 12:59:03 -05:00
ionitron
9d0834b201 chore(): add updated snapshots 2023-12-01 17:55:49 +00:00
Liam DeBeasi
7b21bd40a6 feat(picker-column): add styles, disabled and active states 2023-12-01 12:44:38 -05:00
43 changed files with 325 additions and 161 deletions

View File

@@ -919,6 +919,7 @@ ion-picker-column,prop,value,number | string | undefined,undefined,false,false
ion-picker-column,event,ionChange,PickerColumnItem,true
ion-picker-column-option,shadow
ion-picker-column-option,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,'primary',false,true
ion-picker-column-option,prop,disabled,boolean,false,false,false
ion-picker-column-option,prop,value,any,undefined,false,false

View File

@@ -1987,6 +1987,10 @@ export namespace Components {
"value"?: string | number;
}
interface IonPickerColumnOption {
/**
* 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 picker column option.
*/
@@ -4047,7 +4051,7 @@ declare global {
new (): HTMLIonPickerElement;
};
interface HTMLIonPickerColumnElementEventMap {
"ionChange": PickerColumnItem;
"ionChange": string | number | undefined;
}
interface HTMLIonPickerColumnElement extends Components.IonPickerColumn, HTMLStencilElement {
addEventListener<K extends keyof HTMLIonPickerColumnElementEventMap>(type: K, listener: (this: HTMLIonPickerColumnElement, ev: IonPickerColumnCustomEvent<HTMLIonPickerColumnElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
@@ -6627,13 +6631,17 @@ declare namespace LocalJSX {
/**
* Emitted when the value has changed.
*/
"onIonChange"?: (event: IonPickerColumnCustomEvent<PickerColumnItem>) => void;
"onIonChange"?: (event: IonPickerColumnCustomEvent<string | number | undefined>) => void;
/**
* The selected option in the picker.
*/
"value"?: string | number;
}
interface IonPickerColumnOption {
/**
* 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 picker column option.
*/

View File

@@ -0,0 +1 @@
@import "./picker-column-option.scss";

View File

@@ -0,0 +1,5 @@
@import "./picker-column-option.scss";
:host(.option-active) button {
color: current-color(base);
}

View File

@@ -0,0 +1,45 @@
@import "../../themes/ionic.globals";
// Picker Column
// --------------------------------------------------
button {
@include padding(0);
@include margin(0);
width: 100%;
height: 34px;
border: 0px;
outline: none;
background: transparent;
color: inherit;
font-family: $font-family-base;
font-size: inherit;
line-height: 34px;
text-align: inherit;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
overflow: hidden;
}
:host(.option-disabled) {
opacity: 0.4;
}
:host(.option-disabled) button {
cursor: default;
}

View File

@@ -1,9 +1,17 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';
import { inheritAttributes } from '@utils/helpers';
import { createColorClasses } from '@utils/theme';
import { getIonMode } from '../../global/ionic-global';
import type { Color } from '../../interface';
@Component({
tag: 'ion-picker-column-option',
styleUrls: {
ios: 'picker-column-option.ios.scss',
md: 'picker-column-option.md.scss',
},
shadow: true,
})
export class PickerColumnOption implements ComponentInterface {
@@ -29,6 +37,13 @@ export class PickerColumnOption implements ComponentInterface {
*/
@Prop() value?: any | null;
/**
* 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 = 'primary';
/**
* The aria-label of the option has changed after the
* first render and needs to be updated within the component.
@@ -49,20 +64,45 @@ export class PickerColumnOption implements ComponentInterface {
this.ariaLabel = inheritedAttributes['aria-label'] || null;
}
/**
* The column options can load at any time
* so the selected option needs to tell the
* parent picker column when it is loaded
* so the picker column can ensure it is
* centered in the view.
*/
componentDidLoad() {
const parentPickerColumn = this.el.closest('ion-picker-column');
if (parentPickerColumn !== null && this.value === parentPickerColumn.value) {
parentPickerColumn.scrollActiveItemIntoView();
}
}
/**
* When an option is clicked update the
* parent picker column value. This
* component will handle centering the option
* in the column view.
*/
onClick() {
const parentPickerColumn = this.el.closest('ion-picker-column');
if (parentPickerColumn !== null) {
parentPickerColumn.setValue(this.value);
}
}
render() {
const { value, disabled, ariaLabel } = this;
const { color, value, disabled, ariaLabel } = this;
const mode = getIonMode(this);
return (
<Host>
<button
tabindex="-1"
aria-label={ariaLabel}
class={{
'picker-opt': true,
'picker-opt-disabled': !!disabled,
}}
disabled={disabled}
>
<Host
class={createColorClasses(color, {
[mode]: true,
['option-disabled']: disabled,
})}
>
<button tabindex="-1" aria-label={ariaLabel} disabled={disabled} onClick={() => this.onClick()}>
<slot>{value}</slot>
</button>
</Host>

View File

@@ -2,7 +2,7 @@
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Picker Column Option - Basic</title>
<title>Picker Column Option - a11y</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
@@ -14,6 +14,9 @@
<main>
<ion-picker-column-option> my option </ion-picker-column-option>
<ion-picker-column-option aria-label="the best one"> other option </ion-picker-column-option>
<ion-picker-column-option color="tertiary" class="option-active">option</ion-picker-column-option>
<ion-picker-column-option disabled="true">option</ion-picker-column-option>
<ion-picker-column-option color="tertiary" class="option-active" disabled="true">option</ion-picker-column-option>
</main>
</body>
</html>

View File

@@ -46,7 +46,19 @@
<div class="grid">
<div class="grid-item">
<h2>Default</h2>
<ion-picker-column-option> my option </ion-picker-column-option>
<ion-picker-column-option>My Option</ion-picker-column-option>
</div>
<div class="grid-item">
<h2>Disabled</h2>
<ion-picker-column-option disabled="true">My Option</ion-picker-column-option>
</div>
<div class="grid-item">
<h2>Active</h2>
<ion-picker-column-option class="option-active">My Option</ion-picker-column-option>
</div>
<div class="grid-item">
<h2>Active / Disabled</h2>
<ion-picker-column-option class="option-active" disabled="true">My Option</ion-picker-column-option>
</div>
</div>
</ion-content>

View File

@@ -0,0 +1,55 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('picker-column-option: rendering'), () => {
test('picker option should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker-column-option value="option">My Option</ion-picker-column-option>
`,
config
);
const option = page.locator('ion-picker-column-option');
await expect(option).toHaveScreenshot(screenshot('picker-column-option'));
});
test('disabled picker option should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker-column-option disabled="true" value="option">My Option</ion-picker-column-option>
`,
config
);
const option = page.locator('ion-picker-column-option');
await expect(option).toHaveScreenshot(screenshot('disabled-picker-column-option'));
});
test('active picker option should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker-column-option class="option-active" value="option">My Option</ion-picker-column-option>
`,
config
);
const option = page.locator('ion-picker-column-option');
await expect(option).toHaveScreenshot(screenshot('active-picker-column-option'));
});
test('disabled active picker option should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker-column-option class="option-active" disabled="true" value="option">My Option</ion-picker-column-option>
`,
config
);
const option = page.locator('ion-picker-column-option');
await expect(option).toHaveScreenshot(screenshot('disabled-active-picker-column-option'));
});
});
});

View File

@@ -0,0 +1,31 @@
import { newSpecPage } from '@stencil/core/testing';
import { PickerColumnOption } from '../picker-column-option';
describe('PickerColumnOption', () => {
it('option should be enabled by default', async () => {
const page = await newSpecPage({
components: [PickerColumnOption],
html: `
<ion-picker-column-option value="a">A</ion-picker-column-option>
`,
});
const pickerColumnOption = page.body.querySelector('ion-picker-column-option')!;
const button = pickerColumnOption.shadowRoot!.querySelector('button')!;
expect(button.hasAttribute('disabled')).toEqual(false);
});
it('disabled option should have disabled button', async () => {
const page = await newSpecPage({
components: [PickerColumnOption],
html: `
<ion-picker-column-option value="a" disabled="true">A</ion-picker-column-option>
`,
});
const pickerColumnOption = page.body.querySelector('ion-picker-column-option')!;
const button = pickerColumnOption.shadowRoot!.querySelector('button')!;
expect(button.hasAttribute('disabled')).toEqual(true);
});
});

View File

@@ -33,6 +33,17 @@
display: none;
}
::slotted(ion-picker-column-option) {
display: block;
scroll-snap-align: center;
}
.picker-item-empty,
:host(:not([disabled])) ::slotted(ion-picker-column-option.option-disabled) {
scroll-snap-align: none;
}
:host .picker-item {
@include padding(0);
@include margin(0);

View File

@@ -70,7 +70,7 @@ export class PickerColumn implements ComponentInterface {
/**
* Emitted when the value has changed.
*/
@Event() ionChange!: EventEmitter<PickerColumnItem>;
@Event() ionChange!: EventEmitter<string | number | undefined>;
@Watch('value')
valueChange() {
@@ -101,7 +101,9 @@ export class PickerColumn implements ComponentInterface {
* Because this initial call to scrollActiveItemIntoView has to fire before
* the scroll listener is set up, we need to manage the active class manually.
*/
const oldActive = getElementRoot(el).querySelector(`.${PICKER_ITEM_ACTIVE_CLASS}`);
const oldActive = getElementRoot(el).querySelector(
`.${PICKER_ITEM_ACTIVE_CLASS}`
) as HTMLIonPickerColumnOptionElement | null;
if (oldActive) {
this.setPickerItemActiveState(oldActive, false);
}
@@ -130,20 +132,20 @@ export class PickerColumn implements ComponentInterface {
}
componentDidRender() {
const { activeItem, items, isColumnVisible, value } = this;
const { el, activeItem, isColumnVisible, value } = this;
if (isColumnVisible) {
if (activeItem) {
this.scrollActiveItemIntoView();
} else if (items[0]?.value !== value) {
/**
* If the picker column does not have an active item and the current value
* does not match the first item in the picker column, that means
* the value is out of bounds. In this case, we assign the value to the
* first item to match the scroll position of the column.
*
*/
this.setValue(items[0].value);
if (isColumnVisible && !activeItem) {
const firstOption = el.querySelector('ion-picker-column-option');
/**
* If the picker column does not have an active item and the current value
* does not match the first item in the picker column, that means
* the value is out of bounds. In this case, we assign the value to the
* first item to match the scroll position of the column.
*
*/
if (firstOption !== null && firstOption.value !== value) {
this.setValue(firstOption.value);
}
}
}
@@ -167,12 +169,10 @@ export class PickerColumn implements ComponentInterface {
*/
@Method()
async setValue(value?: string | number) {
const { items } = this;
if (this.value === value) { return; }
this.value = value;
const findItem = items.find((item) => item.value === value && item.disabled !== true);
if (findItem) {
this.ionChange.emit(findItem);
}
this.ionChange.emit(value);
}
private centerPickerItemInView = (target: HTMLElement, smooth = true, canExitInputMode = true) => {
@@ -199,7 +199,7 @@ export class PickerColumn implements ComponentInterface {
}
};
private setPickerItemActiveState = (item: Element, isActive: boolean) => {
private setPickerItemActiveState = (item: HTMLIonPickerColumnOptionElement, isActive: boolean) => {
if (isActive) {
item.classList.add(PICKER_ITEM_ACTIVE_CLASS);
item.part.add(PICKER_ITEM_ACTIVE_PART);
@@ -270,7 +270,7 @@ export class PickerColumn implements ComponentInterface {
const { el } = this;
let timeout: ReturnType<typeof setTimeout> | undefined;
let activeEl: HTMLElement | null = this.activeItem;
let activeEl: HTMLIonPickerColumnOptionElement | undefined = this.activeItem;
const scrollCallback = () => {
raf(() => {
@@ -292,13 +292,24 @@ export class PickerColumn implements ComponentInterface {
const centerX = bbox.x + bbox.width / 2;
const centerY = bbox.y + bbox.height / 2;
const activeElement = el.shadowRoot!.elementFromPoint(centerX, centerY) as HTMLButtonElement | null;
const newActiveElement = el.shadowRoot!.elementFromPoint(
centerX,
centerY
) as HTMLIonPickerColumnOptionElement | null;
if (activeEl !== null) {
if (activeEl !== undefined) {
this.setPickerItemActiveState(activeEl, false);
}
if (activeElement === null || activeElement.disabled) {
/**
* This null check is important because activeEl
* can be undefined but newActiveElement can be
* null since we are using a querySelector.
* newActiveElement !== activeEl would return true
* below if newActiveElement was null but activeEl
* was undefined.
*/
if (newActiveElement === null || newActiveElement.disabled) {
return;
}
@@ -306,7 +317,7 @@ export class PickerColumn implements ComponentInterface {
* If we are selecting a new value,
* we need to run haptics again.
*/
if (activeElement !== activeEl) {
if (newActiveElement !== activeEl) {
enableHaptics && hapticSelectionChanged();
if (this.canExitInputMode) {
@@ -325,8 +336,8 @@ export class PickerColumn implements ComponentInterface {
}
}
activeEl = activeElement;
this.setPickerItemActiveState(activeElement, true);
activeEl = newActiveElement;
this.setPickerItemActiveState(newActiveElement, true);
timeout = setTimeout(() => {
this.isScrolling = false;
@@ -352,23 +363,7 @@ export class PickerColumn implements ComponentInterface {
*/
this.canExitInputMode = true;
const dataIndex = activeElement.getAttribute('data-index');
/**
* If no value it is
* possible we hit one of the
* empty padding columns.
*/
if (dataIndex === null) {
return;
}
const index = parseInt(dataIndex, 10);
const selectedItem = this.items[index];
if (selectedItem.value !== this.value) {
this.setValue(selectedItem.value);
}
this.setValue(newActiveElement.value);
}, 250);
});
};
@@ -412,15 +407,25 @@ export class PickerColumn implements ComponentInterface {
};
get activeItem() {
// If the whole picker column is disabled, the current value should appear active
// If the current value item is specifically disabled, it should not appear active
const selector = `.picker-item[data-value="${this.value}"]${this.disabled ? '' : ':not([disabled])'}`;
const { value } = this;
const options = Array.from(
this.el.querySelectorAll('ion-picker-column-option') as NodeListOf<HTMLIonPickerColumnOptionElement>
);
return options.find((option: HTMLIonPickerColumnOptionElement) => {
/**
* If the whole picker column is disabled, the current value should appear active
* If the current value item is specifically disabled, it should not appear active
*/
if (!this.disabled && option.disabled) {
return false;
}
return getElementRoot(this.el).querySelector(selector) as HTMLElement | null;
return option.value === value;
}) as HTMLIonPickerColumnOptionElement | undefined;
}
render() {
const { items, color, disabled: pickerDisabled, isActive, numericInput } = this;
const { color, disabled: pickerDisabled, isActive, numericInput } = this;
const mode = getIonMode(this);
/**
@@ -450,37 +455,7 @@ export class PickerColumn implements ComponentInterface {
<div class="picker-item picker-item-empty" aria-hidden="true">
&nbsp;
</div>
{items.map((item, index) => {
const isItemDisabled = pickerDisabled || item.disabled || false;
{
/*
Users should be able to tab
between multiple columns. As a result,
we set tabindex here so that tabbing switches
between columns instead of buttons. Users
can still use arrow keys on the keyboard to
navigate the column up and down.
*/
}
return (
<button
tabindex="-1"
class={{
'picker-item': true,
}}
data-value={item.value}
data-index={index}
onClick={(ev: Event) => {
this.centerPickerItemInView(ev.target as HTMLElement, true);
}}
disabled={isItemDisabled}
part={PICKER_ITEM_PART}
>
{item.text}
</button>
);
})}
<slot></slot>
<div class="picker-item picker-item-empty" aria-hidden="true">
&nbsp;
</div>
@@ -495,6 +470,6 @@ export class PickerColumn implements ComponentInterface {
}
}
const PICKER_ITEM_ACTIVE_CLASS = 'picker-item-active';
const PICKER_ITEM_ACTIVE_CLASS = 'option-active';
const PICKER_ITEM_PART = 'wheel-item';
const PICKER_ITEM_ACTIVE_PART = 'active';

View File

@@ -57,12 +57,18 @@
const items = Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
}));
.forEach((_, i) => {
const option = document.createElement('ion-picker-column-option');
option.value = i;
option.textContent = i;
defaultPickerColumn.items = items;
defaultPickerColumn.appendChild(option);
});
//defaultPickerColumn.value = 11;
defaultPickerColumn.addEventListener('ionChange', (ev) => {
console.log(ev);
})
</script>
</ion-app>
</body>

View File

@@ -10,18 +10,13 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await page.goto('/src/components/picker-column/test/basic', config);
});
test('should render a picker item for each item', async ({ page }) => {
const columns = page.locator('ion-picker-column .picker-item:not(.picker-item-empty)');
await expect(columns).toHaveCount(24);
});
test('should render 6 empty picker items', async ({ page }) => {
const columns = page.locator('ion-picker-column .picker-item-empty');
await expect(columns).toHaveCount(6);
});
test('should not have an active item when value is not set', async ({ page }) => {
const activeColumn = page.locator('ion-picker-column .picker-item-active');
const activeColumn = page.locator('ion-picker-column .option-active');
await expect(activeColumn).toHaveCount(0);
});
@@ -31,7 +26,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column .picker-item-active');
const activeColumn = page.locator('ion-picker-column .option-active');
expect(activeColumn).not.toBeNull();
});
@@ -45,9 +40,9 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column .picker-item-active');
const activeColumn = page.locator('ion-picker-column .option-active');
expect(await activeColumn?.innerText()).toEqual('23');
await expect(activeColumn).toHaveJSProperty('value', 23);
});
test('should not emit ionChange when the value is modified externally', async ({ page, skip }) => {

View File

@@ -53,31 +53,36 @@
<div class="grid-item">
<h2>Column disabled</h2>
<ion-picker>
<ion-picker-column id="column-disabled" value="11" disabled></ion-picker-column>
<ion-picker-column id="column-disabled" disabled="true"></ion-picker-column>
</ion-picker>
</div>
</div>
</ion-content>
<script>
const halfDisabledPicker = document.getElementById('half-disabled');
const halfDisabledItems = Array(24)
Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
disabled: i % 2 === 0,
}));
halfDisabledPicker.items = halfDisabledItems;
halfDisabledPicker.value = 12;
.forEach((_, i) => {
const option = document.createElement('ion-picker-column-option');
option.value = i;
option.textContent = i;
option.disabled = i % 2 === 0;
halfDisabledPicker.appendChild(option);
});
halfDisabledPicker.value = 4;
const fullDisabledPicker = document.getElementById('column-disabled');
const items = Array(24)
Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
}));
fullDisabledPicker.items = items;
.forEach((_, i) => {
const option = document.createElement('ion-picker-column-option');
option.value = i;
option.textContent = i;
fullDisabledPicker.appendChild(option);
});
fullDisabledPicker.value = 11;
</script>
</ion-app>
</body>

View File

@@ -1,36 +1,6 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This behavior does not vary across directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('picker-column: disabled rendering'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker>
<ion-picker-column value="b"></ion-picker-column>
</ion-picker>
<script>
const column = document.querySelector('ion-picker-column');
column.items = [
{ text: 'A', value: 'a', disabled: true },
{ text: 'B', value: 'b' },
{ text: 'C', value: 'c', disabled: true }
]
</script>
`,
config
);
const picker = page.locator('ion-picker');
await expect(picker).toHaveScreenshot(screenshot(`picker-disabled`));
});
});
});
/**
* This behavior does not vary across modes/directions.
*/

View File

@@ -1476,14 +1476,14 @@ export declare interface IonPickerColumn extends Components.IonPickerColumn {
@ProxyCmp({
inputs: ['disabled', 'value']
inputs: ['color', 'disabled', 'value']
})
@Component({
selector: 'ion-picker-column-option',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled', 'value'],
inputs: ['color', 'disabled', 'value'],
})
export class IonPickerColumnOption {
protected el: HTMLElement;

View File

@@ -1473,14 +1473,14 @@ export declare interface IonPickerColumn extends Components.IonPickerColumn {
@ProxyCmp({
defineCustomElementFn: defineIonPickerColumnOption,
inputs: ['disabled', 'value']
inputs: ['color', 'disabled', 'value']
})
@Component({
selector: 'ion-picker-column-option',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled', 'value'],
inputs: ['color', 'disabled', 'value'],
standalone: true
})
export class IonPickerColumnOption {

View File

@@ -589,7 +589,8 @@ export const IonPickerColumn = /*@__PURE__*/ defineContainer<JSX.IonPickerColumn
export const IonPickerColumnOption = /*@__PURE__*/ defineContainer<JSX.IonPickerColumnOption>('ion-picker-column-option', defineIonPickerColumnOption, [
'disabled',
'value'
'value',
'color'
]);