diff --git a/player/react/src/lib/components/index.ts b/player/react/src/lib/components/index.ts
index a94397b61..48cd0d611 100644
--- a/player/react/src/lib/components/index.ts
+++ b/player/react/src/lib/components/index.ts
@@ -20,6 +20,7 @@ import * as searchinput from './ui-search-input';
import * as text from './ui-text';
import * as textarea from './ui-text-area';
import * as textinput from './ui-text-input';
+import * as timepicker from './ui-time-picker';
import * as link from './ui-link';
import * as loading from './ui-loading';
import * as inlineLoading from './ui-inline-loading';
@@ -59,6 +60,7 @@ export const allComponents = {
text,
textarea,
textinput,
+ timepicker,
overflowMenu,
// Tiles
tile,
diff --git a/player/react/src/lib/components/ui-time-picker.tsx b/player/react/src/lib/components/ui-time-picker.tsx
new file mode 100644
index 000000000..e39c7a5f2
--- /dev/null
+++ b/player/react/src/lib/components/ui-time-picker.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import { TimePickerSelect, TimePicker, SelectItem } from '@carbon/react';
+import { commonSlots, slotsDisabled } from '../common-slots';
+import { SendSignal } from '../types';
+
+export interface TimePickerState {
+ id: string | number;
+ codeContext?: {
+ name: string;
+ };
+ type: string;
+ placeholder: string;
+ disabled?: boolean;
+ invalid?: boolean;
+ invalidText?: string;
+ light?: boolean;
+ size?: string;
+ value?: string;
+ label?: string;
+ timezones?: [];
+ isShowTimePeriod?: boolean;
+ timePeriod?: [];
+}
+
+export const type = 'time-picker';
+
+export const signals = ['valueChange', 'click', 'timezoneValueChange', 'timePeriodValueChange'];
+
+export const slots = {
+ ...commonSlots,
+ ...slotsDisabled,
+ invalid: 'boolean',
+ setInvalid: (state: TimePickerState) => ({
+ ...state,
+ invalid: true
+ }),
+ setValid: (state: TimePickerState) => ({
+ ...state,
+ invalid: false
+ }),
+ toggleInvalid: (state: TimePickerState) => ({
+ ...state,
+ invalid: !state.invalid
+ }),
+ light: 'boolean',
+ setLight: (state: TimePickerState) => ({
+ ...state,
+ light: true
+ }),
+ setDark: (state: TimePickerState) => ({
+ ...state,
+ light: false
+ }),
+ toggleLight: (state: TimePickerState) => ({
+ ...state,
+ light: !state.light
+ }),
+ placeholder: 'string',
+ type: 'string',
+ invalidText: 'string',
+ label: 'string',
+ size: 'string',
+ value: 'string'
+};
+
+export const UITimePicker = ({ state, sendSignal }: {
+ state: TimePickerState;
+ setState: (state: any) => void;
+ setGlobalState: (state: any) => void;
+ sendSignal: SendSignal;
+}) => {
+ if (state.type !== 'time-picker') {
+ // eslint-disable-next-line react/jsx-no-useless-fragment
+ return <>>;
+ }
+
+ return {
+ sendSignal(state.id, 'click');
+ }}
+ onChange={(event: any) => {
+ sendSignal(state.id, 'valueChange', [event.value], { ...state, value: event.value });
+ }}>
+ {state.isShowTimePeriod &&
+ {
+ sendSignal(state.id, 'timePeriodValueChange', [event.value], { ...state, value: event.value });
+ }}>
+
+
+
+ }
+ {state.timezones?.length &&
+ {
+ sendSignal(state.id, 'timezoneValueChange', [event.value], { ...state, value: event.value });
+ }}>
+ {
+ state.timezones.map((step: any, index: number) =>
+ )
+ }
+
+ }
+ ;
+};
diff --git a/player/react/src/lib/utils.tsx b/player/react/src/lib/utils.tsx
index 7c335518a..eea35a319 100644
--- a/player/react/src/lib/utils.tsx
+++ b/player/react/src/lib/utils.tsx
@@ -33,6 +33,7 @@ import { UITextAreaInput } from './components/ui-text-area';
import { UITextInput } from './components/ui-text-input';
import { UITile } from './components/ui-tile';
import { UITileFold } from './components/ui-tile-fold';
+import { UITimePicker } from './components/ui-time-picker';
import { UIToggle } from './components/ui-toggle';
import { kebabCase } from 'lodash';
import { SendSignal } from './types';
@@ -283,6 +284,9 @@ export const renderComponents = (
case 'text-input':
return ;
+ case 'time-picker':
+ return ;
+
case 'overflow-menu':
return ;
diff --git a/sdk/react/src/lib/assets/component-icons/time-picker.svg b/sdk/react/src/lib/assets/component-icons/time-picker.svg
new file mode 100644
index 000000000..68d9ebc69
--- /dev/null
+++ b/sdk/react/src/lib/assets/component-icons/time-picker.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/sdk/react/src/lib/fragment-components/a-time-picker.tsx b/sdk/react/src/lib/fragment-components/a-time-picker.tsx
new file mode 100644
index 000000000..4e101c185
--- /dev/null
+++ b/sdk/react/src/lib/fragment-components/a-time-picker.tsx
@@ -0,0 +1,487 @@
+import React from 'react';
+import { AComponent, ComponentInfo } from './a-component';
+import image from './../assets/component-icons/time-picker.svg';
+import { TextInput, Checkbox, Dropdown, TimePicker, TimePickerSelect, SelectItem } from '@carbon/react';
+import { DraggableTileList, angularClassNamesFromComponentObj, nameStringToVariableString, reactClassNamesFromComponentObj } from '../helpers';
+import { css, cx } from 'emotion';
+import { styleObjectToString } from '@carbon-builder/player-react';
+
+const preventCheckEventStyle = css`
+ pointer-events: none;
+`;
+
+export const ATimePickerSettingsUI = ({ selectedComponent, setComponent }: any) => {
+ const size = [
+ { id: 'sm', text: 'Small' },
+ { id: 'md', text: 'Medium' },
+ { id: 'lg', text: 'Large' }
+ ];
+
+ const updateListItems = (key: string, value: any, index: number) => {
+ const step = {
+ ...selectedComponent.timezones[index],
+ [key]: value
+ };
+ setComponent({
+ ...selectedComponent,
+ timezones: [
+ ...selectedComponent.timezones.slice(0, index),
+ step,
+ ...selectedComponent.timezones.slice(index + 1)
+ ]
+ });
+ };
+
+ const template = (item: any, index: number) => {
+ return <>
+ {
+ updateListItems('text', event.currentTarget.value, index);
+ }} />
+ {
+ updateListItems('value', event.currentTarget.value, index);
+ }} />
+ {
+ updateListItems('selected', checked, index);
+ }} />
+ >;
+ };
+
+ const updateStepList = (newList: any[]) => {
+ setComponent({
+ ...selectedComponent,
+ timezones: newList
+ });
+ };
+ return <>
+ setComponent({
+ ...selectedComponent,
+ isShowTimePeriod: checked
+ })} />
+ setComponent({
+ ...selectedComponent,
+ light: checked
+ })} />
+ setComponent({
+ ...selectedComponent,
+ disabled: checked
+ })} />
+ setComponent({
+ ...selectedComponent,
+ hideLabel: checked
+ })} />
+ setComponent({
+ ...selectedComponent,
+ invalid: checked
+ })} />
+ item.id === selectedComponent.size)}
+ itemToString={(item: any) => (item ? item.text : '')}
+ onChange={(event: any) => setComponent({
+ ...selectedComponent,
+ size: event.selectedItem.id
+ })} />
+ setComponent({
+ ...selectedComponent,
+ label: event.currentTarget.value
+ })} />
+ setComponent({
+ ...selectedComponent,
+ invalidText: event.currentTarget.value
+ })} />
+ setComponent({
+ ...selectedComponent,
+ placeholder: event.currentTarget.value
+ })} />
+
+ >;
+};
+
+export const ATimePickerCodeUI = ({ selectedComponent, setComponent }: any) => setComponent({
+ ...selectedComponent,
+ codeContext: {
+ ...selectedComponent.codeContext,
+ name: event.currentTarget.value
+ }
+ })}
+/>;
+
+export const ATimePicker = ({
+ componentObj,
+ ...rest
+}: any) => {
+ return (
+
+ {
+ cc.id).join(' '),
+ css`${styleObjectToString(componentObj.style)}`
+ )}
+ disabled={componentObj.disabled}
+ invalid={componentObj.invalid}
+ invalidText={componentObj.invalidText}
+ placeholder={componentObj.placeholder}
+ hideLabel={componentObj.hideLabel}
+ labelText={componentObj.label}
+ light={componentObj.light}
+ size={componentObj.size}>
+ {componentObj.isShowTimePeriod &&
+
+ {
+ componentObj.timePeriod.map((step: any, index: number) =>
+ )
+ }
+
+ }
+ {componentObj.timezones.length > 0 &&
+
+ {
+ componentObj.timezones.map((step: any, index: number) =>
+ )
+ }
+
+ }
+
+ }
+
+ );
+};
+
+export const componentInfo: ComponentInfo = {
+ component: ATimePicker,
+ settingsUI: ATimePickerSettingsUI,
+ codeUI: ATimePickerCodeUI,
+ keywords: ['timepicker', 'time', 'picker'],
+ name: 'Time Picker',
+ type: 'time-picker',
+ defaultComponentObj: {
+ type: 'time-picker',
+ invalidText: 'A valid value is required',
+ placeholder: 'hh:mm',
+ label: 'Select a time',
+ isShowTimePeriod: false,
+ timePeriod: [
+ {
+ value:'AM',
+ text:'AM',
+ selected: true
+ },
+ {
+ value:'PM',
+ text:'PM',
+ selected: false
+ }
+ ],
+ value: '',
+ timezones: []
+ },
+ image,
+ codeExport: {
+ angular: {
+ latest: {
+ inputs: ({ json }) => `@Input() ${nameStringToVariableString(json.codeContext?.name)}Value = "${json.value}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Label = "${json.label}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Theme: "light" | "dark" = "${json.light ? 'light' : 'dark'}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsInvalid = ${json.invalid ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Placeholder = "${json.placeholder}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Size: "sm" | "md" | "lg" = "${json.size ?? 'md'}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}HideLabel = ${json.hideLabel ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}InvalidText = "${json.invalidText}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsDisabled = ${json.disabled ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsShowTimePeriod = ${json.isShowTimePeriod ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}TimePeriod: {value: string; text: string; selected: boolean}[]
+ = ${JSON.stringify(json.timePeriod)};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Timezones: {value: string; text: string; selected: boolean}[]
+ = ${JSON.stringify(json.timezones)}`,
+ outputs: ({ json }) => `@Output() ${nameStringToVariableString(json.codeContext?.name)}ValueChange = new EventEmitter();
+ @Output() ${nameStringToVariableString(json.codeContext?.name)}TimeperiodChange = new EventEmitter();
+ @Output() ${nameStringToVariableString(json.codeContext?.name)}TimezoneChange = new EventEmitter();`,
+ imports: ['TimePickerModule', 'TimePickerSelectModule'],
+ code: ({ json }) => {
+ return `
+
+
+
+
+
+
+ `;
+ }
+ },
+ v10: {
+ inputs: ({ json }) => `@Input() ${nameStringToVariableString(json.codeContext?.name)}Value = "${json.value}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Label = "${json.label}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Theme: "light" | "dark" = "${json.light ? 'light' : 'dark'}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsInvalid = ${json.invalid ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Placeholder = "${json.placeholder}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Size: "sm" | "md" | "lg" = "${json.size ?? 'md'}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}HideLabel = ${json.hideLabel ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}InvalidText = "${json.invalidText}";
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsDisabled = ${json.disabled ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}IsShowTimePeriod = ${json.isShowTimePeriod ?? false};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}TimePeriod: {value: string; text: string; selected: boolean}[]
+ = ${JSON.stringify(json.timePeriod)};
+ @Input() ${nameStringToVariableString(json.codeContext?.name)}Timezones: {value: string; text: string; selected: boolean}[]
+ = ${JSON.stringify(json.timezones)}`,
+ outputs: ({ json }) => `@Output() ${nameStringToVariableString(json.codeContext?.name)}ValueChange = new EventEmitter();
+ @Output() ${nameStringToVariableString(json.codeContext?.name)}TimeperiodChange = new EventEmitter();
+ @Output() ${nameStringToVariableString(json.codeContext?.name)}TimezoneChange = new EventEmitter();`,
+ imports: ['TimePickerModule', 'TimePickerSelectModule'],
+ code: ({ json }) => {
+ return `
+ >
+
+
+
+
+
+ `;
+ }
+ }
+ },
+ react: {
+ latest: {
+ imports: ({ json }) => ['TimePicker',
+ ...((json.timePeriod && json.isShowTimePeriod) || json.timezones.length ? ['TimePickerSelect', 'SelectItem'] : [])],
+ code: ({ json }) => {
+ return ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}",
+ value: event.target.value
+ }
+ })}>
+ ${(json.timePeriod && json.isShowTimePeriod) ?
+ ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}TimeZone",
+ value: event.target.value
+ }
+ })}>
+ ${json.timePeriod.map((step: any) => (``
+ )).join('\n')}
+ ` : ''
+ }
+ ${json.timezones.length ?
+ ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}TimeZone",
+ value: event.target.value
+ }
+ })}>
+ ${json.timezones.map((step: any) => (``
+ )).join('\n')}
+ ` : ''
+ }
+ `;
+ }
+ },
+ v10: {
+ imports: ({ json }) => ['TimePicker',
+ ...((json.timePeriod && json.isShowTimePeriod) || json.timezones.length ? ['TimePickerSelect', 'SelectItem'] : [])],
+ code: ({ json }) => {
+ return ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}",
+ value: event.target.value
+ }
+ })}>
+ ${(json.timePeriod && json.isShowTimePeriod) ?
+ ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}TimeZone",
+ value: event.target.value
+ }
+ })}>
+ ${json.timePeriod.map((step: any) => (``
+ )).join('\n')}
+ ` : ''
+ }
+ ${json.timezones.length ?
+ ` handleInputChange({
+ target: {
+ name: "${json.codeContext?.name}TimeZone",
+ value: event.target.value
+ }
+ })}>
+ ${json.timezones.map((step: any) => (``
+ )).join('\n')}
+ ` : ''
+ }
+ `;
+ }
+ }
+ }
+ }
+};
diff --git a/sdk/react/src/lib/fragment-components/index.ts b/sdk/react/src/lib/fragment-components/index.ts
index e4308a3fe..a570ec40e 100644
--- a/sdk/react/src/lib/fragment-components/index.ts
+++ b/sdk/react/src/lib/fragment-components/index.ts
@@ -21,6 +21,7 @@ import * as searchinput from './a-searchinput';
import * as text from './a-text';
import * as textarea from './a-text-area';
import * as textinput from './a-text-input';
+import * as timepicker from './a-time-picker';
import * as link from './a-link';
import * as loading from './a-loading';
import * as inlineLoading from './a-inline-loading';
@@ -60,6 +61,7 @@ export { ATag, ATagCodeUI, ATagSettingsUI } from './a-tag';
export { AText, ATextCodeUI, ATextSettingsUI } from './a-text';
export { ATextArea, ATextAreaSettingsUI, ATextAreaCodeUI } from './a-text-area';
export { ATextInput, ATextInputSettingsUI, ATextInputCodeUI } from './a-text-input';
+export { ATimePicker, ATimePickerSettingsUI, ATimePickerCodeUI } from './a-time-picker';
export { AOverflowMenu, AOverflowMenuCodeUI, AOverflowMenuSettingsUI } from './a-overflow-menu';
export { ARadio, ARadioSettingsUI, ARadioCodeUI } from './a-radio';
export { ARadioGroup, ARadioGroupSettingsUI, ARadioGroupCodeUI } from './a-radio-group';
@@ -101,6 +103,7 @@ export const allComponents = {
text,
textarea,
textinput,
+ timepicker,
overflowMenu,
// Tiles
tile,
diff --git a/sdk/react/src/lib/helpers/tools.ts b/sdk/react/src/lib/helpers/tools.ts
index d91d708ee..727f794a3 100644
--- a/sdk/react/src/lib/helpers/tools.ts
+++ b/sdk/react/src/lib/helpers/tools.ts
@@ -146,7 +146,7 @@ export const getUsedCollectionsStyleUrls = (collections: any[], componentObj: an
}
return collections
- .filter((collection) => usedCollectionsNames.includes(collection.name))
+ ?.filter((collection) => usedCollectionsNames.includes(collection.name))
.flatMap((collection) => collection.styleUrls);
};